NextGEN Gallery – WordPress Gallery Plugin - Version 2.0.57

Version Description

  • 03.05.2013 =
  • NEW: Re-introduced the Reset button
  • NEW: Tooltip added for Page Link to functionality
  • NEW: Displayed Gallery Triggers moved from NextGEN Pro to NextGEN Gallery (not in use)
  • NEW: Added NGG_Store, a client-side persistence layer (not in use)
  • NEW: Added NGG_CRON_SCHEDULE constant. Set to the number of seconds between the execution of NextGEN Gallery cron jobs
  • NEW: Added NGG_RENDERING_CACHE_TTL constant. TTL measured in seconds.
  • NEW: Added NGG_DISPLAYED_GALLERY_CACHE_TTL constant. TTL measured in seconds.
  • NEW: Added NGG_DISABLE_LEGACY_SHORTCODES constant. When TRUE, [slideshow] becomes [nggslideshow].
  • NEW: Added Font Awesome, available for NextGEN Gallery extensions
  • Changed: Transients are removed every 30 minutes instead of 60 minutes
  • Changed: Admin Page & Form components refactored to allow custom POST processing
  • Changed: Default path for NEW multisite installations to wp-content/uploads/sites/%BLOG_ID%/nggallery/
  • Fixed: Ability to upload ZIP files on Windows hosts
  • Fixed: Support for filenames with non-ASCII characters
  • Fixed: Dynamic updates in the Attach to Post interface (interframe communication)
  • Fixed: Attach to Post interface freezing in IE11
  • Fixed: Path issues on Windows Servers
  • Fixed: Module installer integrity
  • Fixed: Database query performance. No more joins to the WP options table
  • Fixed: Lightboxes storing absolute paths for static resources
  • Fixed: Displayed gallery cache not regularly flushed
  • Fixed: SQL query performance problems. Honor max_packet_allowed variable for MySQL
  • Fixed: Multiple database queries generated for determining next available image slug
  • Fixed: Corrupted MediaRSS feeds
  • Fixed: Padding on Gallery Settings and Other Options pages
  • Fixed: Routing issues on subdirectory installs
  • Fixed: Importing galleries using the Attach to Post Interface
  • Fixed: Gallery path calculations on Windows web servers
  • Fixed: Sub-album urls not processed correctly
  • Fixed: Apply maximum entity count to existing displayed galleries
  • Fixed: NextGEN Gallery Thumbnail Widget shouldn't use ImageBrowser effect
  • Fixed: Ability to set shuffle parameter for ImageRotator slideshows
  • Fixed: PHP warning about HTMLDocument when displaying a SinglePic
  • Fixed: Sanitization of gallery title
  • Fixed: Home URL now used instead of Site URL in MediaRSS feed
  • Fixed: Attach to Post interface broken when WPML is installed
  • Fixed: Attach to Post interface instructing browser to cache the page
  • Fixed: Watermarking not working in low-memory environments
  • Fixed: Maximum images limit not being applied for galleries already created.
  • Fixed: Double forward slashes in static urls
  • Fixed: Don't sleep when checking if the installer is running
  • Fixed: Don't enforce Pope interface contracts
  • Fixed: Remove custom table extra records from wp_options table
  • Fixed: Scan folder for new images not working
  • Fixed: Incorrect page permalink used for "Page Link To" functionality
  • Fixed: Pagination broken when Basic Thumbnail gallery on the same page as Basic Album
  • Fixed: parse_url() warnings generated for PHP 5.3.3 and earlier
  • Fixed: Compatibility with Headway Themes
  • Fixed: Compatibility with web servers which don't provide PHP a document root
  • Fixed: Third-party incompatibilities caused by the Photocrati Resource Manager
  • Fixed: Compatibility with the Flattr plugin
  • Fixed: Compatibility with the Weaver II theme
  • Fixed: Interface tweaks for WordPress 3.8
Download this release

Release Info

Developer photocrati
Plugin Icon 128x128 NextGEN Gallery – WordPress Gallery Plugin
Version 2.0.57
Comparing to
See all releases

Code changes from version 2.0.0 to 2.0.57

Files changed (168) hide show
  1. changelog.txt +243 -0
  2. nggallery.php +291 -49
  3. non_pope/class.nextgen_settings.php +12 -8
  4. non_pope/class.nextgen_shortcode_manager.php +148 -0
  5. non_pope/class.nextgen_style_manager.php +280 -0
  6. non_pope/class.photocrati_cache.php +101 -15
  7. non_pope/class.photocrati_installer.php +130 -9
  8. non_pope/class.photocrati_resource_manager.php +213 -0
  9. non_pope/class.photocrati_settings_manager.php +54 -5
  10. pope/lib/autoload.php +1 -1
  11. pope/lib/class.base_module.php +2 -2
  12. pope/lib/class.base_product.php +2 -2
  13. pope/lib/class.component_factory.php +2 -2
  14. pope/lib/class.extensibleobject.php +47 -5
  15. products/photocrati_nextgen/modules/ajax/class.ajax_controller.php +10 -10
  16. products/photocrati_nextgen/modules/ajax/class.ajax_installer.php +5 -22
  17. products/photocrati_nextgen/modules/ajax/class.ajax_option_handler.php +29 -0
  18. products/photocrati_nextgen/modules/ajax/module.ajax.php +22 -9
  19. products/photocrati_nextgen/modules/ajax/static/ngg_store.js +42 -0
  20. products/photocrati_nextgen/modules/ajax/static/persist.js +145 -0
  21. products/photocrati_nextgen/modules/ajax/static/persist.swf +0 -0
  22. products/photocrati_nextgen/modules/ajax/static/store.js +2 -0
  23. products/photocrati_nextgen/modules/attach_to_post/adapter.attach_to_post_ajax.php +3 -3
  24. products/photocrati_nextgen/modules/attach_to_post/adapter.gallery_storage_frame_event.php +14 -6
  25. products/photocrati_nextgen/modules/attach_to_post/class.attach_controller.php +82 -11
  26. products/photocrati_nextgen/modules/attach_to_post/class.attach_to_post_installer.php +5 -26
  27. products/photocrati_nextgen/modules/attach_to_post/class.attach_to_post_option_handler.php +28 -0
  28. products/photocrati_nextgen/modules/attach_to_post/mixin.attach_to_post_display_tab.php +19 -6
  29. products/photocrati_nextgen/modules/attach_to_post/module.attach_to_post.php +79 -81
  30. products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.js +19 -21
  31. products/photocrati_nextgen/modules/attach_to_post/static/iframely.css +6 -1
  32. products/photocrati_nextgen/modules/attach_to_post/static/iframely.js +50 -10
  33. products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.js +6 -3
  34. products/photocrati_nextgen/modules/attach_to_post/templates/display_tab_js.php +43 -5
  35. products/photocrati_nextgen/modules/cache/class.cache.php +2 -2
  36. products/photocrati_nextgen/modules/cache/module.cache.php +1 -1
  37. products/photocrati_nextgen/modules/datamapper/class.custompost_datamapper_driver.php +44 -22
  38. products/photocrati_nextgen/modules/datamapper/class.customtable_datamapper_driver.php +47 -58
  39. products/photocrati_nextgen/modules/datamapper/class.datamapper_driver_base.php +171 -33
  40. products/photocrati_nextgen/modules/datamapper/class.datamapper_installer.php +1 -1
  41. products/photocrati_nextgen/modules/datamapper/class.datamapper_model.php +11 -11
  42. products/photocrati_nextgen/modules/datamapper/module.datamapper.php +32 -13
  43. products/photocrati_nextgen/modules/dynamic_stylesheet/class.dynamic_stylesheet_controller.php +3 -3
  44. products/photocrati_nextgen/modules/dynamic_stylesheet/class.dynamic_stylesheet_installer.php +1 -1
  45. products/photocrati_nextgen/modules/dynamic_stylesheet/module.dynamic_stylesheet.php +1 -1
  46. products/photocrati_nextgen/modules/dynamic_thumbnails/adapter.dynamic_thumbnails_storage_driver.php +15 -6
  47. products/photocrati_nextgen/modules/dynamic_thumbnails/class.dynamic_thumbnails_installer.php +1 -1
  48. products/photocrati_nextgen/modules/dynamic_thumbnails/class.dynamic_thumbnails_manager.php +1 -1
  49. products/photocrati_nextgen/modules/dynamic_thumbnails/module.dynamic_thumbnails.php +1 -1
  50. products/photocrati_nextgen/modules/frame_communication/class.frame_communication_installer.php +1 -1
  51. products/photocrati_nextgen/modules/frame_communication/class.frame_event_publisher.php +10 -2
  52. products/photocrati_nextgen/modules/frame_communication/module.frame_communication.php +5 -3
  53. products/photocrati_nextgen/modules/fs/class.fs.php +36 -20
  54. products/photocrati_nextgen/modules/fs/module.fs.php +1 -1
  55. products/photocrati_nextgen/modules/lightbox/adapter.lightbox_factory.php +4 -4
  56. products/photocrati_nextgen/modules/lightbox/adapter.lightbox_library_form.php +4 -4
  57. products/photocrati_nextgen/modules/lightbox/class.lightbox_installer.php +175 -156
  58. products/photocrati_nextgen/modules/lightbox/class.lightbox_library.php +12 -1
  59. products/photocrati_nextgen/modules/lightbox/class.lightbox_library_mapper.php +1 -1
  60. products/photocrati_nextgen/modules/lightbox/module.lightbox.php +239 -10
  61. products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.css +3 -1
  62. products/photocrati_nextgen/modules/lightbox/static/fancybox/nextgen_fancybox_init.js +13 -7
  63. products/photocrati_nextgen/modules/lightbox/static/highslide/nextgen_highslide_init.js +41 -20
  64. products/photocrati_nextgen/modules/lightbox/static/jquery.lightbox/nextgen_lightbox_init.js +21 -11
  65. products/photocrati_nextgen/modules/lightbox/static/lightbox_context.js +27 -0
  66. products/photocrati_nextgen/modules/lightbox/static/shutter/nextgen_shutter.js +16 -10
  67. products/photocrati_nextgen/modules/lightbox/static/shutter_reloaded/nextgen_shutter_reloaded.js +9 -8
  68. products/photocrati_nextgen/modules/lightbox/static/thickbox/nextgen_thickbox_init.js +7 -2
  69. products/photocrati_nextgen/modules/mediarss/class.mediarss_controller.php +6 -6
  70. products/photocrati_nextgen/modules/mediarss/module.mediarss.php +1 -1
  71. products/photocrati_nextgen/modules/mediarss/templates/mediarss_feed.php +6 -6
  72. products/photocrati_nextgen/modules/mediarss/templates/playlist_feed.php +4 -4
  73. products/photocrati_nextgen/modules/mvc/adapter.mvc_fs.php +1 -1
  74. products/photocrati_nextgen/modules/mvc/adapter.mvc_router.php +5 -5
  75. products/photocrati_nextgen/modules/mvc/class.mvc_controller.php +2 -2
  76. products/photocrati_nextgen/modules/mvc/class.mvc_installer.php +2 -3
  77. products/photocrati_nextgen/modules/mvc/class.mvc_option_handler.php +9 -0
  78. products/photocrati_nextgen/modules/mvc/class.mvc_view.php +3 -3
  79. products/photocrati_nextgen/modules/mvc/module.mvc.php +7 -2
  80. products/photocrati_nextgen/modules/mvc/template_helper.php +20 -2
  81. products/photocrati_nextgen/modules/mvc/templates/index.php +2 -2
  82. products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.nextgen_addgallery_ajax.php +30 -21
  83. products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.nextgen_addgallery_forms.php +7 -9
  84. products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.nextgen_addgallery_pages.php +6 -7
  85. products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.upload_images_form.php +10 -6
  86. products/photocrati_nextgen/modules/nextgen_addgallery_page/module.nextgen_addgallery_page.php +7 -5
  87. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/jquery.filetree/connectors/jqueryFileTree.php +0 -36
  88. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/Moxie.swf +0 -0
  89. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/Moxie.xap +0 -0
  90. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ar.js +2 -0
  91. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/bs.js +2 -0
  92. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ca.js +2 -0
  93. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cs.js +2 -0
  94. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cy.js +2 -0
  95. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/da.js +2 -0
  96. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/de.js +2 -0
  97. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/el.js +2 -0
  98. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/en.js +2 -0
  99. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/es.js +2 -0
  100. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/et.js +2 -0
  101. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fa.js +2 -0
  102. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fi.js +2 -0
  103. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fr.js +2 -0
  104. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/he.js +2 -0
  105. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hr.js +2 -0
  106. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hu.js +2 -0
  107. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hy.js +2 -0
  108. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/id.js +2 -0
  109. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/it.js +2 -0
  110. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ja.js +2 -0
  111. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ka.js +2 -0
  112. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/kk.js +2 -0
  113. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ko.js +2 -0
  114. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lt.js +2 -0
  115. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lv.js +2 -0
  116. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/nl.js +2 -0
  117. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pl.js +2 -0
  118. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pt_BR.js +2 -0
  119. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ro.js +2 -0
  120. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ru.js +2 -0
  121. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sk.js +2 -0
  122. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sr.js +2 -0
  123. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sv.js +2 -0
  124. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/th_TH.js +2 -0
  125. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/tr.js +2 -0
  126. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/uk_UA.js +2 -0
  127. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_CN.js +2 -0
  128. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_TW.js +2 -0
  129. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/css/jquery.plupload.queue.css +181 -0
  130. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/backgrounds.gif +0 -0
  131. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/buttons-disabled.png +0 -0
  132. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/buttons.png +0 -0
  133. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/delete.gif +0 -0
  134. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/done.gif +0 -0
  135. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/error.gif +0 -0
  136. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/throbber.gif +0 -0
  137. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/transp50.png +0 -0
  138. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/jquery.plupload.queue.js +424 -0
  139. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/jquery.plupload.queue.min.js +1 -0
  140. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/css/jquery.ui.plupload.css +362 -0
  141. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/img/loading.gif +0 -0
  142. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/img/plupload.png +0 -0
  143. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/jquery.ui.plupload.js +1307 -0
  144. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/jquery.ui.plupload.min.js +1 -0
  145. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/moxie.js +10684 -0
  146. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/moxie.min.js +15 -0
  147. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/plupload.dev.js +2273 -0
  148. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/plupload.full.min.js +28 -0
  149. products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/plupload.min.js +13 -0
  150. products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/import_folder.php +6 -5
  151. products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/upload_images.php +63 -36
  152. products/photocrati_nextgen/modules/nextgen_admin/adapter.nextgen_admin_default_pages.php +5 -3
  153. products/photocrati_nextgen/modules/nextgen_admin/class.form.php +36 -15
  154. products/photocrati_nextgen/modules/nextgen_admin/class.nextgen_admin_installer.php +23 -15
  155. products/photocrati_nextgen/modules/nextgen_admin/class.nextgen_admin_option_handler.php +29 -0
  156. products/photocrati_nextgen/modules/nextgen_admin/class.nextgen_admin_page_controller.php +30 -9
  157. products/photocrati_nextgen/modules/nextgen_admin/class.page_manager.php +55 -21
  158. products/photocrati_nextgen/modules/nextgen_admin/module.nextgen_admin.php +12 -6
  159. products/photocrati_nextgen/modules/nextgen_admin/static/jquery-ui/jquery-ui-1.9.1.custom.css +5 -0
  160. products/photocrati_nextgen/modules/nextgen_admin/static/nextgen_admin_page.css +16 -1
  161. products/photocrati_nextgen/modules/nextgen_admin/static/nextgen_admin_page.js +2 -8
  162. products/photocrati_nextgen/modules/nextgen_admin/templates/field_generator/nextgen_settings_field_color.php +1 -2
  163. products/photocrati_nextgen/modules/nextgen_admin/templates/field_generator/thumbnail_settings.php +1 -1
  164. products/photocrati_nextgen/modules/nextgen_admin/templates/nextgen_admin_page.php +1 -1
  165. products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album.php +3 -3
  166. products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album_controller.php +73 -54
  167. products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album_forms.php +4 -4
  168. products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album_mapper.php +13 -5
changelog.txt CHANGED
@@ -1,6 +1,249 @@
1
  NextGEN Gallery
2
  by Photocrati Media
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  = V2.0 - 07.30.2013 =
5
  * NEW: Improved user experience throughout the plugin, settings and usage.
6
  * NEW: Plupload queue uploader that allows for bulk and zip uploads within the same interface.
1
  NextGEN Gallery
2
  by Photocrati Media
3
 
4
+ = V2.0.57 - 03.05.2013 =
5
+ * NEW: Re-introduced the Reset button
6
+ * NEW: Tooltip added for Page Link to functionality
7
+ * NEW: Displayed Gallery Triggers moved from NextGEN Pro to NextGEN Gallery (not in use)
8
+ * NEW: Added NGG_Store, a client-side persistence layer (not in use)
9
+ * NEW: Added NGG_CRON_SCHEDULE constant. Set to the number of seconds between the execution of NextGEN Gallery cron jobs
10
+ * NEW: Added NGG_RENDERING_CACHE_TTL constant. TTL measured in seconds.
11
+ * NEW: Added NGG_DISPLAYED_GALLERY_CACHE_TTL constant. TTL measured in seconds.
12
+ * NEW: Added NGG_DISABLE_LEGACY_SHORTCODES constant. When TRUE, [slideshow] becomes [nggslideshow].
13
+ * NEW: Added Font Awesome, available for NextGEN Gallery extensions
14
+ * Changed: Transients are removed every 30 minutes instead of 60 minutes
15
+ * Changed: Admin Page & Form components refactored to allow custom POST processing
16
+ * Changed: Default path for NEW multisite installations to wp-content/uploads/sites/%BLOG_ID%/nggallery/
17
+ * Fixed: Ability to upload ZIP files on Windows hosts
18
+ * Fixed: Support for filenames with non-ASCII characters
19
+ * Fixed: Dynamic updates in the Attach to Post interface (interframe communication)
20
+ * Fixed: Attach to Post interface freezing in IE11
21
+ * Fixed: Path issues on Windows Servers
22
+ * Fixed: Module installer integrity
23
+ * Fixed: Database query performance. No more joins to the WP options table
24
+ * Fixed: Lightboxes storing absolute paths for static resources
25
+ * Fixed: Displayed gallery cache not regularly flushed
26
+ * Fixed: SQL query performance problems. Honor max_packet_allowed variable for MySQL
27
+ * Fixed: Multiple database queries generated for determining next available image slug
28
+ * Fixed: Corrupted MediaRSS feeds
29
+ * Fixed: Padding on Gallery Settings and Other Options pages
30
+ * Fixed: Routing issues on subdirectory installs
31
+ * Fixed: Importing galleries using the Attach to Post Interface
32
+ * Fixed: Gallery path calculations on Windows web servers
33
+ * Fixed: Sub-album urls not processed correctly
34
+ * Fixed: Apply maximum entity count to existing displayed galleries
35
+ * Fixed: NextGEN Gallery Thumbnail Widget shouldn't use ImageBrowser effect
36
+ * Fixed: Ability to set shuffle parameter for ImageRotator slideshows
37
+ * Fixed: PHP warning about HTMLDocument when displaying a SinglePic
38
+ * Fixed: Sanitization of gallery title
39
+ * Fixed: Home URL now used instead of Site URL in MediaRSS feed
40
+ * Fixed: Attach to Post interface broken when WPML is installed
41
+ * Fixed: Attach to Post interface instructing browser to cache the page
42
+ * Fixed: Watermarking not working in low-memory environments
43
+ * Fixed: Maximum images limit not being applied for galleries already created.
44
+ * Fixed: Double forward slashes in static urls
45
+ * Fixed: Don't sleep when checking if the installer is running
46
+ * Fixed: Don't enforce Pope interface contracts
47
+ * Fixed: Remove custom table extra records from wp_options table
48
+ * Fixed: Scan folder for new images not working
49
+ * Fixed: Incorrect page permalink used for "Page Link To" functionality
50
+ * Fixed: Pagination broken when Basic Thumbnail gallery on the same page as Basic Album
51
+ * Fixed: parse_url() warnings generated for PHP 5.3.3 and earlier
52
+ * Fixed: Compatibility with Headway Themes
53
+ * Fixed: Compatibility with web servers which don't provide PHP a document root
54
+ * Fixed: Third-party incompatibilities caused by the Photocrati Resource Manager
55
+ * Fixed: Compatibility with the Flattr plugin
56
+ * Fixed: Compatibility with the Weaver II theme
57
+ * Fixed: Interface tweaks for WordPress 3.8
58
+
59
+ = V2.0.40 - 11.26.2013 =
60
+ * NEW: Added the ability to apply lightbox effects to non-NGG images
61
+ * NEW: Added NGG_HIDE_STRICT_ERRORS constant. Define and set to TRUE to hide strict errors
62
+ * NEW: Added NEXTGEN_GALLERY_IMPORT_ROOT constant. Define and set to TRUE to browse from a custom directory
63
+ * NEW: Added NGG_DEBUG constant. Define and set to TRUE to display helpful messages for debugging
64
+ * NEW: Each custom table record will have an associated custom post record for expansion
65
+ * NEW: Display helpful error messages when there's a problem uploading images
66
+ * NEW: Add data-(src|thumbnail|image-id|title|description) attribute to gallery image anchors
67
+ * NEW: Variant support for displayed gallery sources. Random images is limited to 5 variations
68
+ * Fixed: Excessive creation of transients for random galleries
69
+ * Fixed: Many issues prohibiting the ability to upload images
70
+ * Fixed: Compatibility with NextGEN Gallery Export Plugin for Adobe Lightroom (thanks Vladimir!)
71
+ * Fixed: Sorting in the Attach to Post interface
72
+ * Fixed: HTML allowed in gallery/album descriptions
73
+ * Fixed: Requests for galleries within albums that have numeric names are broken
74
+ * Fixed: Call to a non-member function get() on WP_Query
75
+ * Fixed: Ability to sort by Image ID in the Attach to Post interface
76
+ * Fixed: Isolate the Attach to Post from implicit third-party script inclusion
77
+ * Fixed: Check for the existance of thumbnails when generating urls, and if missing, generate new ones
78
+ * Fixed: Compatibility with NextGEN Facebook OpenGraph+ plugin
79
+ * Fixed: Various XML-RPC issues
80
+ * Fixed: Widgets stylesheet not included
81
+ * Fixed: Issue with color not being pre-selected when previewing Watermark
82
+ * Fixed: E_NOTICE emitted when cleaning up cached image files
83
+ * Fixed: E_NOTICE emitted when viewing display type settings
84
+ * Fixed: Typo adjusting pcre.backtrack_limit for shortcodes
85
+ * Fixed: Content within the tabs of the Attach to Post interface cut-off
86
+ * Fixed: Routing problem which would cause conflicts with different display types on the same page
87
+ * Fixed: Broken Dynamic CSS links on GoDaddy
88
+ * Fixed: Ability to use HTML in gallery/album descriptions
89
+ * Fixed: Sub-album requests conflicting with paginated galleries on the same page
90
+ * Merged: Pull request from andreasE (https://bitbucket.org/photocrati/nextgen-gallery/pull-request/6/)
91
+
92
+ = V2.0.33 - 10.21.2013 =
93
+ * NEW: Requests /ngg_tag/[tagname] will create a displayed gallery
94
+ * NEW: Option added to "Import Gallery" tab to use original images
95
+ * Fixed: Links are broken on the ngg_tags-sitemap.xml file by WordPress SEO
96
+ * Fixed: PHP notice: Attempt to assign property of non-object
97
+ * Fixed: Undefined property warnings when using NextGEN Basic Thumbnails
98
+ * Fixed: Detect if an applying a transient to a displayed gallery was successful
99
+ * Fixed: Compatibility issues with BJ-Lazy-Load and Colorbox
100
+ * Fixed: Pagination conflicts for multiple Imagebrowsers on the same page
101
+ * Fixed: Ability to display previous exception with debug mode
102
+ * Fixed: Tagclouds not working in multisite instances
103
+ * Fixed: Load widgets.css when a widget is being used
104
+ * Fixed: Installer should remove all instances of the component factory
105
+ * Fixed: Widget settings interface not intuitive
106
+ * Fixed: Inability to upload images in some Windows host environments
107
+ * Fixed: Sorting images/galleries using the Attach To Post interface
108
+ * Fixed: Fix detection of HTTPS (pull request by Leonhardt Wille)
109
+ * Fixed: Compilation errors of regular expressions
110
+ * Fixed: Pro galleries wouldn't display in environments using PHP 5.3.3 or less
111
+ * Fixed: Scanning of router slug is now limited to the uri, not the url
112
+ * Fixed: Show slideshow link isn't required for thumbnail/imagebrowser integration
113
+ * Fixed: WordPress media-upload with 'singlepic' image size
114
+ * Fixed: Use target=_blank when the link setting is provided for NextGEN Basic Singlepic
115
+ * Fixed: Only display rendering errors if WP_DEBUG is enabled
116
+
117
+
118
+ = V2.0.31 - 10.03.2013 =
119
+ * NEW: Restored AJAX pagination for NextGEN Basic ImageBrowser display type
120
+ * Fixed: Compatibility with WordPress Local SEO by Yoast
121
+ * Fixed: Inability to upload images if image_slug field was missing in database
122
+ * Fixed: Integration of NextGEN Basic Thumbnail and NextGEN Basic Slideshow display types
123
+ * Fixed: Photocrati Resource Manager further adjusted to be third-party friendly
124
+ * Fixed: Added the ability to find legacy templates in both the child/parent theme directories
125
+ * Fixed: JavaScript errors in Attach to Post interface
126
+ * Fixed: Router can handle port numbers in urls
127
+ * Fixed: Carousel template was linking to NextGEN Basic ImageBrowser view
128
+ * Fixed: SQL query generated for displayed galleries using tags as source
129
+ * Fixed: 3rd party compat: raise & never lower pcre.backtrack_limit
130
+
131
+ = V2.0.30 - 09.25.2013 =
132
+ * NEW: Restored the ability to use imagebrowser display type instead of a lightbox effect
133
+ * Changed: Displayed galleries are no longer rendered in RSS feeds
134
+ * Changed: Removed "Plugin Check" widget from overview page
135
+ * Fixed: Silence PHP warnings/errors in an output buffer for AJAX actions
136
+ * Fixed: Compatibility issue with WordPress SEO and broken site maps (and large error_logs)
137
+ * Fixed: Compatibility issue with AJAX Event Calendar (and possibly others)
138
+ * Fixed: Adjusted Photocrati Resource Manager to be third-party friendly
139
+ * Fixed: Fixed empty result set for displayed galleries selecting 'All' tags
140
+ * Fixed: URL generation for imagebrowser pagination links
141
+ * Fixed: Ensure that image meta is imported on creation
142
+ * Fixed: Ensure that transients are removed when an external object cache is used
143
+ * Fixed: Don't load pluggable.php. This will fix plugin conflicts
144
+ * Fixed: In Attach to Post interface, galleries created in one tab weren't showing in another
145
+ * Fixed: Don't output frame events cookie for XML-RPC requests
146
+
147
+ = V2.0.27 - 09.18.2013 =
148
+ * Fixed: Reduce performance impact of purging displayed gallery transients
149
+
150
+ = V2.0.25 - 09.18.2013 =
151
+ * Changed: Reverting to the 2.0.21 codebase, due to major performance issues in 2.0.23 and 2.0.24
152
+
153
+ = V2.0.24 - 09.18.2013 =
154
+ * WARNING: Broken release. Uses wp_clear_scheduled_hooks() to purge cron records
155
+
156
+ = V2.0.23 - 09.12.2013 =
157
+ * WARNING: Broken release. Major bug creates redundant cron jobs
158
+ * NEW: WP-Cron job to periodically clean-up displayed gallery transients
159
+ * NEW: Added "excluded_container_ids" as parameter for ngg_images shortcode
160
+ * Fixed: Lightbox effect is honoured by all display types
161
+ * Fixed: Highslide displays images from the correct displayed galleries
162
+ * Fixed: Ensure that sub-albums display correctly when the word "album" is part of a slug
163
+ * Fixed: Ensure that sub-albums display correctly when numerical slugs are used
164
+ * Fixed: Related images heading only added when Related Images functionality is enabled
165
+ * Fixed: PHP Warning about undefined index when viewing basic albums
166
+ * Fixed: AJAX handling is third-party compatible
167
+ * Fixed: Image date is no longer overwritten when an image is modified
168
+ * Fixed: Fixed issue with displayed galleries using source='tags'
169
+ * Fixed: Problem with transient cache not getting flushed properly from Other Options page
170
+ * Fixed: Use correct gallery/transient ID when ajax pagination is used
171
+
172
+ = V2.0.21 - 09.09.2013 =
173
+ * NEW: Multisite support
174
+ * Changed: Default image quality set to 100 for generated images
175
+ * Changed: Removed dependence on simplehtmldom library
176
+ * Fixed: Related images functionality works as it did in 1.9.x
177
+ * Fixed: Don't compress inline JavaScript in post/page content
178
+ * Fixed: Click-to-advance slideshow behavior for slideshows
179
+ * Fixed: Security warnings from VaultPress
180
+ * Fixed: View as Slideshow link works with AJAX pagination
181
+ * Fixed: Broken links on Overview page
182
+ * Fixed: Backup images option
183
+ * Fixed: Stylesheet url generated correctly for Windows hosts
184
+ * Fixed: Compatibility with NextGen Custom Fields plugin
185
+ * Fixed: Compatibility with Adsense Explosion plugin
186
+ * Fixed: Suppress wp_footer notices unless WP_DEBUG is set to TRUE
187
+
188
+ = V2.0.17 - 08.30.2013 =
189
+ Fixed: Match legacy behaviour when changing gallery path, i.e. don't move files
190
+
191
+ = V2.0.14 - 08.27.2013 =
192
+ * NEW: Added the ability to override thumbnail settings for NextGEN Basic Albums
193
+ * NEW: Shortcode Manager API, which ensures that shortcodes are outputted as intended
194
+ * Changed: Re-added the ability to select the original image size for widgets
195
+ * Fixed: Ensure that stylesheet url returned is correct for Windows hosts
196
+ * Fixed: Broken links and lightbox effects with AJAX pagination
197
+ * Fixed: Try to ensure that third party plugins don't add content to our dynamic JS
198
+ * Fixed: Improved reliability of iframely.js
199
+ * Fixed: Ensure that urls are generated correctly in HTTPs environments
200
+ * Fixed: Datamapper works correctly in environments where temporary tables aren't supported
201
+ * Fixed: Fixed an issue with thickbox loading animation when home url differs from site url
202
+
203
+ = V2.0.11 - 08.19.2013 =
204
+ * NEW: Added "run_ngg_resource_manager" hook to by-pass our resource manager
205
+ * Changed: Removed "Reset & Uninstall" tab, for now
206
+ * Fixed: Compatibility with W3 Total Cache. Please flush cache after updating.
207
+ * Fixed: Conflicts with Photocrati Theme Galleries
208
+ * Fixed: Blank Attach to Post interface window
209
+ * Fixed: Fixed ability to change Lightbox Effect settings
210
+ * Fixed: Implemented techniques to ensure WP_Query variables aren't overwritten
211
+ * Fixed: Enqueuing AJAX JS libraries twice in wp-admin
212
+ * Fixed: Encoding issues
213
+ * Fixed: PHP warnings caused by accessing unserialized data as array
214
+ * Fixed: Fixed installer issues
215
+
216
+ = V2.0.7 - 08.09.2013 =
217
+ * NEW: New resource manager that fixes many plugin and theme incompatibilities
218
+ * NEW: Styles (custom stylesheets) should reside in wp-content/ngg_styles
219
+ * NEW: Added option to "Other Options -> Misc" to control maximum images returned
220
+ * Secured: Removed default connector for jQuery FileTree library
221
+ * Changed: Updated the simplehtmldom library to version 1.5
222
+ * Changed: jQuery is now enqueued at the beginning of every request
223
+ * Fixed: Incompatibilities with BuddyPress
224
+ * Fixed: Incompatibilities with Events+, bbPress, Custom Permalinks, and many other plugins
225
+ * Fixed: Incompcatibilities with Member Access, AMember, Magic Fields, and More Fields
226
+ * Fixed: Incompatibilities with Elegant Themes, Oxygen, Responsive, and many other themes
227
+ * Fixed: Ensure that gallery images don't have a border by default
228
+ * Fixed: Conflict between imagebrowser and album urls
229
+ * Fixed: Reverted default gallerypath to wp-content/gallery/
230
+ * Fixed: Upgrade-safe way of overriding Styles
231
+ * Fixed: Generation of AJAX url is now based on slug
232
+ * Fixed: Restore nggShowGallery and nggShowSlideshow as wrappers to new API
233
+ * Fixed: Always use domain as specified by WordPress Site URL
234
+ * Fixed: Use WordPress Home URL over Site URL when appropriate
235
+ * Fixed: Numerous pagination issues
236
+ * Fixed: Adjusted our forms to comply with WordPress Firewalls
237
+ * Fixed: Correct use of select2 DOM selector for maximum compatibility
238
+ * Fixed: Path and URL calculations for Windows and UNIX environments
239
+ * Fixed: Ensure that pluggable.php is loaded at the start of every request
240
+ * Fixed: Fancybox: adjust CSS for further box-sizing protection from themes
241
+ * Fixed: Use PHP 5.2.1 compatible named pattern matching syntax
242
+ * Fixed: Remove usage of __DIR__ constant not supported by PHP 5.2.x
243
+ * Fixed: Removed dependency on mb_string PHP module
244
+ * Fixed: Allow "No Lightbox" as an option for Lightbox Effects
245
+ * Fixed: Warning: "Invalid CRT parameters detected" for Windows environments
246
+
247
  = V2.0 - 07.30.2013 =
248
  * NEW: Improved user experience throughout the plugin, settings and usage.
249
  * NEW: Plupload queue uploader that allows for bulk and zip uploads within the same interface.
nggallery.php CHANGED
@@ -3,8 +3,8 @@ if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You
3
 
4
  /**
5
  * Plugin Name: NextGEN Gallery by Photocrati
6
- * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 7 million downloads.
7
- * Version: 2.0
8
  * Author: Photocrati Media
9
  * Plugin URI: http://www.nextgen-gallery.com
10
  * Author URI: http://www.photocrati.com
@@ -12,6 +12,51 @@ if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You
12
  */
13
 
14
  if (!class_exists('E_Clean_Exit')) { class E_Clean_Exit extends RuntimeException {} }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  /**
17
  * NextGEN Gallery is built on top of the Photocrati Pope Framework:
@@ -52,15 +97,42 @@ class C_NextGEN_Bootstrap
52
  $klass = get_class($exception);
53
  echo "<h1>{$klass} thrown</h1>";
54
  echo "<p>{$exception->getMessage()}</p>";
55
- if (self::$debug OR (defined('NEXTGEN_GALLERY_DEBUG') AND NEXTGEN_GALLERY_DEBUG == TRUE)) {
56
  echo "<h3>Where:</h3>";
57
  echo "<p>On line <strong>{$exception->getLine()}</strong> of <strong>{$exception->getFile()}</strong></p>";
58
  echo "<h3>Trace:</h3>";
59
  echo "<pre>{$exception->getTraceAsString()}</pre>";
60
- while (($previous = $exception->getPrevious())) {
61
- self::print_exception($previous);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
63
  }
 
 
64
  }
65
 
66
  function __construct()
@@ -69,27 +141,34 @@ class C_NextGEN_Bootstrap
69
  set_exception_handler(__CLASS__.'::shutdown');
70
 
71
  $this->_define_constants();
72
- $this->_load_non_pope();
73
- $this->_register_hooks();
74
- $this->_load_pope();
75
-
76
  }
77
 
78
  function _load_non_pope()
79
  {
80
  // Load caching component
81
  include_once('non_pope/class.photocrati_cache.php');
82
- C_Photocrati_Cache::$enabled = TRUE;
 
 
 
 
83
 
84
  if (isset($_REQUEST['ngg_flush'])) {
85
  C_Photocrati_Cache::flush('all');
86
- $_SERVER['QUERY_STRING'] = str_replace('ngg_flush=1', '', $_SERVER['QUERY_STRING']);
87
  }
88
  elseif (isset($_REQUEST['ngg_force_update'])) {
89
  C_Photocrati_Cache::$do_not_lookup = TRUE;
90
  C_Photocrati_Cache::$force_update = TRUE;
91
  $_SERVER['QUERY_STRING'] = str_replace('ngg_force_update=1', '', $_SERVER['QUERY_STRING']);
92
  }
 
 
 
 
93
 
94
  // Load Settings Manager
95
  include_once('non_pope/class.photocrati_settings_manager.php');
@@ -99,6 +178,16 @@ class C_NextGEN_Bootstrap
99
 
100
  // Load the installer
101
  include_once('non_pope/class.photocrati_installer.php');
 
 
 
 
 
 
 
 
 
 
102
  }
103
 
104
  /**
@@ -110,16 +199,13 @@ class C_NextGEN_Bootstrap
110
  if ($this->_pope_loaded) return;
111
 
112
  // Pope requires a a higher limit
113
- $tmp = ini_get('xdebug.max_nesting_level');
114
- if ($tmp && (int)$tmp <= 300) @ini_set('xdebug.max_nesting_level', 300);
115
 
116
  // Include pope framework
117
- require_once(path_join(NEXTGEN_GALLERY_PLUGIN_DIR, implode(
118
- DIRECTORY_SEPARATOR, array('pope','lib','autoload.php')
119
- )));
120
-
121
- // Include some extra helpers
122
- require_once(path_join(NEXTGEN_GALLERY_PLUGIN_DIR, 'wordpress_helpers.php'));
123
 
124
  // Get the component registry
125
  $this->_registry = C_Component_Registry::get_instance();
@@ -129,19 +215,16 @@ class C_NextGEN_Bootstrap
129
 
130
  // Load embedded products. Each product is expected to load any
131
  // modules required
132
- $this->_registry->add_module_path(NEXTGEN_GALLERY_PRODUCT_DIR, true, false);
133
  $this->_registry->load_all_products();
134
 
135
- // Give third-party plugins that opportunity to include their own products
136
- // and modules
137
- do_action('load_nextgen_gallery_modules', $this->_registry);
138
 
139
  // Initializes all loaded modules
140
  $this->_registry->initialize_all_modules();
141
 
142
- // Set the document root
143
- $this->_registry->get_utility('I_Fs')->set_document_root(ABSPATH);
144
-
145
  $this->_pope_loaded = TRUE;
146
  }
147
 
@@ -154,16 +237,16 @@ class C_NextGEN_Bootstrap
154
  {
155
  // Load text domain
156
  load_plugin_textdomain(
157
- NEXTGEN_GALLERY_I8N_DOMAIN,
158
  false,
159
  $this->directory_path('lang')
160
  );
161
 
162
  // Register the activation routines
163
- add_action('activate_'.NEXTGEN_GALLERY_PLUGIN_BASENAME, array(get_class(), 'activate'));
164
 
165
  // Register the deactivation routines
166
- add_action('deactivate_'.NEXTGEN_GALLERY_PLUGIN_BASENAME, array(get_class(), 'deactivate'));
167
 
168
  // Register our test suite
169
  add_filter('simpletest_suites', array(&$this, 'add_testsuite'));
@@ -172,11 +255,58 @@ class C_NextGEN_Bootstrap
172
  add_filter('pre_update_option_'.$this->_settings_option_name, array(&$this, 'persist_settings'));
173
  add_filter('pre_update_site_option_'.$this->_settings_option_name, array(&$this, 'persist_settings'));
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  // Update modules
176
- add_action('init', array(&$this, 'update'), PHP_INT_MAX);
177
 
178
  // Start the plugin!
179
- add_action('init', array(&$this, 'route'), PHP_INT_MAX);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
181
 
182
  /**
@@ -192,10 +322,79 @@ class C_NextGEN_Bootstrap
192
  return $settings;
193
  }
194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  function update()
196
  {
197
- $this->_load_pope();
198
- C_Photocrati_Installer::update();
 
 
 
 
 
199
  }
200
 
201
  /**
@@ -224,7 +423,7 @@ class C_NextGEN_Bootstrap
224
  */
225
  static function deactivate()
226
  {
227
- C_Photocrati_Installer::uninstall(NEXTGEN_GALLERY_PLUGIN_BASENAME);
228
  }
229
 
230
  /**
@@ -233,21 +432,64 @@ class C_NextGEN_Bootstrap
233
  function _define_constants()
234
  {
235
  // NextGEN by Photocrati Constants
236
- define('NEXTGEN_GALLERY_PLUGIN', basename($this->directory_path()));
237
- define('NEXTGEN_GALLERY_PLUGIN_BASENAME', plugin_basename(__FILE__));
238
- define('NEXTGEN_GALLERY_PLUGIN_DIR', $this->directory_path());
239
- define('NEXTGEN_GALLERY_PLUGIN_URL', $this->path_uri());
240
- define('NEXTGEN_GALLERY_I8N_DOMAIN', 'nggallery');
241
- define('NEXTGEN_GALLERY_TESTS_DIR', path_join(NEXTGEN_GALLERY_PLUGIN_DIR, 'tests'));
242
- define('NEXTGEN_GALLERY_PRODUCT_DIR', path_join(NEXTGEN_GALLERY_PLUGIN_DIR, 'products'));
243
- define('NEXTGEN_GALLERY_PRODUCT_URL', path_join(NEXTGEN_GALLERY_PLUGIN_URL, 'products'));
244
- define('NEXTGEN_GALLERY_MODULE_DIR', path_join(NEXTGEN_GALLERY_PRODUCT_DIR, 'photocrati_nextgen/modules'));
245
- define('NEXTGEN_GALLERY_MODULE_URL', path_join(NEXTGEN_GALLERY_PRODUCT_URL, 'photocrati_nextgen/modules'));
246
- define('NEXTGEN_GALLERY_PLUGIN_CLASS', path_join(NEXTGEN_GALLERY_PLUGIN_DIR, 'module.NEXTGEN_GALLERY_PLUGIN.php'));
247
- define('NEXTGEN_GALLERY_PLUGIN_STARTED_AT', microtime());
248
- define('NEXTGEN_GALLERY_PLUGIN_VERSION', '2.0');
249
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
 
 
 
 
 
251
 
252
  /**
253
  * Defines the NextGEN Test Suite
@@ -256,7 +498,7 @@ class C_NextGEN_Bootstrap
256
  */
257
  function add_testsuite($suites=array())
258
  {
259
- $tests_dir = NEXTGEN_GALLERY_TESTS_DIR;
260
 
261
  if (file_exists($tests_dir)) {
262
 
3
 
4
  /**
5
  * Plugin Name: NextGEN Gallery by Photocrati
6
+ * Description: The most popular gallery plugin for WordPress and one of the most popular plugins of all time with over 9 million downloads.
7
+ * Version: 2.0.57
8
  * Author: Photocrati Media
9
  * Plugin URI: http://www.nextgen-gallery.com
10
  * Author URI: http://www.photocrati.com
12
  */
13
 
14
  if (!class_exists('E_Clean_Exit')) { class E_Clean_Exit extends RuntimeException {} }
15
+ if (!class_exists('E_NggErrorException')) { class E_NggErrorException extends RuntimeException {} }
16
+
17
+ // This is a temporary function to replace the use of WP's esc_url which strips spaces away from URLs
18
+ // TODO: Move this to a better place
19
+ if (!function_exists('nextgen_esc_url')) {
20
+ function nextgen_esc_url( $url, $protocols = null, $_context = 'display' ) {
21
+ $original_url = $url;
22
+
23
+ if ( '' == $url )
24
+ return $url;
25
+ $url = preg_replace('|[^a-z0-9 \\-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
26
+ $strip = array('%0d', '%0a', '%0D', '%0A');
27
+ $url = _deep_replace($strip, $url);
28
+ $url = str_replace(';//', '://', $url);
29
+ /* If the URL doesn't appear to contain a scheme, we
30
+ * presume it needs http:// appended (unless a relative
31
+ * link starting with /, # or ? or a php file).
32
+ */
33
+
34
+ if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) &&
35
+ ! preg_match('/^[a-z0-9-]+?\.php/i', $url) )
36
+ $url = 'http://' . $url;
37
+
38
+ // Replace ampersands and single quotes only when displaying.
39
+ if ( 'display' == $_context ) {
40
+ $url = wp_kses_normalize_entities( $url );
41
+ $url = str_replace( '&amp;', '&#038;', $url );
42
+ $url = str_replace( "'", '&#039;', $url );
43
+ $url = str_replace( '%', '%25', $url );
44
+ $url = str_replace( ' ', '%20', $url );
45
+ }
46
+
47
+ if ( '/' === $url[0] ) {
48
+ $good_protocol_url = $url;
49
+ } else {
50
+ if ( ! is_array( $protocols ) )
51
+ $protocols = wp_allowed_protocols();
52
+ $good_protocol_url = wp_kses_bad_protocol( $url, $protocols );
53
+ if ( strtolower( $good_protocol_url ) != strtolower( $url ) )
54
+ return '';
55
+ }
56
+
57
+ return apply_filters('clean_url', $good_protocol_url, $original_url, $_context);
58
+ }
59
+ }
60
 
61
  /**
62
  * NextGEN Gallery is built on top of the Photocrati Pope Framework:
97
  $klass = get_class($exception);
98
  echo "<h1>{$klass} thrown</h1>";
99
  echo "<p>{$exception->getMessage()}</p>";
100
+ if (self::$debug OR (defined('NGG_DEBUG') AND NGG_DEBUG == TRUE)) {
101
  echo "<h3>Where:</h3>";
102
  echo "<p>On line <strong>{$exception->getLine()}</strong> of <strong>{$exception->getFile()}</strong></p>";
103
  echo "<h3>Trace:</h3>";
104
  echo "<pre>{$exception->getTraceAsString()}</pre>";
105
+ if (method_exists($exception, 'getPrevious')) {
106
+ if (($previous = $exception->getPrevious())) {
107
+ self::print_exception($previous);
108
+ }
109
+ }
110
+ }
111
+ }
112
+
113
+ static function get_backtrace($objects=FALSE, $remove_dynamic_calls=TRUE)
114
+ {
115
+ $trace = debug_backtrace($objects);
116
+ if ($remove_dynamic_calls) {
117
+ $skip_methods = array(
118
+ '_exec_cached_method',
119
+ '__call',
120
+ 'get_method_property',
121
+ 'set_method_property',
122
+ 'call_method'
123
+ );
124
+ foreach ($trace as $key => &$value) {
125
+ if (isset($value['class']) && isset($value['function'])) {
126
+ if ($value['class'] == 'ReflectionMethod' && $value['function'] == 'invokeArgs')
127
+ unset($trace[$key]);
128
+
129
+ else if ($value['class'] == 'ExtensibleObject' && in_array($value['function'], $skip_methods))
130
+ unset($trace[$key]);
131
+ }
132
  }
133
  }
134
+
135
+ return $trace;
136
  }
137
 
138
  function __construct()
141
  set_exception_handler(__CLASS__.'::shutdown');
142
 
143
  $this->_define_constants();
144
+ $this->_load_non_pope();
145
+ $this->_register_hooks();
146
+ $this->_load_pope();
 
147
  }
148
 
149
  function _load_non_pope()
150
  {
151
  // Load caching component
152
  include_once('non_pope/class.photocrati_cache.php');
153
+ C_Photocrati_Cache::get_instance();
154
+ C_Photocrati_Cache::get_instance('displayed_galleries');
155
+ C_Photocrati_Cache::get_instance('displayed_gallery_rendering');
156
+
157
+ C_Photocrati_Cache::$enabled = PHOTOCRATI_CACHE;
158
 
159
  if (isset($_REQUEST['ngg_flush'])) {
160
  C_Photocrati_Cache::flush('all');
161
+ die("Flushed all caches");
162
  }
163
  elseif (isset($_REQUEST['ngg_force_update'])) {
164
  C_Photocrati_Cache::$do_not_lookup = TRUE;
165
  C_Photocrati_Cache::$force_update = TRUE;
166
  $_SERVER['QUERY_STRING'] = str_replace('ngg_force_update=1', '', $_SERVER['QUERY_STRING']);
167
  }
168
+ elseif (isset($_REQUEST['ngg_flush_expired'])) {
169
+ C_Photocrati_Cache::flush('all', TRUE);
170
+ die("Flushed all expired items from the cache");
171
+ }
172
 
173
  // Load Settings Manager
174
  include_once('non_pope/class.photocrati_settings_manager.php');
178
 
179
  // Load the installer
180
  include_once('non_pope/class.photocrati_installer.php');
181
+
182
+ // Load the resource manager
183
+ include_once('non_pope/class.photocrati_resource_manager.php');
184
+ C_Photocrati_Resource_Manager::init();
185
+
186
+ // Load the style manager
187
+ include_once('non_pope/class.nextgen_style_manager.php');
188
+
189
+ // Load the shortcode manager
190
+ include_once('non_pope/class.nextgen_shortcode_manager.php');
191
  }
192
 
193
  /**
199
  if ($this->_pope_loaded) return;
200
 
201
  // Pope requires a a higher limit
202
+ $tmp = ini_get('xdebug.max_nesting_level');
203
+ if ($tmp && (int)$tmp <= 300) @ini_set('xdebug.max_nesting_level', 300);
204
 
205
  // Include pope framework
206
+ require_once(implode(
207
+ DIRECTORY_SEPARATOR, array(NGG_PLUGIN_DIR, 'pope','lib','autoload.php')
208
+ ));
 
 
 
209
 
210
  // Get the component registry
211
  $this->_registry = C_Component_Registry::get_instance();
215
 
216
  // Load embedded products. Each product is expected to load any
217
  // modules required
218
+ $this->_registry->add_module_path(NGG_PRODUCT_DIR, true, false);
219
  $this->_registry->load_all_products();
220
 
221
+ // Give third-party plugins that opportunity to include their own products
222
+ // and modules
223
+ do_action('load_nextgen_gallery_modules', $this->_registry);
224
 
225
  // Initializes all loaded modules
226
  $this->_registry->initialize_all_modules();
227
 
 
 
 
228
  $this->_pope_loaded = TRUE;
229
  }
230
 
237
  {
238
  // Load text domain
239
  load_plugin_textdomain(
240
+ NGG_I8N_DOMAIN,
241
  false,
242
  $this->directory_path('lang')
243
  );
244
 
245
  // Register the activation routines
246
+ add_action('activate_'.NGG_PLUGIN_BASENAME, array(get_class(), 'activate'));
247
 
248
  // Register the deactivation routines
249
+ add_action('deactivate_'.NGG_PLUGIN_BASENAME, array(get_class(), 'deactivate'));
250
 
251
  // Register our test suite
252
  add_filter('simpletest_suites', array(&$this, 'add_testsuite'));
255
  add_filter('pre_update_option_'.$this->_settings_option_name, array(&$this, 'persist_settings'));
256
  add_filter('pre_update_site_option_'.$this->_settings_option_name, array(&$this, 'persist_settings'));
257
 
258
+ // This plugin uses jQuery extensively
259
+ add_action('wp_enqueue_scripts', array(&$this, 'fix_jquery'));
260
+ add_action('wp_print_scripts', array(&$this, 'fix_jquery'));
261
+
262
+ // We require a minimum of jQuery 1.11.0 for IE11, due to a problem with interframe communication
263
+ $version = get_bloginfo('version');
264
+ if (version_compare($version, '3.9') == -1) {
265
+ add_action('admin_print_scripts', array(&$this, 'custom_jquery_prep'), 1);
266
+ add_action('admin_print_scripts', array(&$this, 'custom_jquery_install'), PHP_INT_MAX-1);
267
+ }
268
+
269
+ // If the selected stylesheet is using an unsafe path, then notify the user
270
+ if (C_NextGen_Style_Manager::get_instance()->is_directory_unsafe()) {
271
+ add_action('all_admin_notices', array(&$this, 'display_stylesheet_notice'));
272
+ }
273
+
274
+ // Delete displayed gallery transients periodically
275
+ add_filter('cron_schedules', array(&$this, 'add_ngg_schedule'));
276
+ add_action('ngg_delete_expired_transients', array(&$this, 'delete_expired_transients'));
277
+ if (!wp_next_scheduled('ngg_delete_expired_transients')) {
278
+ wp_schedule_event(time(), 'ngg_custom', 'ngg_delete_expired_transients');
279
+ }
280
+
281
  // Update modules
282
+ add_action('init', array(&$this, 'update'), PHP_INT_MAX-1);
283
 
284
  // Start the plugin!
285
+ add_action('init', array(&$this, 'route'), 11);
286
+ }
287
+
288
+ /**
289
+ * Defines a new cron schedule
290
+ * @param $schedules
291
+ * @return mixed
292
+ */
293
+ function add_ngg_schedule($schedules)
294
+ {
295
+ $schedules['ngg_custom'] = array(
296
+ 'interval' => NGG_CRON_SCHEDULE,
297
+ 'display' => sprintf(__('Every %d seconds', 'nggallery'), NGG_CRON_SCHEDULE)
298
+ );
299
+
300
+ return $schedules;
301
+ }
302
+
303
+
304
+ /**
305
+ * Flush all expires transients created by the plugin
306
+ */
307
+ function delete_expired_transients()
308
+ {
309
+ C_Photocrati_Cache::flush('displayed_galleries', TRUE);
310
  }
311
 
312
  /**
322
  return $settings;
323
  }
324
 
325
+ /**
326
+ * Ensures that the version of JQuery used is expected for NextGEN Gallery
327
+ */
328
+ function fix_jquery()
329
+ {
330
+ global $wp_scripts;
331
+
332
+ // Determine which version of jQuery to include
333
+ $src = '/wp-includes/js/jquery/jquery.js';
334
+
335
+ // Ensure that jQuery is always set to the default
336
+ if (isset($wp_scripts->registered['jquery'])) {
337
+ $wp_scripts->registered['jquery']->src = FALSE;
338
+ }
339
+
340
+ if (isset($wp_scripts->registered['jquery-core'])) {
341
+ $wp_scripts->registered['jquery-core']->src = $src;
342
+ }
343
+
344
+ wp_enqueue_script('jquery');
345
+ }
346
+
347
+ function custom_jquery_prep()
348
+ {
349
+ ob_start();
350
+ }
351
+
352
+ function custom_jquery_install()
353
+ {
354
+ $scripts = ob_get_clean();
355
+ if (strpos($scripts, "jquery-core") === FALSE) {
356
+ if (preg_match("#<script.*jquery.js.*</script>#", $scripts, $match)) {
357
+ $jquery = $match[0];
358
+ if (preg_match("#<script.*load-scripts\\.php.*</script>#", $scripts, $match)) {
359
+ $load_scripts = $match[0];
360
+ $scripts = str_replace($load_scripts, "{$jquery}\n{$load_scripts}", $scripts);
361
+ }
362
+ }
363
+
364
+ }
365
+ echo $scripts;
366
+ }
367
+
368
+ /**
369
+ * Displays a notice to the user that the current stylesheet location is unsafe
370
+ */
371
+ function display_stylesheet_notice()
372
+ {
373
+ $styles = C_NextGen_Style_Manager::get_instance();
374
+ $filename = $styles->get_selected_stylesheet();
375
+ $abspath = $styles->find_selected_stylesheet_abspath();
376
+ $newpath = $styles->new_dir;
377
+
378
+ echo "<div class='updated error'>
379
+ <h3>WARNING: NextGEN Gallery Stylesheet NOT Upgrade-safe</h3>
380
+ <p>
381
+ <strong>{$filename}</strong> is currently stored in <strong>{$abspath}</strong>, which isn't upgrade-safe. Please move the stylesheet to
382
+ <strong>{$newpath}</strong> to ensure that your customizations persist after updates.
383
+ </p></div>";
384
+ }
385
+
386
+ /**
387
+ * Updates all modules
388
+ */
389
  function update()
390
  {
391
+ if ((!(defined('DOING_AJAX') && DOING_AJAX)) && !isset($_REQUEST['doing_wp_cron'])) {
392
+
393
+ $this->_load_pope();
394
+
395
+ // Try updating all modules
396
+ C_Photocrati_Installer::update();
397
+ }
398
  }
399
 
400
  /**
423
  */
424
  static function deactivate()
425
  {
426
+ C_Photocrati_Installer::uninstall(NGG_PLUGIN_BASENAME);
427
  }
428
 
429
  /**
432
  function _define_constants()
433
  {
434
  // NextGEN by Photocrati Constants
435
+ define('NGG_PLUGIN', basename($this->directory_path()));
436
+ define('NGG_PLUGIN_BASENAME', plugin_basename(__FILE__));
437
+ define('NGG_PLUGIN_DIR', $this->directory_path());
438
+ define('NGG_PLUGIN_URL', $this->path_uri());
439
+ define('NGG_I8N_DOMAIN', 'nggallery');
440
+ define('NGG_TESTS_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'tests')));
441
+ define('NGG_PRODUCT_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PLUGIN_DIR, "/\\"), 'products')));
442
+ define('NGG_MODULE_DIR', implode(DIRECTORY_SEPARATOR, array(rtrim(NGG_PRODUCT_DIR, "/\\"), 'photocrati_nextgen', 'modules')));
443
+ define('NGG_PRODUCT_URL', path_join(str_replace("\\", '/', NGG_PLUGIN_URL), 'products'));
444
+ define('NGG_MODULE_URL', path_join(str_replace("\\", '/', NGG_PRODUCT_URL), 'photocrati_nextgen/modules'));
445
+ define('NGG_PLUGIN_STARTED_AT', microtime());
446
+ define('NGG_PLUGIN_VERSION', '2.0.57');
447
+ define('NGG_JQUERY_VERSION', '1.11.0');
448
+
449
+ if (!defined('NGG_HIDE_STRICT_ERRORS')) {
450
+ define('NGG_HIDE_STRICT_ERRORS', TRUE);
451
+ }
452
+
453
+ // Should we display E_STRICT errors?
454
+ if (NGG_HIDE_STRICT_ERRORS) {
455
+ $level = error_reporting();
456
+ if ($level != 0) error_reporting($level & ~E_STRICT);
457
+ }
458
+
459
+ // Should we display NGG debugging information?
460
+ if (!defined('NGG_DEBUG')) {
461
+ define('NGG_DEBUG', FALSE);
462
+ }
463
+ self::$debug = NGG_DEBUG;
464
+
465
+ // User definable constants
466
+ if (!defined('NGG_IMPORT_ROOT')) {
467
+ $path = WP_CONTENT_DIR;
468
+ if (is_multisite()) {
469
+ $uploads = wp_upload_dir();
470
+ $path = $uploads['path'];
471
+ }
472
+ define('NGG_IMPORT_ROOT', $path);
473
+ }
474
+
475
+ // Should the Photocrati cache be enabled
476
+ if (!defined('PHOTOCRATI_CACHE')) {
477
+ define('PHOTOCRATI_CACHE', TRUE);
478
+ }
479
+ if (!defined('PHOTOCRATI_CACHE_TTL')) {
480
+ define('PHOTOCRATI_CACHE_TTL', 3600);
481
+ }
482
+
483
+ // Cron job
484
+ if (!defined('NGG_CRON_SCHEDULE')) {
485
+ define('NGG_CRON_SCHEDULE', 1800);
486
+ }
487
 
488
+ // Don't enforce interfaces
489
+ if (!defined('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES')) {
490
+ define('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES', FALSE);
491
+ }
492
+ }
493
 
494
  /**
495
  * Defines the NextGEN Test Suite
498
  */
499
  function add_testsuite($suites=array())
500
  {
501
+ $tests_dir = NGG_TESTS_DIR;
502
 
503
  if (file_exists($tests_dir)) {
504
 
non_pope/class.nextgen_settings.php CHANGED
@@ -5,21 +5,25 @@ if (!class_exists('C_NextGen_Settings')) {
5
  class C_NextGen_Settings {
6
  static function get_instance()
7
  {
8
- return C_Photocrati_Settings_Manager::get_instance();
 
 
 
 
 
 
9
  }
10
  }
11
  }
12
 
13
  if (!class_exists('C_NextGen_Global_Settings')) {
14
- class C_NextGen_Global_Settings {
15
  static function get_instance()
16
  {
17
- if (is_multisite()) {
18
- return C_Photocrati_Global_Settings_Manager::get_instance();
19
- }
20
- else {
21
- return C_Photocrati_Settings_Manager::get_instance();
22
- }
23
  }
24
  }
25
  }
5
  class C_NextGen_Settings {
6
  static function get_instance()
7
  {
8
+ return C_Photocrati_Settings_Manager::get_instance();
9
+ }
10
+
11
+ static function add_option_handler($klass, $options=array())
12
+ {
13
+ $instance = self::get_instance();
14
+ return $instance->add_option_handler($klass, $options);
15
  }
16
  }
17
  }
18
 
19
  if (!class_exists('C_NextGen_Global_Settings')) {
20
+ class C_NextGen_Global_Settings extends C_NextGen_Settings {
21
  static function get_instance()
22
  {
23
+ if (is_multisite())
24
+ return C_Photocrati_Global_Settings_Manager::get_instance();
25
+ else
26
+ return C_Photocrati_Settings_Manager::get_instance();
 
 
27
  }
28
  }
29
  }
non_pope/class.nextgen_shortcode_manager.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class C_NextGen_Shortcode_Manager
4
+ {
5
+ private static $_instance = NULL;
6
+ private $_shortcodes = array();
7
+ private $_runlevel = 0;
8
+ private $_has_warned = FALSE;
9
+
10
+ /**
11
+ * Gets an instance of the class
12
+ * @return C_NextGen_Shortcode_Manager
13
+ */
14
+ static function get_instance()
15
+ {
16
+ if (is_null(self::$_instance)) {
17
+ $klass = get_class();
18
+ self::$_instance = new $klass;
19
+ }
20
+ return self::$_instance;
21
+ }
22
+
23
+ /**
24
+ * Adds a shortcode
25
+ * @param $name
26
+ * @param $callback
27
+ */
28
+ static function add($name, $callback)
29
+ {
30
+ $manager = self::get_instance();
31
+ $manager->add_shortcode($name, $callback);
32
+ }
33
+
34
+ /**
35
+ * Removes a previously added shortcode
36
+ * @param $name
37
+ */
38
+ static function remove($name)
39
+ {
40
+ $manager = self::get_instance();
41
+ $manager->remove_shortcode($name);
42
+ }
43
+
44
+ /**
45
+ * Constructor
46
+ */
47
+ private function __construct()
48
+ {
49
+ add_filter('the_content', array(&$this, 'deactivate_all'), -(PHP_INT_MAX-1));
50
+ add_filter('the_content', array(&$this, 'parse_content'), PHP_INT_MAX-1);
51
+ }
52
+
53
+ /**
54
+ * Deactivates all shortcodes
55
+ */
56
+ function deactivate_all($content)
57
+ {
58
+ // There is a bug in Wordpress itself: when a hook recurses any hooks meant to execute after it are discarded.
59
+ // For example the following code, despite expectations, will NOT display 'bar' as bar() is never executed.
60
+ // See https://core.trac.wordpress.org/ticket/17817 for more information.
61
+ /* function foo() {
62
+ * remove_action('foo', 'foo');
63
+ * }
64
+ * function bar() {
65
+ * echo('bar');
66
+ * }
67
+ * add_action('foo', 'foo');
68
+ * add_action('foo', 'bar');
69
+ * do_action('foo');
70
+ */
71
+ $this->_runlevel += 1;
72
+ if ($this->_runlevel > 1 && defined('WP_DEBUG') && WP_DEBUG && !is_admin() && !$this->_has_warned)
73
+ {
74
+ $this->_has_warned = TRUE;
75
+ error_log('Sorry, but recursing filters on "the_content" breaks NextGEN Gallery. Please see https://core.trac.wordpress.org/ticket/17817');
76
+ }
77
+
78
+ foreach (array_keys($this->_shortcodes) as $shortcode) {
79
+ $this->deactivate($shortcode);
80
+ }
81
+
82
+ return $content;
83
+ }
84
+
85
+ /**
86
+ * Activates all registered shortcodes
87
+ */
88
+ function activate_all()
89
+ {
90
+ foreach (array_keys($this->_shortcodes) as $shortcode) {
91
+ $this->activate($shortcode);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Parses the content for shortcodes and returns the substituted content
97
+ * @param $content
98
+ * @return string
99
+ */
100
+ function parse_content($content)
101
+ {
102
+ $this->_runlevel--;
103
+ $this->activate_all();
104
+ return do_shortcode($content);
105
+ }
106
+
107
+ /**
108
+ * Adds a shortcode
109
+ * @param $name
110
+ * @param $callback
111
+ */
112
+ function add_shortcode($name, $callback)
113
+ {
114
+ $this->_shortcodes[$name] = $callback;
115
+ $this->activate($name);
116
+ }
117
+
118
+ /**
119
+ * Activates a particular shortcode
120
+ * @param $shortcode
121
+ */
122
+ function activate($shortcode)
123
+ {
124
+ if (isset($this->_shortcodes[$shortcode])) {
125
+ add_shortcode($shortcode, $this->_shortcodes[$shortcode]);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Removes a shortcode
131
+ * @param $name
132
+ */
133
+ function remove_shortcode($name)
134
+ {
135
+ unset($this->_shortcodes[$name]);
136
+ $this->deactivate($name);
137
+ }
138
+
139
+ /**
140
+ * De-activates a shortcode
141
+ * @param $shortcode
142
+ */
143
+ function deactivate($shortcode)
144
+ {
145
+ if (isset($this->_shortcodes[$shortcode]))
146
+ remove_shortcode($shortcode);
147
+ }
148
+ }
non_pope/class.nextgen_style_manager.php ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class C_NextGen_Style_Manager
4
+ {
5
+ static $_instance = NULL;
6
+ var $directories = array();
7
+ var $unsafe_directories = array();
8
+ var $default_dir = '';
9
+ var $new_dir = '';
10
+
11
+ function __construct()
12
+ {
13
+ $this->default_dir = implode(DIRECTORY_SEPARATOR, array(
14
+ NGG_MODULE_DIR,
15
+ 'ngglegacy',
16
+ 'css'
17
+ ));
18
+
19
+ $this->new_dir = implode(DIRECTORY_SEPARATOR, array(
20
+ rtrim(WP_CONTENT_DIR, "/\\"),
21
+ 'ngg_styles'
22
+ ));
23
+
24
+ // The last place we look for a stylesheet is in ngglegacy
25
+ $this->add_directory($this->default_dir);
26
+
27
+ // This is where all stylesheets should be stored
28
+ $this->add_directory($this->new_dir);
29
+
30
+ // We check the parent theme directory. Needed for child themes
31
+ $this->add_directory(rtrim(get_template_directory(), "/\\"), TRUE);
32
+
33
+ // We also check parent_theme/nggallery
34
+ $this->add_directory(implode(DIRECTORY_SEPARATOR, array(
35
+ rtrim(get_template_directory(), "/\\"),
36
+ 'nggallery'
37
+ )), TRUE);
38
+
39
+ // We also check parent_theme/ngg_styles
40
+ $this->add_directory(implode(DIRECTORY_SEPARATOR, array(
41
+ rtrim(get_template_directory(), "/\\"),
42
+ 'ngg_styles'
43
+ )), TRUE);
44
+
45
+ // We check the root directory of the theme. Users shouldn't store here,
46
+ // but they might
47
+ $this->add_directory(rtrim(get_stylesheet_directory(), "/\\"), TRUE);
48
+
49
+ // We also check the theme/nggallery directory
50
+ $this->add_directory(implode(DIRECTORY_SEPARATOR, array(
51
+ rtrim(get_stylesheet_directory(), "/\\"),
52
+ 'nggallery'
53
+ )), TRUE);
54
+
55
+ // We also check the theme/ngg_styles directory
56
+ $this->add_directory(implode(DIRECTORY_SEPARATOR, array(
57
+ rtrim(get_stylesheet_directory(), "/\\"),
58
+ 'ngg_styles'
59
+ )), TRUE);
60
+ }
61
+
62
+ /**
63
+ * Add a directory to search for stylesheets
64
+ * @param $dir
65
+ * @param bool $unsafe
66
+ */
67
+ function add_directory($dir, $unsafe=FALSE)
68
+ {
69
+ array_unshift($this->directories, $dir);
70
+ if ($unsafe) {
71
+ $this->unsafe_directories[] = $dir;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Determines if a directory is upgrade-safe or not
77
+ * @param $dir
78
+ * @return bool
79
+ */
80
+ function is_directory_unsafe($dir=FALSE)
81
+ {
82
+ if (!$dir) $dir = dirname($this->find_selected_stylesheet_abspath());
83
+
84
+ return in_array($dir, $this->unsafe_directories);
85
+ }
86
+
87
+ /**
88
+ * Determines if the directory is the default ngglegacy path
89
+ * @param $dir
90
+ * @return bool
91
+ */
92
+ function is_default_dir($dir)
93
+ {
94
+ return rtrim($dir, "/\\") == $this->default_dir;
95
+ }
96
+
97
+ function get_new_dir($filename)
98
+ {
99
+ return implode(DIRECTORY_SEPARATOR, array(
100
+ rtrim($this->new_dir, "/\\"),
101
+ $filename
102
+ ));
103
+ }
104
+
105
+ /**
106
+ * Gets the location where the selected stylesheet will be saved to
107
+ * @param bool|string $selected
108
+ * @return string
109
+ */
110
+ function get_selected_stylesheet_saved_abspath($selected=FALSE)
111
+ {
112
+ if (!$selected) $selected = $this->get_selected_stylesheet();
113
+
114
+ $abspath = $this->find_selected_stylesheet_abspath($selected);
115
+ if ($this->is_default_dir(dirname($abspath))) {
116
+ $abspath = $this->get_new_dir(basename($abspath));
117
+ }
118
+
119
+ return $abspath;
120
+ }
121
+
122
+ function save($contents, $selected=FALSE)
123
+ {
124
+ $retval = FALSE;
125
+
126
+ if (!$selected) $selected = $this->get_selected_stylesheet();
127
+ $abspath = $this->get_selected_stylesheet_saved_abspath($selected);
128
+
129
+ wp_mkdir_p(dirname($abspath));
130
+ if (is_writable($abspath) OR (!@file_exists($abspath) && is_writable(dirname($abspath)))) {
131
+ $retval = file_put_contents($abspath, $contents);
132
+ }
133
+ return $retval;
134
+ }
135
+
136
+ /**
137
+ * Gets the selected stylesheet from the user
138
+ * @return mixed
139
+ */
140
+ function get_selected_stylesheet()
141
+ {
142
+ $settings = C_NextGen_Settings::get_instance();
143
+
144
+ // use the same css resource for all subsites when wpmuStyle=true
145
+ if (!is_multisite() || (is_multisite() && $settings->get('wpmuStyle')))
146
+ return $settings->get('CSSfile', 'nggallery.css');
147
+ else
148
+ return C_Nextgen_Global_Settings::get_instance()->get('wpmuCSSfile');
149
+
150
+ }
151
+
152
+ /**
153
+ * Finds the location of the selected stylesheet
154
+ */
155
+ function find_selected_stylesheet_abspath($selected=FALSE)
156
+ {
157
+ if (!$selected) $selected = $this->get_selected_stylesheet();
158
+
159
+ $retval = implode(DIRECTORY_SEPARATOR, array(
160
+ rtrim($this->default_dir, "/\\"),
161
+ $selected
162
+ ));
163
+
164
+ foreach ($this->directories as $dir) {
165
+ $path = implode(DIRECTORY_SEPARATOR, array(
166
+ rtrim($dir, "/\\"),
167
+ $selected
168
+ ));
169
+
170
+ if (@file_exists($path)) {
171
+ $retval = $path;
172
+ break;
173
+ }
174
+ }
175
+
176
+ return $retval;
177
+ }
178
+
179
+ /**
180
+ * Returns the url to the selected stylesheet
181
+ * @return mixed
182
+ */
183
+ function get_selected_stylesheet_url($selected=FALSE)
184
+ {
185
+ if (!$selected) $selected = $this->get_selected_stylesheet();
186
+
187
+ $retval = str_replace(
188
+ C_Fs::get_instance()->get_document_root(),
189
+ site_url(),
190
+ $this->find_selected_stylesheet_abspath($selected)
191
+ );
192
+
193
+ return rtrim(str_replace('\\', '/', $retval), "/");
194
+ }
195
+
196
+
197
+ function find_all_stylesheets($dir = FALSE)
198
+ {
199
+ $retval = array();
200
+ if (!$dir)
201
+ $dir = $this->directories;
202
+
203
+ foreach (array_reverse($dir) as $dir) {
204
+ $path = implode(DIRECTORY_SEPARATOR, array(
205
+ rtrim($dir, "/\\"),
206
+ '*.css'
207
+ ));
208
+ $files = glob($path);
209
+ if (is_array($files)) foreach ($files as $abspath) {
210
+ if (($meta = $this->get_stylesheet_metadata($abspath))) {
211
+ $filename = $meta['filename'];
212
+ $retval[$filename] = $meta;
213
+ }
214
+ }
215
+ }
216
+
217
+ return $retval;
218
+ }
219
+
220
+ /**
221
+ * Gets the metadata for a particular stylesheet
222
+ * @param $abspath
223
+ * @return array
224
+ */
225
+ function get_stylesheet_metadata($abspath)
226
+ {
227
+ $retval = array();
228
+ $contents = file_get_contents($abspath);
229
+ $name = '';
230
+ $desc = '';
231
+ $version = '';
232
+ $author = '';
233
+
234
+ // Find the name of the stylesheet
235
+ if (preg_match("/CSS Name:(.*)/i", $contents, $match)) {
236
+ $name = trim($match[1]);
237
+ }
238
+
239
+ // Find the description of the stylesheet
240
+ if (preg_match("/Description:(.*)/", $contents, $match)) {
241
+ $desc = trim($match[1]);
242
+ }
243
+
244
+ // Find the author of the stylesheet
245
+ if (preg_match("/Author:(.*)/", $contents, $match)) {
246
+ $author = trim($match[1]);
247
+ }
248
+
249
+ // Find the version of the stylesheet
250
+ if (preg_match("/Version:(.*)/", $contents, $match)) {
251
+ $version = trim($match[1]);
252
+ }
253
+
254
+ if ($name) {
255
+ $retval = array(
256
+ 'filename' => basename($abspath),
257
+ 'abspath' => $abspath,
258
+ 'name' => $name,
259
+ 'description' => $desc,
260
+ 'author' => $author,
261
+ 'version' => $version
262
+ );
263
+ }
264
+
265
+ return $retval;
266
+ }
267
+
268
+ /**
269
+ * Gets an instance of the class
270
+ * @return C_NextGen_Style_Manager
271
+ */
272
+ static function get_instance()
273
+ {
274
+ if (is_null(self::$_instance)){
275
+ $klass = get_class();
276
+ self::$_instance = new $klass();
277
+ }
278
+ return self::$_instance;
279
+ }
280
+ }
non_pope/class.photocrati_cache.php CHANGED
@@ -51,7 +51,7 @@ class C_Photocrati_Cache
51
  * @param null $value
52
  * @return bool|int
53
  */
54
- static function set($key, $value=NULL, $group=NULL, $ttl=3600)
55
  {
56
  return self::get_instance($group)->update($key, $value, $ttl);
57
  }
@@ -85,8 +85,9 @@ class C_Photocrati_Cache
85
  /**
86
  * Flush the entire cache
87
  */
88
- static function flush($group=NULL)
89
  {
 
90
  $retval = 0;
91
 
92
  if (self::$enabled) {
@@ -94,36 +95,118 @@ class C_Photocrati_Cache
94
  // Delete all caches
95
  if ($group == 'all') {
96
  foreach (self::$_instances as $cache) {
97
- $retval += self::flush($cache->group);
98
  }
99
  }
100
 
101
  // Delete items from a single cache in particular
102
  else {
103
- foreach (self::get_key_list($group) as $key) {
104
- self::delete($key, FALSE, $group);
 
 
 
 
 
 
 
 
 
105
  }
106
 
107
- // Delete list of cached items
108
- global $wpdb;
109
- $cache = self::get_instance($group);
110
- $sql = $wpdb->prepare("DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", '%'.$cache->group.'%');
111
- $retval = $wpdb->query($sql);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
  }
114
 
115
  return $retval;
116
  }
117
 
118
- static function get_key_list($group=NULL)
119
  {
120
  global $wpdb;
121
 
122
  $cache = self::get_instance($group);
123
- $sql = $wpdb->prepare("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s", '%'.$cache->group.'%');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  return $wpdb->get_col($sql);
125
  }
126
 
 
 
 
 
 
127
 
128
  /**
129
  * Gets an item using a particular key
@@ -149,14 +232,17 @@ class C_Photocrati_Cache
149
  * @param $value
150
  * @return bool|int
151
  */
152
- function update($key, $value, $ttl=3600)
153
  {
 
 
154
  $retval = FALSE;
155
  if (self::$enabled) {
156
  if (is_array($key)) $key = self::generate_key($key);
157
  if (self::$force_update OR $this->lookup($key, FALSE) === FALSE) {
158
  set_transient($key, $value, $ttl);
159
- update_option($this->group.$key, 1);
 
160
  $retval = $key;
161
  }
162
  }
@@ -176,4 +262,4 @@ class C_Photocrati_Cache
176
  }
177
  else return FALSE;
178
  }
179
- }
51
  * @param null $value
52
  * @return bool|int
53
  */
54
+ static function set($key, $value=NULL, $group=NULL, $ttl=NULL)
55
  {
56
  return self::get_instance($group)->update($key, $value, $ttl);
57
  }
85
  /**
86
  * Flush the entire cache
87
  */
88
+ static function flush($group=NULL, $expired_only=FALSE)
89
  {
90
+ ini_set('memory_limit', -1);
91
  $retval = 0;
92
 
93
  if (self::$enabled) {
95
  // Delete all caches
96
  if ($group == 'all') {
97
  foreach (self::$_instances as $cache) {
98
+ $retval += self::flush($cache->group, $expired_only);
99
  }
100
  }
101
 
102
  // Delete items from a single cache in particular
103
  else {
104
+ $cache = self::get_instance($group);
105
+
106
+ // Determine if the object cache is external, and not stored in the DB
107
+ // If it's external, we have to delete each transient, one by one
108
+ global $_wp_using_ext_object_cache, $wpdb;
109
+ if ($_wp_using_ext_object_cache) {
110
+ $keys = ($expired_only ? self::get_expired_key_list($group) : self::get_key_list($group));
111
+ foreach ($keys as $key) $cache->delete($key, FALSE);
112
+ $sql = $wpdb->prepare("DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", "%%{$cache->group}%%");
113
+ if ($expired_only) $sql .= " AND option_value < ".time();
114
+ $retval = $wpdb->query($sql);
115
  }
116
 
117
+ // Transients are stored in the database
118
+ else {
119
+ $keys = ($expired_only ? self::get_expired_key_list($group) : self::get_key_list($group));
120
+ if ($keys) {
121
+ $all_keys = array();
122
+ foreach ($keys as $value) {
123
+ $all_keys[] = "'{$cache->group}{$value}'";
124
+ $all_keys[] = "'_transient_timeout_{$value}'";
125
+ $all_keys[] = "'_transient_{$value}'";
126
+ }
127
+
128
+ // Determine the maximum packet size for the MySQL server
129
+ $max_packet_size = 1000000; // 1 MB
130
+ if ($row = $wpdb->get_row("SHOW VARIABLES LIKE 'max_allowed_packet'")) {
131
+ $max_packet_size = intval($row->Value);
132
+ }
133
+ $precision = -6;
134
+ if ($max_packet_size <1000000) $precision = -5;
135
+ if ($max_packet_size <100000) $precision = -4;
136
+ if ($max_packet_size <10000) $precision = -3;
137
+ if ($max_packet_size <1000) $precision = -2;
138
+
139
+ if (version_compare(PHP_VERSION, '5.3.0') >= 0)
140
+ $max_packet_size = round($max_packet_size, $precision, PHP_ROUND_HALF_DOWN);
141
+ else
142
+ $max_packet_size = round($max_packet_size, $precision);
143
+
144
+ // Generate DELETE queries up to $max_packet_size
145
+ $keys = array();
146
+ $average_key_size = strlen($all_keys[0])+15;
147
+ $count = 1000; // 1 KB buffer
148
+ while (($key = array_pop($all_keys))) {
149
+
150
+ if (($count + $average_key_size) < $max_packet_size) {
151
+ $keys[] = $key;
152
+ $count += $average_key_size;
153
+ }
154
+ else {
155
+ $keys = implode(',', $keys);
156
+ $sql = "DELETE FROM {$wpdb->options} WHERE option_name IN (". $keys. ')';
157
+ if (strlen($sql) > $max_packet_size) error_log("Delete transient query larger than max_allowed_packet for MySQL");
158
+ else $retval += $wpdb->query($sql);
159
+ $count = 1000;
160
+ $keys = array();
161
+ }
162
+ }
163
+
164
+ // If the number of keys to delete is less than the max packet size, then we should still
165
+ // delete the records
166
+ if (!$retval && $keys) {
167
+ $keys = implode(',', $keys);
168
+ $sql = "DELETE FROM {$wpdb->options} WHERE option_name IN (". $keys. ')';
169
+ if (strlen($sql) > $max_packet_size) error_log("Delete transient query larger than max_allowed_packet for MySQL");
170
+ else $retval += $wpdb->query($sql);
171
+ }
172
+ }
173
+ }
174
  }
175
  }
176
 
177
  return $retval;
178
  }
179
 
180
+ static function get_key_list($group=NULL, $strip_group_name=TRUE, $expired_only=FALSE)
181
  {
182
  global $wpdb;
183
 
184
  $cache = self::get_instance($group);
185
+
186
+ $sql = '';
187
+ if ($strip_group_name) {
188
+ $sql = $wpdb->prepare(
189
+ "SELECT REPLACE(option_name, %s, '') FROM {$wpdb->options} WHERE option_name LIKE %s",
190
+ $cache->group, '%'.$cache->group.'%'
191
+ );
192
+ }
193
+ else {
194
+ $sql = $wpdb->prepare(
195
+ "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
196
+ '%'.$cache->group.'%'
197
+ );
198
+ }
199
+
200
+ if ($expired_only) $sql .= " AND option_value < ".time();
201
+
202
  return $wpdb->get_col($sql);
203
  }
204
 
205
+ static function get_expired_key_list($group=NULL, $strip_group_name=TRUE)
206
+ {
207
+ return self::get_key_list($group, $strip_group_name, TRUE);
208
+ }
209
+
210
 
211
  /**
212
  * Gets an item using a particular key
232
  * @param $value
233
  * @return bool|int
234
  */
235
+ function update($key, $value, $ttl=NULL)
236
  {
237
+ if (!$ttl) $ttl = PHOTOCRATI_CACHE_TTL;
238
+
239
  $retval = FALSE;
240
  if (self::$enabled) {
241
  if (is_array($key)) $key = self::generate_key($key);
242
  if (self::$force_update OR $this->lookup($key, FALSE) === FALSE) {
243
  set_transient($key, $value, $ttl);
244
+ delete_option($this->group.$key);
245
+ add_option($this->group.$key, time()+$ttl, NULL, 'no');
246
  $retval = $key;
247
  }
248
  }
262
  }
263
  else return FALSE;
264
  }
265
+ }
non_pope/class.photocrati_installer.php CHANGED
@@ -54,37 +54,139 @@ if (!class_exists('C_Photocrati_Installer'))
54
  if (method_exists($handler, 'uninstall')) return $handler->uninstall($hard);
55
 
56
  if ($hard) {
57
- C_NextGen_Global_Settings::get_instance()->destroy();
58
  C_NextGen_Settings::get_instance()->destroy();
 
59
  }
60
  }
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  static function update($reset=FALSE)
63
  {
64
- $global_settings = C_NextGen_Global_Settings::get_instance();
65
- $local_settings = C_NextGen_Settings::get_instance();
66
- $last_module_list = $reset ? array() : $global_settings->get('pope_module_list', array());
67
- $current_module_list = self::_generate_module_info();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
- $global_settings->set('pope_module_list', $current_module_list);
 
 
 
 
 
 
70
 
71
- if (count(($modules = array_diff($current_module_list, $last_module_list)))>0) {
 
 
 
 
 
 
 
 
 
72
 
73
  // The cache should be flushed
74
  C_Photocrati_Cache::flush();
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  foreach ($modules as $module_name) {
77
  if (($handler = self::get_handler_instance(array_shift(explode('|', $module_name))))) {
78
- if (method_exists($handler, 'install')) $handler->install($reset);
 
79
  }
80
  }
81
 
 
 
 
 
 
 
 
 
 
 
 
82
  // Save any changes settings
83
  $global_settings->save();
84
  $local_settings->save();
85
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  }
87
 
 
 
 
 
 
 
 
 
 
 
 
88
  static function _generate_module_info()
89
  {
90
  $retval = array();
@@ -95,5 +197,24 @@ if (!class_exists('C_Photocrati_Installer'))
95
  }
96
  return $retval;
97
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  }
99
  }
54
  if (method_exists($handler, 'uninstall')) return $handler->uninstall($hard);
55
 
56
  if ($hard) {
 
57
  C_NextGen_Settings::get_instance()->destroy();
58
+ C_NextGen_Global_Settings::get_instance()->destroy();
59
  }
60
  }
61
 
62
+ static function can_do_upgrade()
63
+ {
64
+ $proceed = FALSE;
65
+ if (!get_option('ngg_doing_upgrade', FALSE)) {
66
+ update_option('ngg_doing_upgrade', TRUE);
67
+ $proceed = TRUE;
68
+ }
69
+ return $proceed;
70
+ }
71
+
72
+ static function done_upgrade()
73
+ {
74
+ update_option('ngg_doing_upgrade', FALSE);
75
+ }
76
+
77
  static function update($reset=FALSE)
78
  {
79
+ $local_settings = C_NextGen_Settings::get_instance();
80
+ $global_settings = C_NextGen_Global_Settings::get_instance();
81
+
82
+ // This is a specific hack/work-around/fix and can probably be removed sometime after 2.0.20's release
83
+ //
84
+ // NextGen 2x was not multisite compatible until 2.0.18. Users that upgraded before this
85
+ // will have nearly all of their settings stored globally (network wide) in wp_sitemeta. If
86
+ // pope_module_list (which should always be a local setting) exists site-wide we wipe the current
87
+ // global ngg_options and restore from defaults. This should only ever run once.
88
+ if (is_multisite() && isset($global_settings->pope_module_list))
89
+ {
90
+ // Setting this to TRUE will wipe current settings for display types, but also
91
+ // allows the display type installer to run correctly
92
+ $reset = TRUE;
93
+
94
+ $settings_installer = new C_NextGen_Settings_Installer();
95
+ $global_defaults = $settings_installer->get_global_defaults();
96
+
97
+ // Preserve the network options we honor by restoring them after calling $global_settings->reset()
98
+ $global_settings_to_keep = array();
99
+ foreach ($global_defaults as $key => $val) {
100
+ $global_settings_to_keep[$key] = $global_settings->$key;
101
+ }
102
+
103
+ // Resets internal options to an empty array
104
+ $global_settings->reset();
105
 
106
+ // Restore the defaults, then our saved values. This must be done again later because
107
+ // we've set $reset to TRUE.
108
+ $settings_installer->install_global_settings();
109
+ foreach ($global_settings_to_keep as $key => $val) {
110
+ $global_settings->$key = $val;
111
+ }
112
+ }
113
 
114
+ $last_module_list = self::_get_last_module_list($reset);
115
+ $current_module_list = self::_generate_module_info();
116
+
117
+ if (count(($modules = array_diff($current_module_list, $last_module_list))) > 0 && self::can_do_upgrade())
118
+ {
119
+ // Clear APC cache
120
+ if (function_exists('apc_clear_cache')) {
121
+ @apc_clear_cache('opcode');
122
+ apc_clear_cache();
123
+ }
124
 
125
  // The cache should be flushed
126
  C_Photocrati_Cache::flush();
127
 
128
+ // Remove all NGG created cron jobs
129
+ self::refresh_cron();
130
+
131
+ // Delete auto-update cache
132
+ update_option('photocrati_auto_update_admin_update_list', null);
133
+ update_option('photocrati_auto_update_admin_check_date', '');
134
+
135
+ // Other Pope applications might be loaded, and therefore
136
+ // all singletons should be destroyed, so that they can be
137
+ // adapted as necessary. For now, we'll just assume that the factory
138
+ // is the only singleton that will be used by other Pope applications
139
+ C_Component_Factory::$_instances = array();
140
+
141
  foreach ($modules as $module_name) {
142
  if (($handler = self::get_handler_instance(array_shift(explode('|', $module_name))))) {
143
+ if (method_exists($handler, 'install'))
144
+ $handler->install($reset);
145
  }
146
  }
147
 
148
+ // Update the module list
149
+ $local_settings->set('pope_module_list', $current_module_list);
150
+
151
+ // NOTE & TODO: if the above section that declares $global_settings_to_keep is removed this should also
152
+ // Since a hard-reset of the settings was forced we must again re-apply our previously saved values
153
+ if (isset($global_settings_to_keep)) {
154
+ foreach ($global_settings_to_keep as $key => $val) {
155
+ $global_settings->$key = $val;
156
+ }
157
+ }
158
+
159
  // Save any changes settings
160
  $global_settings->save();
161
  $local_settings->save();
162
+
163
+ self::done_upgrade();
164
+ }
165
+
166
+ // Another workaround to an issue caused by NextGen's lack of multisite compatibility. It's possible
167
+ // the string substitation wasn't performed, so if a '%' symbol exists in gallerypath we reset it. It's
168
+ // another db call, but again this should only ever run once.
169
+ //
170
+ // Remove this when removing the above reset-global-settings code
171
+ if (strpos($local_settings->gallerypath, '%'))
172
+ {
173
+ $settings_installer = new C_NextGen_Settings_Installer();
174
+ $local_settings->gallerypath = $settings_installer->gallerypath_replace($global_settings->gallerypath);
175
+ $local_settings->save();
176
+ }
177
  }
178
 
179
+ static function _get_last_module_list($reset=FALSE)
180
+ {
181
+ $retval = array();
182
+ $local_settings = C_NextGen_Settings::get_instance();
183
+ $last_module_list = $local_settings->get('pope_module_list');
184
+ if (is_array($last_module_list) AND !$reset) foreach ($last_module_list as $key => $value) {
185
+ $retval[] = $value;
186
+ }
187
+ return $retval;
188
+ }
189
+
190
  static function _generate_module_info()
191
  {
192
  $retval = array();
197
  }
198
  return $retval;
199
  }
200
+
201
+ static function refresh_cron()
202
+ {
203
+ @ini_set('memory_limit', -1);
204
+
205
+ // Remove all cron jobs created by NextGEN Gallery
206
+ $cron = _get_cron_array();
207
+ if (is_array($cron)) {
208
+ foreach ($cron as $timestamp => $job) {
209
+ if (is_array($job)) {
210
+ unset($cron[$timestamp]['ngg_delete_expired_transients']);
211
+ if (empty($cron[$timestamp])) {
212
+ unset($cron[$timestamp]);
213
+ }
214
+ }
215
+ }
216
+ }
217
+ _set_cron_array($cron);
218
+ }
219
  }
220
  }
non_pope/class.photocrati_resource_manager.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class C_Photocrati_Resource_Manager
4
+ {
5
+ static $instance = NULL;
6
+
7
+ public $marker = '<!-- ngg_resource_manager_marker -->';
8
+
9
+ var $buffer = '';
10
+ var $styles = '';
11
+ var $scripts = '';
12
+ var $other_output = '';
13
+ var $wrote_footer = FALSE;
14
+ var $run_shutdown = FALSE;
15
+ var $valid_request = TRUE;
16
+
17
+ /**
18
+ * Start buffering all generated output. We'll then do two things with the buffer
19
+ * 1) Find stylesheets lately enqueued and move them to the header
20
+ * 2) Ensure that wp_print_footer_scripts() is called
21
+ */
22
+ function __construct()
23
+ {
24
+ // Validate the request
25
+ $this->validate_request();
26
+ add_action('init', array(&$this, 'start_buffer'), 1);
27
+ add_action('wp_footer', array(&$this, 'print_marker'), -1);
28
+ }
29
+
30
+ /**
31
+ * Created early as possible in the wp_footer action this is the string to which we
32
+ * will move JS resources after
33
+ */
34
+ function print_marker()
35
+ {
36
+ print $this->marker;
37
+ }
38
+
39
+ /**
40
+ * Determines if the resource manager should perform it's routines for this request
41
+ * @return bool
42
+ */
43
+ function validate_request()
44
+ {
45
+ $retval = TRUE;
46
+
47
+ if (is_admin()) {
48
+ if (isset($_REQUEST['page']) && !preg_match("#^(ngg|nextgen)#", $_REQUEST['page'])) $retval = FALSE;
49
+ }
50
+
51
+ if (strpos($_SERVER['REQUEST_URI'], 'wp-admin/update') !== FALSE) $retval = FALSE;
52
+ else if (isset($_GET['display_gallery_iframe'])) $retval = FALSE;
53
+ else if (defined('WP_ADMIN') && WP_ADMIN && defined('DOING_AJAX') && DOING_AJAX) $retval = FALSE;
54
+ else if (preg_match("/(js|css|xsl|xml|kml)$/", $_SERVER['REQUEST_URI'])) $retval = FALSE;
55
+ elseif (preg_match("/\\.(\\w{3,4})$/", $_SERVER['REQUEST_URI'], $match)) {
56
+ if (!in_array($match[1], array('htm', 'html', 'php'))) {
57
+ $retval = FALSE;
58
+ }
59
+ }
60
+
61
+ $this->valid_request = $retval;
62
+ }
63
+
64
+ /**
65
+ * Start the output buffers
66
+ */
67
+ function start_buffer()
68
+ {
69
+ if (defined('NGG_DISABLE_RESOURCE_MANAGER') && NGG_DISABLE_RESOURCE_MANAGER)
70
+ return;
71
+
72
+ if (apply_filters('run_ngg_resource_manager', $this->valid_request)) {
73
+ ob_start(array(&$this, 'output_buffer_handler'));
74
+ ob_start(array(&$this, 'get_buffer'));
75
+
76
+ add_action('wp_print_footer_scripts', array(&$this, 'get_resources'), 1);
77
+ add_action('admin_print_footer_scripts', array(&$this, 'get_resources'), 1);
78
+ add_action('shutdown', array(&$this, 'shutdown'));
79
+ }
80
+ }
81
+
82
+ /**
83
+ *
84
+ **/
85
+ function get_resources()
86
+ {
87
+ ob_start();
88
+ wp_print_styles();
89
+ print_admin_styles();
90
+ $this->styles = ob_get_clean();
91
+
92
+ if (!is_admin()) {
93
+ ob_start();
94
+ wp_print_scripts();
95
+ $this->scripts = ob_get_clean();
96
+ }
97
+
98
+ $this->wrote_footer = TRUE;
99
+ }
100
+
101
+ /**
102
+ * Output the buffer after PHP execution has ended (but before shutdown)
103
+ * @param $content
104
+ * @return string
105
+ */
106
+ function output_buffer_handler($content)
107
+ {
108
+ return $this->output_buffer();
109
+ }
110
+
111
+ /**
112
+ * Removes the closing </html> tag from the output buffer. We'll then write our own closing tag
113
+ * in the shutdown function after running wp_print_footer_scripts()
114
+ * @param $content
115
+ * @return mixed
116
+ */
117
+ function get_buffer($content)
118
+ {
119
+ $this->buffer = $content;
120
+ return '';
121
+ }
122
+
123
+ /**
124
+ * Moves resources to their appropriate place
125
+ */
126
+ function move_resources()
127
+ {
128
+ if ($this->valid_request) {
129
+ // Move stylesheets to head
130
+ if ($this->styles) {
131
+ $this->buffer = str_ireplace('</head>', $this->styles.'</head>', $this->buffer);
132
+ }
133
+
134
+ // Move the scripts to the bottom of the page
135
+ if ($this->scripts) {
136
+ $this->buffer = str_ireplace($this->marker, $this->marker . $this->scripts, $this->buffer);
137
+ }
138
+
139
+ if ($this->other_output) {
140
+ $this->buffer = str_replace($this->marker, $this->marker . $this->other_output, $this->buffer);
141
+ }
142
+ }
143
+ }
144
+
145
+ /**
146
+ * When PHP has finished, we output the footer scripts and closing tags
147
+ */
148
+ function output_buffer($in_shutdown=FALSE)
149
+ {
150
+ // If the footer scripts haven't been outputted, then
151
+ // we need to take action - as they're required
152
+ if (!$this->wrote_footer) {
153
+
154
+ // If W3TC is installed and activated, we can't output the
155
+ // scripts and manipulate the buffer, so we can only provide a warning
156
+ if (defined('W3TC') && defined('WP_DEBUG') && WP_DEBUG && !is_admin()) {
157
+ if (!defined('DONOTCACHEPAGE')) define('DONOTCACHEPAGE', TRUE);
158
+ if (!did_action('wp_footer')) {
159
+ error_log("We're sorry, but your theme's page template didn't make a call to wp_footer(), which is required by NextGEN Gallery. Please add this call to your page templates.");
160
+ }
161
+ else {
162
+ error_log("We're sorry, but your theme's page template didn't make a call to wp_print_footer_scripts(), which is required by NextGEN Gallery. Please add this call to your page templates.");
163
+ }
164
+ }
165
+
166
+ // We don't want to manipulate the buffer if it doesn't contain HTML
167
+ elseif (strpos($this->buffer, '</body>') === FALSE) {
168
+ $this->valid_request = FALSE;
169
+ }
170
+
171
+ // The output_buffer() function has been called in the PHP shutdown callback
172
+ // This will allow us to print the scripts ourselves and manipulate the buffer
173
+ if ($in_shutdown === TRUE) {
174
+ ob_start();
175
+ if (!did_action('wp_footer')) {
176
+ wp_footer();
177
+ }
178
+ else {
179
+ wp_print_footer_scripts();
180
+ }
181
+ $this->other_output = ob_get_clean();
182
+
183
+ }
184
+
185
+ // W3TC isn't activated and we're not in the shutdown callback.
186
+ // We'll therefore add a shutdown callback to print the scripts
187
+ else {
188
+ $this->run_shutdown = TRUE;
189
+ return '';
190
+ }
191
+ }
192
+
193
+ // Once we have the footer scripts, we can modify the buffer and
194
+ // move the resources around
195
+ if ($this->wrote_footer) $this->move_resources();
196
+
197
+ return $this->buffer;
198
+ }
199
+
200
+ /**
201
+ * PHP shutdown callback. Manipulate and output the buffer
202
+ */
203
+ function shutdown()
204
+ {
205
+ if ($this->run_shutdown) echo $this->output_buffer(TRUE);
206
+ }
207
+
208
+ static function init()
209
+ {
210
+ $klass = get_class();
211
+ return self::$instance = new $klass;
212
+ }
213
+ }
non_pope/class.photocrati_settings_manager.php CHANGED
@@ -7,9 +7,10 @@ if (!class_exists('C_Photocrati_Settings_Manager_Base')) {
7
  */
8
  abstract class C_Photocrati_Settings_Manager_Base implements ArrayAccess
9
  {
10
- static $option_name = 'pope_settings';
11
- protected $_options = array();
12
- protected $_defaults = array();
 
13
 
14
  abstract function save();
15
  abstract function destroy();
@@ -20,6 +21,39 @@ if (!class_exists('C_Photocrati_Settings_Manager_Base')) {
20
  $this->load();
21
  }
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * Gets the value of a particular setting
25
  * @param $key
@@ -32,6 +66,9 @@ if (!class_exists('C_Photocrati_Settings_Manager_Base')) {
32
 
33
  if (isset($this->_options[$key]))
34
  $retval = $this->_options[$key];
 
 
 
35
 
36
  // In case a stdObject has been passed in as a value, we
37
  // want to only return scalar values or arrays
@@ -46,13 +83,16 @@ if (!class_exists('C_Photocrati_Settings_Manager_Base')) {
46
  * @param mixed $value
47
  * @return mixed
48
  */
49
- function set($key, $value=NULL)
50
  {
51
  if (is_object($value)) $value = (array) $value;
52
 
53
  if (is_array($key)) {
54
  foreach ($key as $k=>$v) $this->set($k, $v);
55
  }
 
 
 
56
  else $this->_options[$key] = $value;
57
 
58
  return $this;
@@ -64,7 +104,12 @@ if (!class_exists('C_Photocrati_Settings_Manager_Base')) {
64
  */
65
  function delete($key)
66
  {
67
- unset($this->_options[$key]);
 
 
 
 
 
68
  }
69
 
70
  /**
@@ -95,6 +140,7 @@ if (!class_exists('C_Photocrati_Settings_Manager_Base')) {
95
  function reset()
96
  {
97
  $this->_options = array();
 
98
  }
99
 
100
  /**
@@ -197,6 +243,7 @@ if (!class_exists('C_Photocrati_Global_Settings_Manager')) {
197
  {
198
  $this->_options = get_site_option(self::$option_name, $this->to_array());
199
  if (!$this->_options) $this->_options = array();
 
200
  }
201
 
202
  function destroy()
@@ -238,6 +285,8 @@ if (!class_exists('C_Photocrati_Settings_Manager')) {
238
  function load()
239
  {
240
  $this->_options = get_option(self::$option_name, array());
 
 
241
  }
242
 
243
  function destroy()
7
  */
8
  abstract class C_Photocrati_Settings_Manager_Base implements ArrayAccess
9
  {
10
+ static $option_name = 'pope_settings';
11
+ protected $_options = array();
12
+ protected $_defaults = array();
13
+ protected $_option_handlers = array();
14
 
15
  abstract function save();
16
  abstract function destroy();
21
  $this->load();
22
  }
23
 
24
+ /**
25
+ * Adds a class to handle dynamic options
26
+ * @param string $klass
27
+ * @param array $options
28
+ */
29
+ function add_option_handler($klass, $options=array())
30
+ {
31
+ if (!is_array($options)) $options = array($options);
32
+ foreach ($options as $option_name) {
33
+ $this->_option_handlers[$option_name] = $klass;
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Gets a handler used to provide a dynamic option
39
+ * @param string $option_name
40
+ * @return null|mixed
41
+ */
42
+ protected function _get_option_handler($option_name, $method='get')
43
+ {
44
+ $retval = NULL;
45
+
46
+ if (isset($this->_option_handlers[$option_name])) {
47
+ if (!is_object($this->_option_handlers[$option_name])) {
48
+ $klass = $this->_option_handlers[$option_name];
49
+ $this->_option_handlers[$option_name] = new $klass;
50
+ }
51
+ $retval = $this->_option_handlers[$option_name];
52
+ if (!method_exists($retval, $method)) $retval = NULL;
53
+ }
54
+ return $retval;
55
+ }
56
+
57
  /**
58
  * Gets the value of a particular setting
59
  * @param $key
66
 
67
  if (isset($this->_options[$key]))
68
  $retval = $this->_options[$key];
69
+ elseif (($handler = $this->_get_option_handler($key, 'get'))) {
70
+ $retval = $handler->get($key, $default);
71
+ }
72
 
73
  // In case a stdObject has been passed in as a value, we
74
  // want to only return scalar values or arrays
83
  * @param mixed $value
84
  * @return mixed
85
  */
86
+ function set($key, $value=NULL, $skip_handlers=FALSE)
87
  {
88
  if (is_object($value)) $value = (array) $value;
89
 
90
  if (is_array($key)) {
91
  foreach ($key as $k=>$v) $this->set($k, $v);
92
  }
93
+ elseif (!$skip_handlers && ($handler = $this->_get_option_handler($key, 'set'))) {
94
+ $handler->set($key, $value);
95
+ }
96
  else $this->_options[$key] = $value;
97
 
98
  return $this;
104
  */
105
  function delete($key)
106
  {
107
+ if (($handler = $this->_get_option_handler($key, 'delete'))) {
108
+ $handler->delete($key);
109
+ }
110
+ else {
111
+ unset($this->_options[$key]);
112
+ }
113
  }
114
 
115
  /**
140
  function reset()
141
  {
142
  $this->_options = array();
143
+ $this->_defaults = array();
144
  }
145
 
146
  /**
243
  {
244
  $this->_options = get_site_option(self::$option_name, $this->to_array());
245
  if (!$this->_options) $this->_options = array();
246
+ else if (is_string($this->_options)) $this->_options = unserialize($this->_options);
247
  }
248
 
249
  function destroy()
285
  function load()
286
  {
287
  $this->_options = get_option(self::$option_name, array());
288
+ if (!$this->_options) $this->_options = array();
289
+ else if (is_string($this->_options)) $this->_options = unserialize($this->_options);
290
  }
291
 
292
  function destroy()
pope/lib/autoload.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  if (!defined('POPE_VERSION')) {
4
- define('POPE_VERSION', '0.1');
5
  require_once('class.extensibleobject.php');
6
  require_once('interface.component.php');
7
  require_once('class.component.php');
1
  <?php
2
 
3
  if (!defined('POPE_VERSION')) {
4
+ define('POPE_VERSION', '0.6');
5
  require_once('class.extensibleobject.php');
6
  require_once('interface.component.php');
7
  require_once('class.component.php');
pope/lib/class.base_module.php CHANGED
@@ -33,7 +33,7 @@ abstract class C_Base_Module extends C_Component
33
  /**
34
  * Defines the module
35
  */
36
- function define($id, $name, $description='', $version='', $uri='', $author='', $author_uri='', $context=FALSE)
37
  {
38
  parent::define($context);
39
  $this->implement('I_Pope_Module');
@@ -145,7 +145,7 @@ abstract class C_Base_Module extends C_Component
145
  {
146
  return $path;
147
  }
148
- return trim($base, '/') . '/' . ltrim($path, '/');
149
  }
150
 
151
  /**
33
  /**
34
  * Defines the module
35
  */
36
+ function define($id='pope-module', $name='Pope Module', $description='', $version='', $uri='', $author='', $author_uri='', $context=FALSE)
37
  {
38
  parent::define($context);
39
  $this->implement('I_Pope_Module');
145
  {
146
  return $path;
147
  }
148
+ return trim($base, "/\\") . DIRECTORY_SEPARATOR . ltrim($path, "/\\");
149
  }
150
 
151
  /**
pope/lib/class.base_product.php CHANGED
@@ -12,9 +12,9 @@ if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) { die('You
12
  */
13
  abstract class C_Base_Product extends C_Base_Module
14
  {
15
- function define($id, $name, $description='', $version='', $uri='', $author='', $author_uri='')
16
  {
17
- parent::define($id, $name, $description, $version, $uri, $author, $author_uri);
18
 
19
  $this->get_registry()->add_product($this->module_id, $this);
20
  }
12
  */
13
  abstract class C_Base_Product extends C_Base_Module
14
  {
15
+ function define($id='pope-product', $name='Pope Product', $description='', $version='', $uri='', $author='', $author_uri='', $context=FALSE)
16
  {
17
+ parent::define($id, $name, $description, $version, $uri, $author, $author_uri, $context);
18
 
19
  $this->get_registry()->add_product($this->module_id, $this);
20
  }
pope/lib/class.component_factory.php CHANGED
@@ -7,9 +7,9 @@ class C_Component_Factory extends C_Component
7
  {
8
  static $_instances = array();
9
 
10
- function define()
11
  {
12
- parent::define();
13
  $this->implement('I_Component_Factory');
14
  }
15
 
7
  {
8
  static $_instances = array();
9
 
10
+ function define($context=FALSE)
11
  {
12
+ parent::define($context);
13
  $this->implement('I_Component_Factory');
14
  }
15
 
pope/lib/class.extensibleobject.php CHANGED
@@ -2,6 +2,10 @@
2
  define('__EXTOBJ_STATIC__', '__STATICALLY_CALLED__');
3
  define('__EXTOBJ_NO_INIT__', '__NO_INIT__');
4
 
 
 
 
 
5
 
6
  /**
7
  * Provides helper methods for Pope objects
@@ -162,7 +166,7 @@ class ExtensibleObject extends PopeHelpers
162
  // call_user_func_array(array($this, 'define'), $args);
163
  }
164
 
165
- $this->_enforce_interface_contracts();
166
 
167
  if ($init_instance)
168
  {
@@ -750,7 +754,7 @@ class ExtensibleObject extends PopeHelpers
750
  */
751
  function __call($method, $args)
752
  {
753
- $this->clear_method_properties($method, $args);
754
 
755
  // Run pre hooks?
756
  if ($this->are_pre_hooks_enabled($method) && $this->get_method_property($method, self::METHOD_PROPERTY_RUN_PRE_HOOKS)) {
@@ -833,7 +837,10 @@ class ExtensibleObject extends PopeHelpers
833
  }
834
  }
835
 
836
- return $this->get_method_property($method, self::METHOD_PROPERTY_RETURN_VALUE);
 
 
 
837
  }
838
 
839
 
@@ -1181,7 +1188,7 @@ class ExtensibleObject extends PopeHelpers
1181
  * before every method call (before pre-hooks)
1182
  * @param string $method
1183
  */
1184
- function clear_method_properties($method, $args=array())
1185
  {
1186
  $this->_method_properties[$method] = array(
1187
  'run' => TRUE,
@@ -1191,6 +1198,35 @@ class ExtensibleObject extends PopeHelpers
1191
  );
1192
  }
1193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1194
 
1195
  /**
1196
  * Returns TRUE if the ExtensibleObject has decided to implement a
@@ -1291,6 +1327,9 @@ class Mixin extends PopeHelpers
1291
  $backtrace = debug_backtrace();
1292
  $klass = get_class($backtrace[0]['object']);
1293
 
 
 
 
1294
  // Perform the routine described above...
1295
  $this->object->disable_pre_hooks($method);
1296
  $this->object->disable_post_hooks($method);
@@ -1308,6 +1347,9 @@ class Mixin extends PopeHelpers
1308
  $this->object->enable_post_hooks($method);
1309
  $this->object->enable_mixin($method, $klass);
1310
 
 
 
 
1311
  return $retval;
1312
  }
1313
 
@@ -1366,7 +1408,7 @@ class Hook extends Mixin
1366
  * Provides an alias for call_anchor, as there's no parent
1367
  * to call in the context of a hook.
1368
  */
1369
- function call_parent()
1370
  {
1371
  $args = func_get_args();
1372
  return call_user_func_array(
2
  define('__EXTOBJ_STATIC__', '__STATICALLY_CALLED__');
3
  define('__EXTOBJ_NO_INIT__', '__NO_INIT__');
4
 
5
+ if (!defined('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES')) {
6
+ define('EXTENSIBLE_OBJECT_ENFORCE_INTERFACES', TRUE);
7
+ }
8
+
9
 
10
  /**
11
  * Provides helper methods for Pope objects
166
  // call_user_func_array(array($this, 'define'), $args);
167
  }
168
 
169
+ if (EXTENSIBLE_OBJECT_ENFORCE_INTERFACES) $this->_enforce_interface_contracts();
170
 
171
  if ($init_instance)
172
  {
754
  */
755
  function __call($method, $args)
756
  {
757
+ $this->reset_method_properties($method, $args);
758
 
759
  // Run pre hooks?
760
  if ($this->are_pre_hooks_enabled($method) && $this->get_method_property($method, self::METHOD_PROPERTY_RUN_PRE_HOOKS)) {
837
  }
838
  }
839
 
840
+ // Get return value, clear all method properties, and then return
841
+ $retval = $this->get_method_property($method, self::METHOD_PROPERTY_RETURN_VALUE);
842
+ $this->remove_method_properties($method);
843
+ return $retval;
844
  }
845
 
846
 
1188
  * before every method call (before pre-hooks)
1189
  * @param string $method
1190
  */
1191
+ function reset_method_properties($method, $args=array())
1192
  {
1193
  $this->_method_properties[$method] = array(
1194
  'run' => TRUE,
1198
  );
1199
  }
1200
 
1201
+ /**
1202
+ * Removes the cache of the method properties
1203
+ * @param $method
1204
+ */
1205
+ function remove_method_properties($method)
1206
+ {
1207
+ unset($this->_method_properties[$method]);
1208
+ }
1209
+
1210
+ /**
1211
+ * Gets all method properties
1212
+ * @return array
1213
+ */
1214
+ function get_method_properties($method)
1215
+ {
1216
+ return $this->_method_properties[$method];
1217
+ }
1218
+
1219
+ /**
1220
+ * Sets all method properties
1221
+ * @param $method
1222
+ * @param $props
1223
+ */
1224
+ function set_method_properties($method, $props)
1225
+ {
1226
+ foreach ($props as $key => $value) {
1227
+ $this->set_method_property($method, $key, $value);
1228
+ }
1229
+ }
1230
 
1231
  /**
1232
  * Returns TRUE if the ExtensibleObject has decided to implement a
1327
  $backtrace = debug_backtrace();
1328
  $klass = get_class($backtrace[0]['object']);
1329
 
1330
+ // Get the method properties. We'll store this afterwards.
1331
+ $props = $this->object->get_method_properties($method);
1332
+
1333
  // Perform the routine described above...
1334
  $this->object->disable_pre_hooks($method);
1335
  $this->object->disable_post_hooks($method);
1347
  $this->object->enable_post_hooks($method);
1348
  $this->object->enable_mixin($method, $klass);
1349
 
1350
+ // Re-set all method properties
1351
+ $this->object->set_method_properties($method, $props);
1352
+
1353
  return $retval;
1354
  }
1355
 
1408
  * Provides an alias for call_anchor, as there's no parent
1409
  * to call in the context of a hook.
1410
  */
1411
+ function call_parent($method)
1412
  {
1413
  $args = func_get_args();
1414
  return call_user_func_array(
products/photocrati_nextgen/modules/ajax/class.ajax_controller.php CHANGED
@@ -12,13 +12,11 @@ class C_Ajax_Controller extends C_MVC_Controller
12
 
13
  function index_action()
14
  {
15
- $retval = FALSE;
16
- $error_reporting = error_reporting(
17
- E_CORE_ERROR|E_CORE_WARNING|E_COMPILE_ERROR|E_ERROR|E_PARSE|E_USER_ERROR|E_USER_WARNING|E_RECOVERABLE_ERROR
18
- );
19
 
20
- // Inform the MVC framework what type of content we're returning
21
- $this->set_content_type('json');
22
 
23
  // Get the action requested & find and execute the related method
24
  if (($action = $this->param('action'))) {
@@ -29,14 +27,16 @@ class C_Ajax_Controller extends C_MVC_Controller
29
  }
30
 
31
  // If no retval has been set, then return an error
32
- if (!$retval)
33
  $retval = array('error' => 'Not a valid AJAX action');
34
 
 
 
 
 
 
35
  // Return the JSON to the browser
36
  echo json_encode($retval);
37
-
38
- // reset the reporting level
39
- error_reporting($error_reporting);
40
  }
41
 
42
  /**
12
 
13
  function index_action()
14
  {
15
+ // Inform the MVC framework what type of content we're returning
16
+ $this->set_content_type('json');
 
 
17
 
18
+ // Start an output buffer to avoid displaying any PHP warnings/errors
19
+ ob_start();
20
 
21
  // Get the action requested & find and execute the related method
22
  if (($action = $this->param('action'))) {
27
  }
28
 
29
  // If no retval has been set, then return an error
30
+ if (is_null($retval))
31
  $retval = array('error' => 'Not a valid AJAX action');
32
 
33
+ // Flush the buffer
34
+ while (ob_get_level() > 0 ) {
35
+ ob_end_clean();
36
+ }
37
+
38
  // Return the JSON to the browser
39
  echo json_encode($retval);
 
 
 
40
  }
41
 
42
  /**
products/photocrati_nextgen/modules/ajax/class.ajax_installer.php CHANGED
@@ -2,29 +2,12 @@
2
 
3
  class C_Ajax_Installer
4
  {
5
- function __construct()
6
- {
7
- $this->settings = C_NextGen_Global_Settings::get_instance();
8
- }
9
-
10
- function get_registry()
11
- {
12
- return C_Component_Registry::get_instance();
13
- }
14
-
15
  function install()
16
  {
17
- $slug = 'photocrati_ajax';
18
- $router = $this->get_registry()->get_utility('I_Router');
19
-
20
- $this->settings->set_default_value('ajax_slug', $slug);
21
- $this->settings->set_default_value('ajax_url', $router->get_url($slug, FALSE));
22
- $this->settings->set_default_value('ajax_js_url', $router->get_url($slug . '/js', FALSE));
23
- }
24
-
25
- function uninstall($hard=FALSE)
26
- {
27
- if ($hard) foreach (array('ajax_slug', 'ajax_url', 'ajax_js_url') as $key)
28
- $this->settings->delete($key);
29
  }
30
  }
2
 
3
  class C_Ajax_Installer
4
  {
 
 
 
 
 
 
 
 
 
 
5
  function install()
6
  {
7
+ // Delete cached values. Needed for 2.0.7 and less
8
+ $settings = C_NextGen_Settings::get_instance();
9
+ $settings->delete('ajax_url');
10
+ $settings->delete('ajax_slug');
11
+ $settings->delete('ajax_js_url');
 
 
 
 
 
 
 
12
  }
13
  }
products/photocrati_nextgen/modules/ajax/class.ajax_option_handler.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class C_Ajax_Option_Handler
4
+ {
5
+ private $slug = 'photocrati_ajax';
6
+
7
+ function get_router()
8
+ {
9
+ return C_Component_Registry::get_instance()->get_utility('I_Router');
10
+ }
11
+
12
+ function get($key, $default=NULL)
13
+ {
14
+ $retval = $default;
15
+
16
+ switch($key) {
17
+ case 'ajax_slug':
18
+ $retval = $this->slug;
19
+ break;
20
+ case 'ajax_url':
21
+ $retval = $this->get_router()->get_url($this->slug, FALSE);
22
+ break;
23
+ case 'ajax_js_url':
24
+ $retval = $this->get_router()->get_static_url('photocrati-ajax#ajax.js');
25
+ break;
26
+ }
27
+ return $retval;
28
+ }
29
+ }
products/photocrati_nextgen/modules/ajax/module.ajax.php CHANGED
@@ -14,12 +14,19 @@ class M_Ajax extends C_Base_Module
14
  'photocrati-ajax',
15
  'AJAX',
16
  'Provides AJAX functionality',
17
- '0.1',
18
  'http://www.photocrati.com',
19
  'Photocrati Media',
20
  'http://www.photocrati.com'
21
  );
22
 
 
 
 
 
 
 
 
23
  include_once('class.ajax_installer.php');
24
  C_Photocrati_Installer::add_handler($this->module_id, 'C_Ajax_Installer');
25
  }
@@ -40,8 +47,7 @@ class M_Ajax extends C_Base_Module
40
  */
41
  function _register_hooks()
42
  {
43
- add_action('init', array(&$this, 'enqueue_scripts'));
44
- add_action('admin_init', array(&$this, 'enqueue_scripts'));
45
  }
46
 
47
 
@@ -50,20 +56,27 @@ class M_Ajax extends C_Base_Module
50
  */
51
  function enqueue_scripts()
52
  {
53
- $settings = C_NextGen_Global_Settings::get_instance();
54
  $router = $this->get_registry()->get_utility('I_Router');
55
 
56
- $site_url = $router->get_base_url();
 
57
 
58
- wp_register_script('photocrati_ajax', $router->get_static_url('photocrati-ajax#ajax.js'));
59
  wp_enqueue_script('photocrati_ajax');
60
 
61
  $vars = array(
62
- 'url' => $settings->ajax_url,
63
- 'wp_site_url' => $site_url,
64
- 'wp_site_static_url' => str_replace('/index.php', '', $site_url)
65
  );
66
  wp_localize_script('photocrati_ajax', 'photocrati_ajax', $vars);
 
 
 
 
 
 
67
  }
68
 
69
  function get_type_list()
14
  'photocrati-ajax',
15
  'AJAX',
16
  'Provides AJAX functionality',
17
+ '0.7',
18
  'http://www.photocrati.com',
19
  'Photocrati Media',
20
  'http://www.photocrati.com'
21
  );
22
 
23
+ include_once('class.ajax_option_handler.php');
24
+ C_NextGen_Settings::add_option_handler('C_Ajax_Option_Handler', array(
25
+ 'ajax_slug',
26
+ 'ajax_url',
27
+ 'ajax_js_url'
28
+ ));
29
+
30
  include_once('class.ajax_installer.php');
31
  C_Photocrati_Installer::add_handler($this->module_id, 'C_Ajax_Installer');
32
  }
47
  */
48
  function _register_hooks()
49
  {
50
+ add_action('init', array(&$this, 'enqueue_scripts'), 9);
 
51
  }
52
 
53
 
56
  */
57
  function enqueue_scripts()
58
  {
59
+ $settings = C_NextGen_Settings::get_instance();
60
  $router = $this->get_registry()->get_utility('I_Router');
61
 
62
+ $site_url = $router->get_base_url(TRUE);
63
+ $home_url = $router->get_base_url();
64
 
65
+ wp_register_script('photocrati_ajax', $settings->ajax_js_url);
66
  wp_enqueue_script('photocrati_ajax');
67
 
68
  $vars = array(
69
+ 'url' => $router->get_url($settings->ajax_slug, FALSE),
70
+ 'wp_site_url' => $home_url,
71
+ 'wp_site_static_url' => str_replace('/index.php', '', str_replace('/index.php', '', $site_url))
72
  );
73
  wp_localize_script('photocrati_ajax', 'photocrati_ajax', $vars);
74
+
75
+ wp_register_script('persist-js', $router->get_static_url('photocrati-ajax#persist.js'));
76
+ wp_register_script('store-js', $router->get_static_url('photocrati-ajax#store.js'));
77
+ wp_register_script('ngg-store-js', $router->get_static_url('photocrati-ajax#ngg_store.js'), array('jquery', 'persist-js', 'store-js'));
78
+
79
+ wp_enqueue_script('ngg-store-js');
80
  }
81
 
82
  function get_type_list()
products/photocrati_nextgen/modules/ajax/static/ngg_store.js ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(function($){
2
+
3
+ // Store isn't working 100% for me. So disabling it for now.
4
+ store.enabled = false;
5
+
6
+ window.Ngg_Store = {
7
+ driver: store.enabled ? store : new Persist.Store('ngg_store'),
8
+
9
+ get: function(key){
10
+ return this.driver.get(key);
11
+ },
12
+
13
+ set: function(key, value){
14
+ if (typeof(value) == 'object') {
15
+ value = JSON.stringify(value);
16
+ }
17
+ return this.driver.set(key, value);
18
+ },
19
+
20
+ delete: function(key){
21
+ this.driver.remove(key);
22
+ return !this.has(key);
23
+ },
24
+
25
+ has: function(key){
26
+ var value = this.get(key);
27
+ return typeof(value) != 'undefined' && value != null;
28
+ },
29
+
30
+ save: function(){
31
+ if (typeof(this.driver['save']) != 'undefined') {
32
+ return this.driver.save();
33
+ }
34
+ else return true;
35
+ }
36
+ };
37
+
38
+ $(window).unload(function(){
39
+ Ngg_Store.save();
40
+ })
41
+
42
+ });
products/photocrati_nextgen/modules/ajax/static/persist.js ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ var swfobject=function(){var UNDEF="undefined",OBJECT="object",SHOCKWAVE_FLASH="Shockwave Flash",SHOCKWAVE_FLASH_AX="ShockwaveFlash.ShockwaveFlash",FLASH_MIME_TYPE="application/x-shockwave-flash",EXPRESS_INSTALL_ID="SWFObjectExprInst",ON_READY_STATE_CHANGE="onreadystatechange",win=window,doc=document,nav=navigator,plugin=false,domLoadFnArr=[main],regObjArr=[],objIdArr=[],listenersArr=[],storedAltContent,storedAltContentId,storedCallbackFn,storedCallbackObj,isDomLoaded=false,isExpressInstallActive=false,dynamicStylesheet,dynamicStylesheetMedia,autoHideShow=true,ua=function(){var w3cdom=typeof doc.getElementById!=UNDEF&&typeof doc.getElementsByTagName!=UNDEF&&typeof doc.createElement!=UNDEF,u=nav.userAgent.toLowerCase(),p=nav.platform.toLowerCase(),windows=p?/win/.test(p):/win/.test(u),mac=p?/mac/.test(p):/mac/.test(u),webkit=/webkit/.test(u)?parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,ie=!+"\v1",playerVersion=[0,0,0],d=null;if(typeof nav.plugins!=UNDEF&&typeof nav.plugins[SHOCKWAVE_FLASH]==OBJECT){d=nav.plugins[SHOCKWAVE_FLASH].description;if(d&&!(typeof nav.mimeTypes!=UNDEF&&nav.mimeTypes[FLASH_MIME_TYPE]&&!nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)){plugin=true;ie=false;d=d.replace(/^.*\s+(\S+\s+\S+$)/,"$1");playerVersion[0]=parseInt(d.replace(/^(.*)\..*$/,"$1"),10);playerVersion[1]=parseInt(d.replace(/^.*\.(.*)\s.*$/,"$1"),10);playerVersion[2]=/[a-zA-Z]/.test(d)?parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0;}}
3
+ else if(typeof win.ActiveXObject!=UNDEF){try{var a=new ActiveXObject(SHOCKWAVE_FLASH_AX);if(a){d=a.GetVariable("$version");if(d){ie=true;d=d.split(" ")[1].split(",");playerVersion=[parseInt(d[0],10),parseInt(d[1],10),parseInt(d[2],10)];}}}
4
+ catch(e){}}
5
+ return{w3:w3cdom,pv:playerVersion,wk:webkit,ie:ie,win:windows,mac:mac};}(),onDomLoad=function(){if(!ua.w3){return;}
6
+ if((typeof doc.readyState!=UNDEF&&doc.readyState=="complete")||(typeof doc.readyState==UNDEF&&(doc.getElementsByTagName("body")[0]||doc.body))){callDomLoadFunctions();}
7
+ if(!isDomLoaded){if(typeof doc.addEventListener!=UNDEF){doc.addEventListener("DOMContentLoaded",callDomLoadFunctions,false);}
8
+ if(ua.ie&&ua.win){doc.attachEvent(ON_READY_STATE_CHANGE,function(){if(doc.readyState=="complete"){doc.detachEvent(ON_READY_STATE_CHANGE,arguments.callee);callDomLoadFunctions();}});if(win==top){(function(){if(isDomLoaded){return;}
9
+ try{doc.documentElement.doScroll("left");}
10
+ catch(e){setTimeout(arguments.callee,0);return;}
11
+ callDomLoadFunctions();})();}}
12
+ if(ua.wk){(function(){if(isDomLoaded){return;}
13
+ if(!/loaded|complete/.test(doc.readyState)){setTimeout(arguments.callee,0);return;}
14
+ callDomLoadFunctions();})();}
15
+ addLoadEvent(callDomLoadFunctions);}}();function callDomLoadFunctions(){if(isDomLoaded){return;}
16
+ try{var t=doc.getElementsByTagName("body")[0].appendChild(createElement("span"));t.parentNode.removeChild(t);}
17
+ catch(e){return;}
18
+ isDomLoaded=true;var dl=domLoadFnArr.length;for(var i=0;i<dl;i++){domLoadFnArr[i]();}}
19
+ function addDomLoadEvent(fn){if(isDomLoaded){fn();}
20
+ else{domLoadFnArr[domLoadFnArr.length]=fn;}}
21
+ function addLoadEvent(fn){if(typeof win.addEventListener!=UNDEF){win.addEventListener("load",fn,false);}
22
+ else if(typeof doc.addEventListener!=UNDEF){doc.addEventListener("load",fn,false);}
23
+ else if(typeof win.attachEvent!=UNDEF){addListener(win,"onload",fn);}
24
+ else if(typeof win.onload=="function"){var fnOld=win.onload;win.onload=function(){fnOld();fn();};}
25
+ else{win.onload=fn;}}
26
+ function main(){if(plugin){testPlayerVersion();}
27
+ else{matchVersions();}}
28
+ function testPlayerVersion(){var b=doc.getElementsByTagName("body")[0];var o=createElement(OBJECT);o.setAttribute("type",FLASH_MIME_TYPE);var t=b.appendChild(o);if(t){var counter=0;(function(){if(typeof t.GetVariable!=UNDEF){var d=t.GetVariable("$version");if(d){d=d.split(" ")[1].split(",");ua.pv=[parseInt(d[0],10),parseInt(d[1],10),parseInt(d[2],10)];}}
29
+ else if(counter<10){counter++;setTimeout(arguments.callee,10);return;}
30
+ b.removeChild(o);t=null;matchVersions();})();}
31
+ else{matchVersions();}}
32
+ function matchVersions(){var rl=regObjArr.length;if(rl>0){for(var i=0;i<rl;i++){var id=regObjArr[i].id;var cb=regObjArr[i].callbackFn;var cbObj={success:false,id:id};if(ua.pv[0]>0){var obj=getElementById(id);if(obj){if(hasPlayerVersion(regObjArr[i].swfVersion)&&!(ua.wk&&ua.wk<312)){setVisibility(id,true);if(cb){cbObj.success=true;cbObj.ref=getObjectById(id);cb(cbObj);}}
33
+ else if(regObjArr[i].expressInstall&&canExpressInstall()){var att={};att.data=regObjArr[i].expressInstall;att.width=obj.getAttribute("width")||"0";att.height=obj.getAttribute("height")||"0";if(obj.getAttribute("class")){att.styleclass=obj.getAttribute("class");}
34
+ if(obj.getAttribute("align")){att.align=obj.getAttribute("align");}
35
+ var par={};var p=obj.getElementsByTagName("param");var pl=p.length;for(var j=0;j<pl;j++){if(p[j].getAttribute("name").toLowerCase()!="movie"){par[p[j].getAttribute("name")]=p[j].getAttribute("value");}}
36
+ showExpressInstall(att,par,id,cb);}
37
+ else{displayAltContent(obj);if(cb){cb(cbObj);}}}}
38
+ else{setVisibility(id,true);if(cb){var o=getObjectById(id);if(o&&typeof o.SetVariable!=UNDEF){cbObj.success=true;cbObj.ref=o;}
39
+ cb(cbObj);}}}}}
40
+ function getObjectById(objectIdStr){var r=null;var o=getElementById(objectIdStr);if(o&&o.nodeName=="OBJECT"){if(typeof o.SetVariable!=UNDEF){r=o;}
41
+ else{var n=o.getElementsByTagName(OBJECT)[0];if(n){r=n;}}}
42
+ return r;}
43
+ function canExpressInstall(){return!isExpressInstallActive&&hasPlayerVersion("6.0.65")&&(ua.win||ua.mac)&&!(ua.wk&&ua.wk<312);}
44
+ function showExpressInstall(att,par,replaceElemIdStr,callbackFn){isExpressInstallActive=true;storedCallbackFn=callbackFn||null;storedCallbackObj={success:false,id:replaceElemIdStr};var obj=getElementById(replaceElemIdStr);if(obj){if(obj.nodeName=="OBJECT"){storedAltContent=abstractAltContent(obj);storedAltContentId=null;}
45
+ else{storedAltContent=obj;storedAltContentId=replaceElemIdStr;}
46
+ att.id=EXPRESS_INSTALL_ID;if(typeof att.width==UNDEF||(!/%$/.test(att.width)&&parseInt(att.width,10)<310)){att.width="310";}
47
+ if(typeof att.height==UNDEF||(!/%$/.test(att.height)&&parseInt(att.height,10)<137)){att.height="137";}
48
+ doc.title=doc.title.slice(0,47)+" - Flash Player Installation";var pt=ua.ie&&ua.win?"ActiveX":"PlugIn",fv="MMredirectURL="+win.location.toString().replace(/&/g,"%26")+"&MMplayerType="+pt+"&MMdoctitle="+doc.title;if(typeof par.flashvars!=UNDEF){par.flashvars+="&"+fv;}
49
+ else{par.flashvars=fv;}
50
+ if(ua.ie&&ua.win&&obj.readyState!=4){var newObj=createElement("div");replaceElemIdStr+="SWFObjectNew";newObj.setAttribute("id",replaceElemIdStr);obj.parentNode.insertBefore(newObj,obj);obj.style.display="none";(function(){if(obj.readyState==4){obj.parentNode.removeChild(obj);}
51
+ else{setTimeout(arguments.callee,10);}})();}
52
+ createSWF(att,par,replaceElemIdStr);}}
53
+ function displayAltContent(obj){if(ua.ie&&ua.win&&obj.readyState!=4){var el=createElement("div");obj.parentNode.insertBefore(el,obj);el.parentNode.replaceChild(abstractAltContent(obj),el);obj.style.display="none";(function(){if(obj.readyState==4){obj.parentNode.removeChild(obj);}
54
+ else{setTimeout(arguments.callee,10);}})();}
55
+ else{obj.parentNode.replaceChild(abstractAltContent(obj),obj);}}
56
+ function abstractAltContent(obj){var ac=createElement("div");if(ua.win&&ua.ie){ac.innerHTML=obj.innerHTML;}
57
+ else{var nestedObj=obj.getElementsByTagName(OBJECT)[0];if(nestedObj){var c=nestedObj.childNodes;if(c){var cl=c.length;for(var i=0;i<cl;i++){if(!(c[i].nodeType==1&&c[i].nodeName=="PARAM")&&!(c[i].nodeType==8)){ac.appendChild(c[i].cloneNode(true));}}}}}
58
+ return ac;}
59
+ function createSWF(attObj,parObj,id){var r,el=getElementById(id);if(ua.wk&&ua.wk<312){return r;}
60
+ if(el){if(typeof attObj.id==UNDEF){attObj.id=id;}
61
+ if(ua.ie&&ua.win){var att="";for(var i in attObj){if(attObj[i]!=Object.prototype[i]){if(i.toLowerCase()=="data"){parObj.movie=attObj[i];}
62
+ else if(i.toLowerCase()=="styleclass"){att+=' class="'+attObj[i]+'"';}
63
+ else if(i.toLowerCase()!="classid"){att+=' '+i+'="'+attObj[i]+'"';}}}
64
+ var par="";for(var j in parObj){if(parObj[j]!=Object.prototype[j]){par+='<param name="'+j+'" value="'+parObj[j]+'" />';}}
65
+ el.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+att+'>'+par+'</object>';objIdArr[objIdArr.length]=attObj.id;r=getElementById(attObj.id);}
66
+ else{var o=createElement(OBJECT);o.setAttribute("type",FLASH_MIME_TYPE);for(var m in attObj){if(attObj[m]!=Object.prototype[m]){if(m.toLowerCase()=="styleclass"){o.setAttribute("class",attObj[m]);}
67
+ else if(m.toLowerCase()!="classid"){o.setAttribute(m,attObj[m]);}}}
68
+ for(var n in parObj){if(parObj[n]!=Object.prototype[n]&&n.toLowerCase()!="movie"){createObjParam(o,n,parObj[n]);}}
69
+ el.parentNode.replaceChild(o,el);r=o;}}
70
+ return r;}
71
+ function createObjParam(el,pName,pValue){var p=createElement("param");p.setAttribute("name",pName);p.setAttribute("value",pValue);el.appendChild(p);}
72
+ function removeSWF(id){var obj=getElementById(id);if(obj&&obj.nodeName=="OBJECT"){if(ua.ie&&ua.win){obj.style.display="none";(function(){if(obj.readyState==4){removeObjectInIE(id);}
73
+ else{setTimeout(arguments.callee,10);}})();}
74
+ else{obj.parentNode.removeChild(obj);}}}
75
+ function removeObjectInIE(id){var obj=getElementById(id);if(obj){for(var i in obj){if(typeof obj[i]=="function"){obj[i]=null;}}
76
+ obj.parentNode.removeChild(obj);}}
77
+ function getElementById(id){var el=null;try{el=doc.getElementById(id);}
78
+ catch(e){}
79
+ return el;}
80
+ function createElement(el){return doc.createElement(el);}
81
+ function addListener(target,eventType,fn){target.attachEvent(eventType,fn);listenersArr[listenersArr.length]=[target,eventType,fn];}
82
+ function hasPlayerVersion(rv){var pv=ua.pv,v=rv.split(".");v[0]=parseInt(v[0],10);v[1]=parseInt(v[1],10)||0;v[2]=parseInt(v[2],10)||0;return(pv[0]>v[0]||(pv[0]==v[0]&&pv[1]>v[1])||(pv[0]==v[0]&&pv[1]==v[1]&&pv[2]>=v[2]))?true:false;}
83
+ function createCSS(sel,decl,media,newStyle){if(ua.ie&&ua.mac){return;}
84
+ var h=doc.getElementsByTagName("head")[0];if(!h){return;}
85
+ var m=(media&&typeof media=="string")?media:"screen";if(newStyle){dynamicStylesheet=null;dynamicStylesheetMedia=null;}
86
+ if(!dynamicStylesheet||dynamicStylesheetMedia!=m){var s=createElement("style");s.setAttribute("type","text/css");s.setAttribute("media",m);dynamicStylesheet=h.appendChild(s);if(ua.ie&&ua.win&&typeof doc.styleSheets!=UNDEF&&doc.styleSheets.length>0){dynamicStylesheet=doc.styleSheets[doc.styleSheets.length-1];}
87
+ dynamicStylesheetMedia=m;}
88
+ if(ua.ie&&ua.win){if(dynamicStylesheet&&typeof dynamicStylesheet.addRule==OBJECT){dynamicStylesheet.addRule(sel,decl);}}
89
+ else{if(dynamicStylesheet&&typeof doc.createTextNode!=UNDEF){dynamicStylesheet.appendChild(doc.createTextNode(sel+" {"+decl+"}"));}}}
90
+ function setVisibility(id,isVisible){if(!autoHideShow){return;}
91
+ var v=isVisible?"visible":"hidden";if(isDomLoaded&&getElementById(id)){getElementById(id).style.visibility=v;}
92
+ else{createCSS("#"+id,"visibility:"+v);}}
93
+ function urlEncodeIfNecessary(s){var regex=/[\\\"<>\.;]/;var hasBadChars=regex.exec(s)!=null;return hasBadChars&&typeof encodeURIComponent!=UNDEF?encodeURIComponent(s):s;}
94
+ var cleanup=function(){if(ua.ie&&ua.win){window.attachEvent("onunload",function(){var ll=listenersArr.length;for(var i=0;i<ll;i++){listenersArr[i][0].detachEvent(listenersArr[i][1],listenersArr[i][2]);}
95
+ var il=objIdArr.length;for(var j=0;j<il;j++){removeSWF(objIdArr[j]);}
96
+ for(var k in ua){ua[k]=null;}
97
+ ua=null;for(var l in swfobject){swfobject[l]=null;}
98
+ swfobject=null;});}}();return{registerObject:function(objectIdStr,swfVersionStr,xiSwfUrlStr,callbackFn){if(ua.w3&&objectIdStr&&swfVersionStr){var regObj={};regObj.id=objectIdStr;regObj.swfVersion=swfVersionStr;regObj.expressInstall=xiSwfUrlStr;regObj.callbackFn=callbackFn;regObjArr[regObjArr.length]=regObj;setVisibility(objectIdStr,false);}
99
+ else if(callbackFn){callbackFn({success:false,id:objectIdStr});}},getObjectById:function(objectIdStr){if(ua.w3){return getObjectById(objectIdStr);}},embedSWF:function(swfUrlStr,replaceElemIdStr,widthStr,heightStr,swfVersionStr,xiSwfUrlStr,flashvarsObj,parObj,attObj,callbackFn){var callbackObj={success:false,id:replaceElemIdStr};if(ua.w3&&!(ua.wk&&ua.wk<312)&&swfUrlStr&&replaceElemIdStr&&widthStr&&heightStr&&swfVersionStr){setVisibility(replaceElemIdStr,false);addDomLoadEvent(function(){widthStr+="";heightStr+="";var att={};if(attObj&&typeof attObj===OBJECT){for(var i in attObj){att[i]=attObj[i];}}
100
+ att.data=swfUrlStr;att.width=widthStr;att.height=heightStr;var par={};if(parObj&&typeof parObj===OBJECT){for(var j in parObj){par[j]=parObj[j];}}
101
+ if(flashvarsObj&&typeof flashvarsObj===OBJECT){for(var k in flashvarsObj){if(typeof par.flashvars!=UNDEF){par.flashvars+="&"+k+"="+flashvarsObj[k];}
102
+ else{par.flashvars=k+"="+flashvarsObj[k];}}}
103
+ if(hasPlayerVersion(swfVersionStr)){var obj=createSWF(att,par,replaceElemIdStr);if(att.id==replaceElemIdStr){setVisibility(replaceElemIdStr,true);}
104
+ callbackObj.success=true;callbackObj.ref=obj;}
105
+ else if(xiSwfUrlStr&&canExpressInstall()){att.data=xiSwfUrlStr;showExpressInstall(att,par,replaceElemIdStr,callbackFn);return;}
106
+ else{setVisibility(replaceElemIdStr,true);}
107
+ if(callbackFn){callbackFn(callbackObj);}});}
108
+ else if(callbackFn){callbackFn(callbackObj);}},switchOffAutoHideShow:function(){autoHideShow=false;},ua:ua,getFlashPlayerVersion:function(){return{major:ua.pv[0],minor:ua.pv[1],release:ua.pv[2]};},hasFlashPlayerVersion:hasPlayerVersion,createSWF:function(attObj,parObj,replaceElemIdStr){if(ua.w3){return createSWF(attObj,parObj,replaceElemIdStr);}
109
+ else{return undefined;}},showExpressInstall:function(att,par,replaceElemIdStr,callbackFn){if(ua.w3&&canExpressInstall()){showExpressInstall(att,par,replaceElemIdStr,callbackFn);}},removeSWF:function(objElemIdStr){if(ua.w3){removeSWF(objElemIdStr);}},createCSS:function(selStr,declStr,mediaStr,newStyleBoolean){if(ua.w3){createCSS(selStr,declStr,mediaStr,newStyleBoolean);}},addDomLoadEvent:addDomLoadEvent,addLoadEvent:addLoadEvent,getQueryParamValue:function(param){var q=doc.location.search||doc.location.hash;if(q){if(/\?/.test(q)){q=q.split("?")[1];}
110
+ if(param==null){return urlEncodeIfNecessary(q);}
111
+ var pairs=q.split("&");for(var i=0;i<pairs.length;i++){if(pairs[i].substring(0,pairs[i].indexOf("="))==param){return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=")+1)));}}}
112
+ return"";},expressInstallCallback:function(){if(isExpressInstallActive){var obj=getElementById(EXPRESS_INSTALL_ID);if(obj&&storedAltContent){obj.parentNode.replaceChild(storedAltContent,obj);if(storedAltContentId){setVisibility(storedAltContentId,true);if(ua.ie&&ua.win){storedAltContent.style.display="block";}}
113
+ if(storedCallbackFn){storedCallbackFn(storedCallbackObj);}}
114
+ isExpressInstallActive=false;}}};}();(function(){if(window.google&&google.gears){return;}
115
+ var F=null;if(typeof GearsFactory!='undefined'){F=new GearsFactory();}else{try{F=new ActiveXObject('Gears.Factory');if(F.getBuildInfo().indexOf('ie_mobile')!=-1){F.privateSetGlobalObject(this);}}catch(e){if((typeof navigator.mimeTypes!='undefined')&&navigator.mimeTypes["application/x-googlegears"]){F=document.createElement("object");F.style.display="none";F.width=0;F.height=0;F.type="application/x-googlegears";document.documentElement.appendChild(F);}}}
116
+ if(!F){return;}
117
+ if(!window.google){google={};}
118
+ if(!google.gears){google.gears={factory:F};}})();Persist=(function(){var VERSION='0.3.1',P,B,esc,init,empty,ec;ec=(function(){var EPOCH='Thu, 01-Jan-1970 00:00:01 GMT',RATIO=1000*60*60*24,KEYS=['expires','path','domain'],esc=escape,un=unescape,doc=document,me;var get_now=function(){var r=new Date();r.setTime(r.getTime());return r;};var cookify=function(c_key,c_val){var i,key,val,r=[],opt=(arguments.length>2)?arguments[2]:{};r.push(esc(c_key)+'='+esc(c_val));for(var idx=0;idx<KEYS.length;idx++){key=KEYS[idx];val=opt[key];if(val){r.push(key+'='+val);}}
119
+ if(opt.secure){r.push('secure');}
120
+ return r.join('; ');};var alive=function(){var k='__EC_TEST__',v=new Date();v=v.toGMTString();this.set(k,v);this.enabled=(this.remove(k)==v);return this.enabled;};me={set:function(key,val){var opt=(arguments.length>2)?arguments[2]:{},now=get_now(),expire_at,cfg={};if(opt.expires){if(opt.expires==-1){cfg.expires=-1}
121
+ else{var expires=opt.expires*RATIO;cfg.expires=new Date(now.getTime()+expires);cfg.expires=cfg.expires.toGMTString();}}
122
+ var keys=['path','domain','secure'];for(var i=0;i<keys.length;i++){if(opt[keys[i]]){cfg[keys[i]]=opt[keys[i]];}}
123
+ var r=cookify(key,val,cfg);doc.cookie=r;return val;},has:function(key){key=esc(key);var c=doc.cookie,ofs=c.indexOf(key+'='),len=ofs+key.length+1,sub=c.substring(0,key.length);return((!ofs&&key!=sub)||ofs<0)?false:true;},get:function(key){key=esc(key);var c=doc.cookie,ofs=c.indexOf(key+'='),len=ofs+key.length+1,sub=c.substring(0,key.length),end;if((!ofs&&key!=sub)||ofs<0){return null;}
124
+ end=c.indexOf(';',len);if(end<0){end=c.length;}
125
+ return un(c.substring(len,end));},remove:function(k){var r=me.get(k),opt={expires:EPOCH};doc.cookie=cookify(k,'',opt);return r;},keys:function(){var c=doc.cookie,ps=c.split('; '),i,p,r=[];for(var idx=0;idx<ps.length;idx++){p=ps[idx].split('=');r.push(un(p[0]));}
126
+ return r;},all:function(){var c=doc.cookie,ps=c.split('; '),i,p,r=[];for(var idx=0;idx<ps.length;idx++){p=ps[idx].split('=');r.push([un(p[0]),un(p[1])]);}
127
+ return r;},version:'0.2.1',enabled:false};me.enabled=alive.call(me);return me;}());var index_of=(function(){if(Array.prototype.indexOf){return function(ary,val){return Array.prototype.indexOf.call(ary,val);};}else{return function(ary,val){var i,l;for(var idx=0,len=ary.length;idx<len;idx++){if(ary[idx]==val){return idx;}}
128
+ return-1;};}})();empty=function(){};esc=function(str){return'PS'+str.replace(/_/g,'__').replace(/ /g,'_s');};var C={search_order:['localstorage','globalstorage','gears','cookie','ie','flash'],name_re:/^[a-z][a-z0-9_ \-]+$/i,methods:['init','get','set','remove','load','save','iterate'],sql:{version:'1',create:"CREATE TABLE IF NOT EXISTS persist_data (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)",get:"SELECT v FROM persist_data WHERE k = ?",set:"INSERT INTO persist_data(k, v) VALUES (?, ?)",remove:"DELETE FROM persist_data WHERE k = ?",keys:"SELECT * FROM persist_data"},flash:{div_id:'_persist_flash_wrap',id:'_persist_flash',path:'persist.swf',size:{w:1,h:1},params:{autostart:true}}};B={gears:{size:-1,test:function(){return(window.google&&window.google.gears)?true:false;},methods:{init:function(){var db;db=this.db=google.gears.factory.create('beta.database');db.open(esc(this.name));db.execute(C.sql.create).close();},get:function(key){var r,sql=C.sql.get;var db=this.db;var ret;db.execute('BEGIN').close();r=db.execute(sql,[key]);ret=r.isValidRow()?r.field(0):null;r.close();db.execute('COMMIT').close();return ret;},set:function(key,val){var rm_sql=C.sql.remove,sql=C.sql.set,r;var db=this.db;var ret;db.execute('BEGIN').close();db.execute(rm_sql,[key]).close();db.execute(sql,[key,val]).close();db.execute('COMMIT').close();return val;},remove:function(key){var get_sql=C.sql.get,sql=C.sql.remove,r,val=null,is_valid=false;var db=this.db;db.execute('BEGIN').close();db.execute(sql,[key]).close();db.execute('COMMIT').close();return true;},iterate:function(fn,scope){var key_sql=C.sql.keys;var r;var db=this.db;r=db.execute(key_sql);while(r.isValidRow()){fn.call(scope||this,r.field(0),r.field(1));r.next();}
129
+ r.close();}}},globalstorage:{size:5*1024*1024,test:function(){if(window.globalStorage){var domain='127.0.0.1';if(this.o&&this.o.domain){domain=this.o.domain;}
130
+ try{var dontcare=globalStorage[domain];return true;}catch(e){if(window.console&&window.console.warn){console.warn("globalStorage exists, but couldn't use it because your browser is running on domain:",domain);}
131
+ return false;}}else{return false;}},methods:{key:function(key){return esc(this.name)+esc(key);},init:function(){this.store=globalStorage[this.o.domain];},get:function(key){key=this.key(key);return this.store.getItem(key);},set:function(key,val){key=this.key(key);this.store.setItem(key,val);return val;},remove:function(key){var val;key=this.key(key);val=this.store.getItem[key];this.store.removeItem(key);return val;}}},localstorage:{size:-1,test:function(){try{if(window.localStorage&&window.localStorage.setItem("test",null)==undefined){if(/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){var ffVersion=RegExp.$1;if(ffVersion>=9){return true;}
132
+ if(window.location.protocol=='file:'){return false;}}else{return true;}}else{return false;}
133
+ return window.localStorage?true:false;}catch(e){return false;}},methods:{key:function(key){return this.name+'>'+key;},init:function(){this.store=localStorage;},get:function(key){key=this.key(key);return this.store.getItem(key);},set:function(key,val){key=this.key(key);this.store.setItem(key,val);return val;},remove:function(key){var val;key=this.key(key);val=this.store.getItem(key);this.store.removeItem(key);return val;},iterate:function(fn,scope){var l=this.store,key,keys;for(var i=0;i<l.length;i++){key=l.key(i);keys=key.split('>');if((keys.length==2)&&(keys[0]==this.name)){fn.call(scope||this,keys[1],l.getItem(key));}}}}},ie:{prefix:'_persist_data-',size:64*1024,test:function(){return window.ActiveXObject?true:false;},make_userdata:function(id){var el=document.createElement('div');el.id=id;el.style.display='none';el.addBehavior('#default#userdata');document.body.appendChild(el);return el;},methods:{init:function(){var id=B.ie.prefix+esc(this.name);this.el=B.ie.make_userdata(id);if(this.o.defer){this.load();}},get:function(key){var val;key=esc(key);if(!this.o.defer){this.load();}
134
+ val=this.el.getAttribute(key);return val;},set:function(key,val){key=esc(key);this.el.setAttribute(key,val);if(!this.o.defer){this.save();}
135
+ return val;},remove:function(key){var val;key=esc(key);if(!this.o.defer){this.load();}
136
+ val=this.el.getAttribute(key);this.el.removeAttribute(key);if(!this.o.defer){this.save();}
137
+ return val;},load:function(){this.el.load(esc(this.name));},save:function(){this.el.save(esc(this.name));}}},cookie:{delim:':',size:4000,test:function(){return P.Cookie.enabled?true:false;},methods:{key:function(key){return this.name+B.cookie.delim+key;},get:function(key,fn){var val;key=this.key(key);val=ec.get(key);return val;},set:function(key,val,fn){key=this.key(key);ec.set(key,val,this.o);return val;},remove:function(key,val){var val;key=this.key(key);val=ec.remove(key);return val;}}},flash:{test:function(){try{if(!swfobject){return false;}}catch(e){return false;}
138
+ var major=swfobject.getFlashPlayerVersion().major;return(major>=8)?true:false;},methods:{init:function(){if(!B.flash.el){var key,el,fel,cfg=C.flash;el=document.createElement('div');el.id=cfg.div_id;fel=document.createElement('div');fel.id=cfg.id;el.appendChild(fel);document.body.appendChild(el);B.flash.el=swfobject.createSWF({id:cfg.id,data:this.o.swf_path||cfg.path,width:cfg.size.w,height:cfg.size.h},cfg.params,cfg.id);}
139
+ this.el=B.flash.el;},get:function(key){var val;key=esc(key);val=this.el.get(this.name,key);return val;},set:function(key,val){var old_val;key=esc(key);old_val=this.el.set(this.name,key,val);return old_val;},remove:function(key){var val;key=esc(key);val=this.el.remove(this.name,key);return val;}}}};init=function(){var i,l,b,key,fns=C.methods,keys=C.search_order;for(var idx=0,len=fns.length;idx<len;idx++){P.Store.prototype[fns[idx]]=empty;}
140
+ P.type=null;P.size=-1;for(var idx2=0,len2=keys.length;!P.type&&idx2<len2;idx2++){b=B[keys[idx2]];if(b.test()){P.type=keys[idx2];P.size=b.size;for(key in b.methods){P.Store.prototype[key]=b.methods[key];}}}
141
+ P._init=true;};P={VERSION:VERSION,type:null,size:0,add:function(o){B[o.id]=o;C.search_order=[o.id].concat(C.search_order);init();},remove:function(id){var ofs=index_of(C.search_order,id);if(ofs<0){return;}
142
+ C.search_order.splice(ofs,1);delete B[id];init();},Cookie:ec,Store:function(name,o){if(!C.name_re.exec(name)){throw new Error("Invalid name");}
143
+ if(!P.type){throw new Error("No suitable storage found");}
144
+ o=o||{};this.name=name;o.domain=o.domain||location.hostname||'localhost';o.domain=o.domain.replace(/:\d+$/,'');o.domain=(o.domain=='localhost')?'':o.domain;this.o=o;o.expires=o.expires||365*2;o.path=o.path||'/';if(this.o.search_order){C.search_order=this.o.search_order;init();}
145
+ this.init();}};init();return P;})();
products/photocrati_nextgen/modules/ajax/static/persist.swf ADDED
Binary file
products/photocrati_nextgen/modules/ajax/static/store.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /* Copyright (c) 2010-2013 Marcus Westin */
2
+ this.JSON||(this.JSON={}),function(){function f(e){return e<10?"0"+e:e}function quote(e){return escapable.lastIndex=0,escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t=="string"?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];a&&typeof a=="object"&&typeof a.toJSON=="function"&&(a=a.toJSON(e)),typeof rep=="function"&&(a=rep.call(t,e,a));switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a)return"null";gap+=indent,u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n<s;n+=1)u[n]=str(n,a)||"null";return i=u.length===0?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+o+"]":"["+u.join(",")+"]",gap=o,i}if(rep&&typeof rep=="object"){s=rep.length;for(n=0;n<s;n+=1)r=rep[n],typeof r=="string"&&(i=str(r,a),i&&u.push(quote(r)+(gap?": ":":")+i))}else for(r in a)Object.hasOwnProperty.call(a,r)&&(i=str(r,a),i&&u.push(quote(r)+(gap?": ":":")+i));return i=u.length===0?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+o+"}":"{"+u.join(",")+"}",gap=o,i}}typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(e){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(e){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(e,t,n){var r;gap="",indent="";if(typeof n=="number")for(r=0;r<n;r+=1)indent+=" ";else typeof n=="string"&&(indent=n);rep=t;if(!t||typeof t=="function"||typeof t=="object"&&typeof t.length=="number")return str("",{"":e});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(e,t){var n,r,i=e[t];if(i&&typeof i=="object")for(n in i)Object.hasOwnProperty.call(i,n)&&(r=walk(i,n),r!==undefined?i[n]=r:delete i[n]);return reviver.call(e,t,i)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),typeof reviver=="function"?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(),function(e){function o(){try{return r in e&&e[r]}catch(t){return!1}}var t={},n=e.document,r="localStorage",i="script",s;t.disabled=!1,t.set=function(e,t){},t.get=function(e){},t.remove=function(e){},t.clear=function(){},t.transact=function(e,n,r){var i=t.get(e);r==null&&(r=n,n=null),typeof i=="undefined"&&(i=n||{}),r(i),t.set(e,i)},t.getAll=function(){},t.forEach=function(){},t.serialize=function(e){return JSON.stringify(e)},t.deserialize=function(e){if(typeof e!="string")return undefined;try{return JSON.parse(e)}catch(t){return e||undefined}};if(o())s=e[r],t.set=function(e,n){return n===undefined?t.remove(e):(s.setItem(e,t.serialize(n)),n)},t.get=function(e){return t.deserialize(s.getItem(e))},t.remove=function(e){s.removeItem(e)},t.clear=function(){s.clear()},t.getAll=function(){var e={};return t.forEach(function(t,n){e[t]=n}),e},t.forEach=function(e){for(var n=0;n<s.length;n++){var r=s.key(n);e(r,t.get(r))}};else if(n.documentElement.addBehavior){var u,a;try{a=new ActiveXObject("htmlfile"),a.open(),a.write("<"+i+">document.w=window</"+i+'><iframe src="/favicon.ico"></iframe>'),a.close(),u=a.w.frames[0].document,s=u.createElement("div")}catch(f){s=n.createElement("div"),u=n.body}function l(e){return function(){var n=Array.prototype.slice.call(arguments,0);n.unshift(s),u.appendChild(s),s.addBehavior("#default#userData"),s.load(r);var i=e.apply(t,n);return u.removeChild(s),i}}var c=new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]","g");function h(e){return e.replace(c,"___")}t.set=l(function(e,n,i){return n=h(n),i===undefined?t.remove(n):(e.setAttribute(n,t.serialize(i)),e.save(r),i)}),t.get=l(function(e,n){return n=h(n),t.deserialize(e.getAttribute(n))}),t.remove=l(function(e,t){t=h(t),e.removeAttribute(t),e.save(r)}),t.clear=l(function(e){var t=e.XMLDocument.documentElement.attributes;e.load(r);for(var n=0,i;i=t[n];n++)e.removeAttribute(i.name);e.save(r)}),t.getAll=function(e){var n={};return t.forEach(function(e,t){n[e]=t}),n},t.forEach=l(function(e,n){var r=e.XMLDocument.documentElement.attributes;for(var i=0,s;s=r[i];++i)n(s.name,t.deserialize(e.getAttribute(s.name)))})}try{var p="__storejs__";t.set(p,p),t.get(p)!=p&&(t.disabled=!0),t.remove(p)}catch(f){t.disabled=!0}t.enabled=!t.disabled,typeof module!="undefined"&&module.exports?module.exports=t:typeof define=="function"&&define.amd?define(t):e.store=t}(this.window||global)
products/photocrati_nextgen/modules/attach_to_post/adapter.attach_to_post_ajax.php CHANGED
@@ -167,7 +167,7 @@ class A_Attach_To_Post_Ajax extends Mixin
167
  }
168
 
169
  // Get the thumbnail
170
- $entity->thumb_url = $storage->get_image_url($image, 'thumb');
171
  $entity->thumb_html = $storage->get_image_html($image, 'thumb');
172
  $entity->max_width = $settings->thumbwidth;
173
  $entity->max_height = $settings->thumbheight;
@@ -189,7 +189,7 @@ class A_Attach_To_Post_Ajax extends Mixin
189
  $mapper = $this->object->get_registry()->get_utility('I_Displayed_Gallery_Mapper');
190
 
191
  // Do we have fields to work with?
192
- if ($this->object->validate_ajax_request(true) && ($params = $this->object->param('displayed_gallery'))) {
193
 
194
  // Existing displayed gallery ?
195
  if (($id = $this->object->param('id'))) {
@@ -200,7 +200,7 @@ class A_Attach_To_Post_Ajax extends Mixin
200
  }
201
  else {
202
  $factory = $this->object->get_registry()->get_utility('I_Component_Factory');
203
- $displayed_gallery = $factory->create('displayed_gallery', $mapper, $params);
204
  }
205
 
206
  // Save the changes
167
  }
168
 
169
  // Get the thumbnail
170
+ $entity->thumb_url = $storage->get_image_url($image, 'thumb', TRUE);
171
  $entity->thumb_html = $storage->get_image_html($image, 'thumb');
172
  $entity->max_width = $settings->thumbwidth;
173
  $entity->max_height = $settings->thumbheight;
189
  $mapper = $this->object->get_registry()->get_utility('I_Displayed_Gallery_Mapper');
190
 
191
  // Do we have fields to work with?
192
+ if ($this->object->validate_ajax_request(true) && ($params = json_decode($this->object->param('displayed_gallery')))) {
193
 
194
  // Existing displayed gallery ?
195
  if (($id = $this->object->param('id'))) {
200
  }
201
  else {
202
  $factory = $this->object->get_registry()->get_utility('I_Component_Factory');
203
+ $displayed_gallery = $factory->create('displayed_gallery', $params, $mapper);
204
  }
205
 
206
  // Save the changes
products/photocrati_nextgen/modules/attach_to_post/adapter.gallery_storage_frame_event.php CHANGED
@@ -29,11 +29,19 @@ class A_Gallery_Storage_Frame_Event extends Mixin
29
  $storage->get_thumb_url($image)
30
  );
31
 
32
- $events->add_event(
33
- array(
34
- 'event' => 'thumbnail_modified',
35
- 'image' => $image,
36
- )
37
- );
 
 
 
 
 
 
 
 
38
  }
39
  }
29
  $storage->get_thumb_url($image)
30
  );
31
 
32
+ if (is_admin()) {
33
+
34
+ $event = new stdClass();
35
+ $event->pid = $image->{$image->id_field};
36
+ $event->id_field = $image->id_field;
37
+ $event->thumb_url = $image->thumb_url;
38
+
39
+ $events->add_event(
40
+ array(
41
+ 'event' => 'thumbnail_modified',
42
+ 'image' => $event,
43
+ )
44
+ );
45
+ }
46
  }
47
  }
products/photocrati_nextgen/modules/attach_to_post/class.attach_controller.php CHANGED
@@ -4,6 +4,8 @@ class C_Attach_Controller extends C_NextGen_Admin_Page_Controller
4
  {
5
  static $_instances = array();
6
  var $_displayed_gallery;
 
 
7
 
8
  static function &get_instance($context)
9
  {
@@ -28,6 +30,56 @@ class C_Attach_Controller extends C_NextGen_Admin_Page_Controller
28
  {
29
  parent::initialize();
30
  $this->_load_displayed_gallery();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
  }
33
 
@@ -40,30 +92,37 @@ class Mixin_Attach_To_Post extends Mixin
40
  $this->object->_displayed_gallery = $mapper->create();
41
  }
42
  }
 
 
 
 
 
43
 
44
  function enqueue_backend_resources()
45
  {
46
  $this->call_parent('enqueue_backend_resources');
47
-
48
- // wp_auth_check_load invokes functions not defined yet
49
- remove_action('admin_enqueue_scripts', 'wp_auth_check_load');
50
- do_action('admin_enqueue_scripts');
51
-
52
  // Enqueue frame event publishing
53
  wp_enqueue_script('frame_event_publisher');
 
54
 
55
  // Enqueue JQuery UI libraries
56
  wp_enqueue_script('jquery-ui-tabs');
57
  wp_enqueue_script('jquery-ui-sortable');
58
- wp_enqueue_script('jquery-ui-tooltip');
59
  wp_enqueue_script('ngg_tabs', $this->get_static_url('photocrati-attach_to_post#ngg_tabs.js'));
 
 
 
 
60
 
61
  // Ensure select2
62
  wp_enqueue_style('select2');
63
  wp_enqueue_script('select2');
 
64
 
65
  // Ensure that the Photocrati AJAX library is loaded
66
  wp_enqueue_script('photocrati_ajax');
 
67
 
68
  // Enqueue logic for the Attach to Post interface as a whole
69
  wp_enqueue_script(
@@ -72,9 +131,11 @@ class Mixin_Attach_To_Post extends Mixin
72
  wp_enqueue_style(
73
  'ngg_attach_to_post', $this->get_static_url('photocrati-attach_to_post#attach_to_post.css')
74
  );
 
75
 
76
  // Enqueue backbone.js library, required by the Attach to Post display tab
77
  wp_enqueue_script('backbone'); // provided by WP
 
78
 
79
  // Ensure underscore sting, a helper utility
80
  wp_enqueue_script(
@@ -83,9 +144,10 @@ class Mixin_Attach_To_Post extends Mixin
83
  array('underscore'),
84
  '2.3.0'
85
  );
 
86
 
87
  // Enqueue the backbone app for the display tab
88
- $settings = C_NextGen_Global_Settings::get_instance();
89
  $preview_url = $settings->gallery_preview_url;
90
  $display_tab_js_url = $settings->attach_to_post_display_tab_js_url;
91
  if ($this->object->_displayed_gallery->id()) {
@@ -102,6 +164,15 @@ class Mixin_Attach_To_Post extends Mixin
102
  'ngg_displayed_gallery_preview_url',
103
  $settings->gallery_preview_url
104
  );
 
 
 
 
 
 
 
 
 
105
  }
106
 
107
  /**
@@ -109,8 +180,8 @@ class Mixin_Attach_To_Post extends Mixin
109
  */
110
  function index_action($return=FALSE)
111
  {
112
- if ($this->object->_displayed_gallery->is_new()) $this->object->expires("+2 hour");
113
-
114
  // Enqueue resources
115
  return $this->object->render_view('photocrati-attach_to_post#attach_to_post', array(
116
  'page_title' => $this->object->_get_page_title(),
@@ -235,8 +306,8 @@ class Mixin_Attach_To_Post extends Mixin
235
  */
236
  function _render_ngg_page_in_frame($page, $tab_id = null)
237
  {
238
- $frame_url = real_site_url("/wp-admin/admin.php?page={$page}&attach_to_post");
239
- $frame_url = esc_url($frame_url);
240
 
241
  if ($tab_id) {
242
  $tab_id = " id='ngg-iframe-{$tab_id}'";
4
  {
5
  static $_instances = array();
6
  var $_displayed_gallery;
7
+ var $_marked_scripts;
8
+ var $_is_rendering;
9
 
10
  static function &get_instance($context)
11
  {
30
  {
31
  parent::initialize();
32
  $this->_load_displayed_gallery();
33
+
34
+ $this->_marked_scripts = array();
35
+
36
+ if (did_action('wp_print_scripts')) {
37
+ $this->_handle_scripts();
38
+ }
39
+ else {
40
+ add_action('wp_print_scripts', array($this, '_handle_scripts'), 9999);
41
+ }
42
+ }
43
+
44
+ function _handle_scripts()
45
+ {
46
+ if (is_admin() && $this->_is_rendering)
47
+ {
48
+ global $wp_scripts;
49
+
50
+ $queue = $wp_scripts->queue;
51
+ $marked = $this->_marked_scripts;
52
+
53
+ foreach ($marked as $tag => $value) {
54
+ $this->_handle_script($tag, $queue);
55
+ }
56
+
57
+ foreach ($queue as $extra) {
58
+ wp_dequeue_script($extra);
59
+ }
60
+ }
61
+ }
62
+
63
+ function _handle_script($tag, &$queue)
64
+ {
65
+ global $wp_scripts;
66
+
67
+ $registered = $wp_scripts->registered;
68
+
69
+ $idx = array_search($tag, $queue);
70
+ if ($idx !== false) {
71
+ unset($queue[$idx]);
72
+ }
73
+
74
+ if (isset($registered[$tag])) {
75
+ $script = $registered[$tag];
76
+
77
+ if ($script->deps) {
78
+ foreach ($script->deps as $dep) {
79
+ $this->_handle_script($dep, $queue);
80
+ }
81
+ }
82
+ }
83
  }
84
  }
85
 
92
  $this->object->_displayed_gallery = $mapper->create();
93
  }
94
  }
95
+
96
+ function mark_script($script_tag)
97
+ {
98
+ $this->object->_marked_scripts[$script_tag] = true;
99
+ }
100
 
101
  function enqueue_backend_resources()
102
  {
103
  $this->call_parent('enqueue_backend_resources');
 
 
 
 
 
104
  // Enqueue frame event publishing
105
  wp_enqueue_script('frame_event_publisher');
106
+ $this->object->mark_script('frame_event_publisher');
107
 
108
  // Enqueue JQuery UI libraries
109
  wp_enqueue_script('jquery-ui-tabs');
110
  wp_enqueue_script('jquery-ui-sortable');
111
+ wp_enqueue_script('jquery-ui-tooltip');
112
  wp_enqueue_script('ngg_tabs', $this->get_static_url('photocrati-attach_to_post#ngg_tabs.js'));
113
+ $this->object->mark_script('jquery-ui-tabs');
114
+ $this->object->mark_script('jquery-ui-sortable');
115
+ $this->object->mark_script('jquery-ui-tooltip');
116
+ $this->object->mark_script('ngg_tabs');
117
 
118
  // Ensure select2
119
  wp_enqueue_style('select2');
120
  wp_enqueue_script('select2');
121
+ $this->object->mark_script('select2');
122
 
123
  // Ensure that the Photocrati AJAX library is loaded
124
  wp_enqueue_script('photocrati_ajax');
125
+ $this->object->mark_script('photocrati_ajax');
126
 
127
  // Enqueue logic for the Attach to Post interface as a whole
128
  wp_enqueue_script(
131
  wp_enqueue_style(
132
  'ngg_attach_to_post', $this->get_static_url('photocrati-attach_to_post#attach_to_post.css')
133
  );
134
+ $this->object->mark_script('ngg_attach_to_post');
135
 
136
  // Enqueue backbone.js library, required by the Attach to Post display tab
137
  wp_enqueue_script('backbone'); // provided by WP
138
+ $this->object->mark_script('backbone');
139
 
140
  // Ensure underscore sting, a helper utility
141
  wp_enqueue_script(
144
  array('underscore'),
145
  '2.3.0'
146
  );
147
+ $this->object->mark_script('underscore.string');
148
 
149
  // Enqueue the backbone app for the display tab
150
+ $settings = C_NextGen_Settings::get_instance();
151
  $preview_url = $settings->gallery_preview_url;
152
  $display_tab_js_url = $settings->attach_to_post_display_tab_js_url;
153
  if ($this->object->_displayed_gallery->id()) {
164
  'ngg_displayed_gallery_preview_url',
165
  $settings->gallery_preview_url
166
  );
167
+ $this->object->mark_script('ngg_display_tab');
168
+
169
+ // TODO: for now mark Pro scripts to ensure they are enqueued properly, remove this after Pro upgrade with tagging added
170
+ $display_types = array('photocrati-nextgen_pro_slideshow', 'photocrati-nextgen_pro_horizontal_filmstrip', 'photocrati-nextgen_pro_thumbnail_grid', 'photocrati-nextgen_pro_blog_gallery', 'photocrati-nextgen_pro_film');
171
+ foreach ($display_types as $display_type) {
172
+ $this->object->mark_script($display_type . '-js');
173
+ }
174
+
175
+ $this->object->mark_script('nextgen_pro_albums_settings_script');
176
  }
177
 
178
  /**
180
  */
181
  function index_action($return=FALSE)
182
  {
183
+ $this->object->do_not_cache();
184
+
185
  // Enqueue resources
186
  return $this->object->render_view('photocrati-attach_to_post#attach_to_post', array(
187
  'page_title' => $this->object->_get_page_title(),
306
  */
307
  function _render_ngg_page_in_frame($page, $tab_id = null)
308
  {
309
+ $frame_url = admin_url("/admin.php?page={$page}&attach_to_post");
310
+ $frame_url = nextgen_esc_url($frame_url);
311
 
312
  if ($tab_id) {
313
  $tab_id = " id='ngg-iframe-{$tab_id}'";
products/photocrati_nextgen/modules/attach_to_post/class.attach_to_post_installer.php CHANGED
@@ -2,33 +2,12 @@
2
 
3
  class C_Attach_To_Post_Installer
4
  {
5
- function get_registry()
6
- {
7
- return C_Component_Registry::get_instance();
8
- }
9
-
10
- function __construct()
11
- {
12
- $this->settings = C_NextGen_Global_Settings::get_instance();
13
-
14
- $router = $this->get_registry()->get_utility('I_Router');
15
- $this->defaults = array(
16
- 'attach_to_post_url' => $router->get_url('/nextgen-attach_to_post', FALSE),
17
- 'gallery_preview_url' => $router->get_url('/nextgen-attach_to_post/preview', FALSE),
18
- 'attach_to_post_display_tab_js_url' => $router->get_url('/nextgen-attach_to_post/display_tab_js', FALSE)
19
- );
20
- }
21
-
22
  function install()
23
  {
24
- foreach ($this->defaults as $key => $val) {
25
- $this->settings->set_default_value($key, $val);
26
- }
27
- }
28
-
29
- function uninstall($hard=FALSE)
30
- {
31
- if ($hard) foreach (array_keys($this->defaults) as $key)
32
- $this->settings->delete($key);
33
  }
34
  }
2
 
3
  class C_Attach_To_Post_Installer
4
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  function install()
6
  {
7
+ // Delete cached values. Needed for 2.0.7 and less
8
+ $settings = C_NextGen_Settings::get_instance();
9
+ $settings->delete('attach_to_post_url');
10
+ $settings->delete('gallery_preview_url');
11
+ $settings->delete('attach_to_post_display_tab_js_url');
 
 
 
 
12
  }
13
  }
products/photocrati_nextgen/modules/attach_to_post/class.attach_to_post_option_handler.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class C_Attach_To_Post_Option_Handler
4
+ {
5
+ function get_router()
6
+ {
7
+ return C_Component_Registry::get_instance()->get_utility('I_Router');
8
+ }
9
+
10
+ function get($key, $default=NULL)
11
+ {
12
+ $retval = $default;
13
+
14
+ switch ($key) {
15
+ case 'attach_to_post_url':
16
+ $retval = $this->get_router()->get_url('/nextgen-attach_to_post', FALSE);
17
+ break;
18
+ case 'gallery_preview_url':
19
+ $retval = $this->get_router()->get_url('/nextgen-attach_to_post/preview', FALSE);
20
+ break;
21
+ case 'attach_to_post_display_tab_js_url':
22
+ $retval = $this->get_router()->get_url('/nextgen-attach_to_post/display_tab_js', FALSE);
23
+ break;
24
+ }
25
+
26
+ return $retval;
27
+ }
28
+ }
products/photocrati_nextgen/modules/attach_to_post/mixin.attach_to_post_display_tab.php CHANGED
@@ -15,11 +15,16 @@ class Mixin_Attach_To_Post_Display_Tab extends Mixin
15
 
16
  // Ensure that JS is returned
17
  $this->object->set_content_type('javascript');
 
 
 
 
18
 
19
  // Get all entities used by the display tab
20
  $context = 'attach_to_post';
21
  $gallery_mapper = $this->get_registry()->get_utility('I_Gallery_Mapper', $context);
22
  $album_mapper = $this->get_registry()->get_utility('I_Album_Mapper', $context);
 
23
  $display_type_mapper= $this->get_registry()->get_utility('I_Display_Type_Mapper', $context);
24
  $source_mapper = $this->get_registry()->get_utility('I_Displayed_Gallery_Source_Mapper', $context);
25
  $security = $this->get_registry()->get_utility('I_Security_Manager');
@@ -41,7 +46,7 @@ class Mixin_Attach_To_Post_Display_Tab extends Mixin
41
 
42
  usort($display_types, array($this->object, '_display_type_list_sort'));
43
 
44
- return $this->object->render_view('photocrati-attach_to_post#display_tab_js', array(
45
  'displayed_gallery' => json_encode($this->object->_displayed_gallery->get_entity()),
46
  'sources' => json_encode($source_mapper->select()->order_by('title')->run_query()),
47
  'gallery_primary_key' => $gallery_mapper->get_primary_key_column(),
@@ -49,8 +54,11 @@ class Mixin_Attach_To_Post_Display_Tab extends Mixin
49
  'albums' => json_encode($album_mapper->find_all()),
50
  'tags' => json_encode($tags),
51
  'display_types' => json_encode($display_types),
52
- 'sec_token' => $security->get_request_token('nextgen_edit_displayed_gallery')->get_json()
 
53
  ), $return);
 
 
54
  }
55
 
56
  function _display_type_list_sort($type_1, $type_2)
@@ -59,11 +67,11 @@ class Mixin_Attach_To_Post_Display_Tab extends Mixin
59
  $order_2 = $type_2->view_order;
60
 
61
  if ($order_1 == null) {
62
- $order_1 = NEXTGEN_DISPLAY_PRIORITY_BASE;
63
  }
64
 
65
  if ($order_2 == null) {
66
- $order_2 = NEXTGEN_DISPLAY_PRIORITY_BASE;
67
  }
68
 
69
  if ($order_1 > $order_2) {
@@ -83,6 +91,11 @@ class Mixin_Attach_To_Post_Display_Tab extends Mixin
83
  */
84
  function _get_display_tabs()
85
  {
 
 
 
 
 
86
  return array(
87
  $this->object->_render_display_types_tab(),
88
  $this->object->_render_display_source_tab(),
@@ -194,9 +207,9 @@ class Mixin_Attach_To_Post_Display_Tab extends Mixin
194
  $retval = array();
195
 
196
  // Get all display setting forms
197
- $form_manager = $this->get_registry()->get_utility('I_Form_Manager');
198
  $forms = $form_manager->get_forms(
199
- NEXTGEN_DISPLAY_SETTINGS_SLUG, TRUE
200
  );
201
 
202
  // Display each form
15
 
16
  // Ensure that JS is returned
17
  $this->object->set_content_type('javascript');
18
+
19
+ while (ob_get_level() > 0) {
20
+ ob_end_clean();
21
+ }
22
 
23
  // Get all entities used by the display tab
24
  $context = 'attach_to_post';
25
  $gallery_mapper = $this->get_registry()->get_utility('I_Gallery_Mapper', $context);
26
  $album_mapper = $this->get_registry()->get_utility('I_Album_Mapper', $context);
27
+ $image_mapper = $this->get_registry()->get_utility('I_Image_Mapper', $context);
28
  $display_type_mapper= $this->get_registry()->get_utility('I_Display_Type_Mapper', $context);
29
  $source_mapper = $this->get_registry()->get_utility('I_Displayed_Gallery_Source_Mapper', $context);
30
  $security = $this->get_registry()->get_utility('I_Security_Manager');
46
 
47
  usort($display_types, array($this->object, '_display_type_list_sort'));
48
 
49
+ $output = $this->object->render_view('photocrati-attach_to_post#display_tab_js', array(
50
  'displayed_gallery' => json_encode($this->object->_displayed_gallery->get_entity()),
51
  'sources' => json_encode($source_mapper->select()->order_by('title')->run_query()),
52
  'gallery_primary_key' => $gallery_mapper->get_primary_key_column(),
54
  'albums' => json_encode($album_mapper->find_all()),
55
  'tags' => json_encode($tags),
56
  'display_types' => json_encode($display_types),
57
+ 'sec_token' => $security->get_request_token('nextgen_edit_displayed_gallery')->get_json(),
58
+ 'image_primary_key' => $image_mapper->get_primary_key_column()
59
  ), $return);
60
+
61
+ return $output;
62
  }
63
 
64
  function _display_type_list_sort($type_1, $type_2)
67
  $order_2 = $type_2->view_order;
68
 
69
  if ($order_1 == null) {
70
+ $order_1 = NGG_DISPLAY_PRIORITY_BASE;
71
  }
72
 
73
  if ($order_2 == null) {
74
+ $order_2 = NGG_DISPLAY_PRIORITY_BASE;
75
  }
76
 
77
  if ($order_1 > $order_2) {
91
  */
92
  function _get_display_tabs()
93
  {
94
+ // The ATP requires more memmory than some applications, somewhere around 60MB.
95
+ // Because it's such an important feature of NextGEN Gallery, we temporarily disable
96
+ // any memory limits
97
+ @ini_set('memory_limit', -1);
98
+
99
  return array(
100
  $this->object->_render_display_types_tab(),
101
  $this->object->_render_display_source_tab(),
207
  $retval = array();
208
 
209
  // Get all display setting forms
210
+ $form_manager = C_Form_Manager::get_instance();
211
  $forms = $form_manager->get_forms(
212
+ NGG_DISPLAY_SETTINGS_SLUG, TRUE
213
  );
214
 
215
  // Display each form
products/photocrati_nextgen/modules/attach_to_post/module.attach_to_post.php CHANGED
@@ -6,7 +6,7 @@
6
  }
7
  */
8
 
9
- define('NEXTGEN_GALLERY_ATTACH_TO_POST_SLUG', 'ngg_attach_to_post');
10
 
11
  class M_Attach_To_Post extends C_Base_Module
12
  {
@@ -23,15 +23,28 @@ class M_Attach_To_Post extends C_Base_Module
23
  'photocrati-attach_to_post',
24
  'Attach To Post',
25
  'Provides the "Attach to Post" interface for displaying galleries and albums',
26
- '0.3',
27
  'http://www.nextgen-gallery.com',
28
  'Photocrati Media',
29
  'http://www.photocrati.com',
30
  $context
31
  );
32
 
 
 
 
 
 
 
 
33
  include_once('class.attach_to_post_installer.php');
34
  C_Photocrati_Installer::add_handler($this->module_id, 'C_Attach_To_Post_Installer');
 
 
 
 
 
 
35
  }
36
 
37
  /**
@@ -107,15 +120,35 @@ class M_Attach_To_Post extends C_Base_Module
107
  add_action('after_delete_post', array(&$this, 'cleanup_displayed_galleries'));
108
 
109
  // Add hook to subsitute displayed gallery placeholders
110
- add_filter('the_content', array(&$this, 'substitute_placeholder_imgs'), 1000, 1);
111
 
112
  // Emit frame communication events
113
  add_action('ngg_created_new_gallery', array(&$this, 'new_gallery_event'));
114
  add_action('ngg_after_new_images_added',array(&$this, 'images_added_event'));
115
  add_action('ngg_page_event', array(&$this, 'nextgen_page_event'));
116
  add_action('ngg_manage_tags', array(&$this, 'manage_tags_event'));
 
 
 
 
 
 
 
117
  }
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  /**
120
  * Substitutes the gallery placeholder content with the gallery type frontend
121
  * view, returns a list of static resources that need to be loaded
@@ -123,72 +156,43 @@ class M_Attach_To_Post extends C_Base_Module
123
  */
124
  function substitute_placeholder_imgs($content)
125
  {
126
- // Load html into parser
127
- $doc = new simple_html_dom();
128
- if ($content) {
129
- $doc->load($content);
130
-
131
- // Find all placeholder images
132
- $imgs = $doc->find("img[class='ngg_displayed_gallery']");
133
- if ($imgs) {
134
-
135
- // Get some utilities
136
- $mapper = $this->get_registry()->get_utility('I_Displayed_Gallery_Mapper');
137
- $router = $this->get_registry()->get_utility('I_Router');
138
-
139
- // To match ATP entries we compare the stored url against a generic path
140
- // We must check HTTP and HTTPS as well as permalink and non-permalink forms
141
- $preview_url = parse_url($router->join_paths(
142
- $router->remove_url_segment('index.php', $router->get_base_url()),
143
- '/nextgen-attach_to_post/preview'
144
- ));
145
- $preview_url = preg_quote($preview_url['host'] . $preview_url['path'], '#');
146
-
147
- $alt_preview_url = parse_url($router->join_paths(
148
- $router->remove_url_segment('index.php', $router->get_base_url()),
149
- 'index.php/nextgen-attach_to_post/preview'
150
- ));
151
- $alt_preview_url = preg_quote($alt_preview_url['host'] . $alt_preview_url['path'], '#');
152
-
153
- // Substitute each image for the gallery type frontent content
154
- foreach ($imgs as $img) {
155
-
156
- // The placeholder MUST have a gallery instance id
157
- if (preg_match("#http(s)?://({$preview_url}|{$alt_preview_url})/id--(\d+)#", $img->src, $match)) {
158
-
159
- // Find the displayed gallery
160
- $displayed_gallery_id = $match[3];
161
- $displayed_gallery = $mapper->find($displayed_gallery_id, TRUE);
162
-
163
- // Get the content for the displayed gallery
164
- $content = '<p>'._('Invalid Displayed Gallery').'</p>';
165
- if ($displayed_gallery) {
166
- $renderer = $this->get_registry()->get_utility('I_Displayed_Gallery_Renderer');
167
- $content = $renderer->render($displayed_gallery, TRUE);
168
- }
169
-
170
- // Replace the placeholder with the displayed gallery content
171
- $img->outertext = $this->compress_html($content);
172
- }
173
- }
174
- $content = (string)$doc->save();
175
- }
176
- return $content;
177
- }
178
- }
179
 
 
 
 
 
 
 
 
 
180
 
181
- /**
182
- * Removes any un-nessessary whitespace from the HTML
183
- * @param string $html
184
- * @return string
185
- */
186
- function compress_html($html)
187
- {
188
- $html = preg_replace("/>\s+/", ">", $html);
189
- $html = preg_replace("/\s+</", "<", $html);
190
- $html = preg_replace("/<!--(?:(?!-->).)*-->/m", "", $html);
191
- return $html;
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  }
193
 
194
  /**
@@ -201,13 +205,6 @@ class M_Attach_To_Post extends C_Base_Module
201
  // Enqueue resources needed at post/page level
202
  if (preg_match("/\/wp-admin\/(post|post-new)\.php$/", $_SERVER['SCRIPT_NAME'])) {
203
  $this->_enqueue_tinymce_resources();
204
-
205
- # wp_enqueue_style(
206
- # 'ngg_custom_scrollbar', $this->get_static_url('jquery.mCustomScrollbar.css')
207
- # );
208
- # wp_enqueue_script(
209
- # 'ngg_custom_scrollbar', $this->get_static_url('jquery.mCustomScrollbar.concat.min.js'), array('jquery')
210
- # );
211
  wp_enqueue_style(
212
  'ngg_attach_to_post_dialog', $router->get_static_url('photocrati-attach_to_post#attach_to_post_dialog.css')
213
  );
@@ -229,7 +226,7 @@ class M_Attach_To_Post extends C_Base_Module
229
  wp_localize_script(
230
  'media-editor',
231
  'nextgen_gallery_attach_to_post_url',
232
- C_NextGen_Global_Settings::get_instance()->attach_to_post_url
233
  );
234
 
235
  // Registers our tinymce button and plugin for attaching galleries
@@ -327,12 +324,13 @@ class M_Attach_To_Post extends C_Base_Module
327
  function new_gallery_event($gallery_id)
328
  {
329
  $gallery = $this->get_registry()->get_utility('I_Gallery_Mapper')->find($gallery_id);
330
-
331
- $this->_get_frame_event_publisher()->add_event(array(
332
- 'event' => 'new_gallery',
333
- 'gallery_id'=> intval($gallery_id),
334
- 'gallery_title' => $gallery->title
335
- ));
 
336
  }
337
 
338
  /**
6
  }
7
  */
8
 
9
+ define('NGG_ATTACH_TO_POST_SLUG', 'nextgen-attach_to_post');
10
 
11
  class M_Attach_To_Post extends C_Base_Module
12
  {
23
  'photocrati-attach_to_post',
24
  'Attach To Post',
25
  'Provides the "Attach to Post" interface for displaying galleries and albums',
26
+ '0.10',
27
  'http://www.nextgen-gallery.com',
28
  'Photocrati Media',
29
  'http://www.photocrati.com',
30
  $context
31
  );
32
 
33
+ include_once('class.attach_to_post_option_handler.php');
34
+ C_NextGen_Settings::add_option_handler('C_Attach_To_Post_Option_Handler', array(
35
+ 'attach_to_post_url',
36
+ 'gallery_preview_url',
37
+ 'attach_to_post_display_tab_js_url'
38
+ ));
39
+
40
  include_once('class.attach_to_post_installer.php');
41
  C_Photocrati_Installer::add_handler($this->module_id, 'C_Attach_To_Post_Installer');
42
+
43
+ $uri = strtolower($_SERVER['REQUEST_URI']);
44
+
45
+ if (strpos($uri, '/nextgen-attach_to_post') !== false) {
46
+ define('WP_ADMIN', true);
47
+ }
48
  }
49
 
50
  /**
120
  add_action('after_delete_post', array(&$this, 'cleanup_displayed_galleries'));
121
 
122
  // Add hook to subsitute displayed gallery placeholders
123
+ add_filter('the_content', array(&$this, 'substitute_placeholder_imgs'), PHP_INT_MAX, 1);
124
 
125
  // Emit frame communication events
126
  add_action('ngg_created_new_gallery', array(&$this, 'new_gallery_event'));
127
  add_action('ngg_after_new_images_added',array(&$this, 'images_added_event'));
128
  add_action('ngg_page_event', array(&$this, 'nextgen_page_event'));
129
  add_action('ngg_manage_tags', array(&$this, 'manage_tags_event'));
130
+
131
+ // We use two hooks here because we need it to execute for both the post-new.php
132
+ // page and ATP interface
133
+ add_action('plugins_loaded', array(&$this, 'fix_ie11'), 1);
134
+ add_action('admin_init', array(&$this, 'fix_ie11'), PHP_INT_MAX-1);
135
+ add_action('admin_enqueue_scripts', array(&$this, 'fix_ie11'), 1);
136
+ add_action('admin_enqueue_scripts', array(&$this, 'fix_ie11'), PHP_INT_MAX-1);
137
  }
138
 
139
+ /**
140
+ * WordPress sets the X-UA-Compatible header to IE=edge. Unfortunately, this causes problems with Plupload,
141
+ * so we have the send this header
142
+ */
143
+ function fix_ie11()
144
+ {
145
+ if ((array_search('attach_to_post', array_keys($_REQUEST)) !== FALSE OR strpos($_SERVER['REQUEST_URI'], NGG_ATTACH_TO_POST_SLUG) !== FALSE OR strpos($_SERVER['REQUEST_URI'], 'wp-admin/post.php') !== FALSE OR strpos($_SERVER['REQUEST_URI'], 'wp-admin/post-new.php') !== FALSE)) {
146
+ if (!headers_sent()) {
147
+ header('X-UA-Compatible: IE=EmulateIE10');
148
+ }
149
+ }
150
+ }
151
+
152
  /**
153
  * Substitutes the gallery placeholder content with the gallery type frontend
154
  * view, returns a list of static resources that need to be loaded
156
  */
157
  function substitute_placeholder_imgs($content)
158
  {
159
+ // Get some utilities
160
+ $mapper = $this->get_registry()->get_utility('I_Displayed_Gallery_Mapper');
161
+ $router = $this->get_registry()->get_utility('I_Router');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
+ // To match ATP entries we compare the stored url against a generic path
164
+ // We must check HTTP and HTTPS as well as permalink and non-permalink forms
165
+ $preview_url = parse_url($router->join_paths(
166
+ $router->remove_url_segment('index.php', $router->get_base_url()),
167
+ '/nextgen-attach_to_post/preview'
168
+ ));
169
+ $router->debug = TRUE;
170
+ $preview_url = preg_quote($preview_url['host'] . $preview_url['path'], '#');
171
 
172
+ $alt_preview_url = parse_url($router->join_paths(
173
+ $router->remove_url_segment('index.php', $router->get_base_url()),
174
+ 'index.php/nextgen-attach_to_post/preview'
175
+ ));
176
+ $alt_preview_url = preg_quote($alt_preview_url['host'] . $alt_preview_url['path'], '#');
177
+
178
+ // The placeholder MUST have a gallery instance id
179
+ if (preg_match_all("#<img.*http(s)?://({$preview_url}|{$alt_preview_url})/id--(\\d+).*\\/>#mi", $content, $matches, PREG_SET_ORDER)) {
180
+ foreach ($matches as $match) {
181
+ // Find the displayed gallery
182
+ $displayed_gallery_id = $match[3];
183
+ $displayed_gallery = $mapper->find($displayed_gallery_id, TRUE);
184
+
185
+ // Get the content for the displayed gallery
186
+ $retval = '<p>'._('Invalid Displayed Gallery').'</p>';
187
+ if ($displayed_gallery) {
188
+ $renderer = $this->get_registry()->get_utility('I_Displayed_Gallery_Renderer');
189
+ $retval = $renderer->render($displayed_gallery, TRUE);
190
+ }
191
+ $content = str_replace($match[0], $retval, $content);
192
+ }
193
+ }
194
+
195
+ return $content;
196
  }
197
 
198
  /**
205
  // Enqueue resources needed at post/page level
206
  if (preg_match("/\/wp-admin\/(post|post-new)\.php$/", $_SERVER['SCRIPT_NAME'])) {
207
  $this->_enqueue_tinymce_resources();
 
 
 
 
 
 
 
208
  wp_enqueue_style(
209
  'ngg_attach_to_post_dialog', $router->get_static_url('photocrati-attach_to_post#attach_to_post_dialog.css')
210
  );
226
  wp_localize_script(
227
  'media-editor',
228
  'nextgen_gallery_attach_to_post_url',
229
+ C_NextGen_Settings::get_instance()->attach_to_post_url
230
  );
231
 
232
  // Registers our tinymce button and plugin for attaching galleries
324
  function new_gallery_event($gallery_id)
325
  {
326
  $gallery = $this->get_registry()->get_utility('I_Gallery_Mapper')->find($gallery_id);
327
+ if ($gallery) {
328
+ $this->_get_frame_event_publisher()->add_event(array(
329
+ 'event' => 'new_gallery',
330
+ 'gallery_id'=> intval($gallery_id),
331
+ 'gallery_title' => $gallery->title
332
+ ));
333
+ }
334
  }
335
 
336
  /**
products/photocrati_nextgen/modules/attach_to_post/static/attach_to_post.js CHANGED
@@ -6,35 +6,33 @@ function close_attach_to_post_window()
6
 
7
  // Adjusts the height of a frame on the page, and then executes
8
  // the specified callback
9
- function adjust_height_for_frame(frame, callback)
10
  {
11
  // Adjust height of the frame
12
- var $frame = jQuery(frame);
13
- var new_height = $frame.contents().find('#wpbody').height();
14
- var parent_height = jQuery(parent.document).height();
 
15
  var current_height = $frame.height();
16
 
17
- // If the height is less than the parent window height, then use
18
- // the parent window height instead
19
  if (new_height < parent_height) new_height = parent_height;
20
 
21
- // If the height has changed, then use the new height
22
- if (current_height != new_height) {
23
- var frame_id = $frame.attr('id');
24
-
25
- $frame.height(new_height);
26
-
27
- if (frame_id && frame_id.indexOf('ngg-iframe-') == 0) {
28
- var tab_id = frame_id.substr(11);
29
-
30
- if (tab_id) {
31
- jQuery('#' + tab_id).height(new_height);
32
- }
33
- }
34
- }
35
 
36
  if (callback != undefined)
37
- return callback.call(frame, new_height);
38
  else
39
  return true;
40
  }
6
 
7
  // Adjusts the height of a frame on the page, and then executes
8
  // the specified callback
9
+ function adjust_height_for_frame(parent_window, current_window, callback)
10
  {
11
  // Adjust height of the frame
12
+ var $frame = jQuery(current_window.frameElement);
13
+ var new_height = $frame.contents().height()/3;
14
+ var new_height_body = $frame.contents().find('#wpbody').height();
15
+ var parent_height = jQuery(parent_window.document).height();
16
  var current_height = $frame.height();
17
 
18
+ if (new_height < new_height_body) new_height = new_height_body;
 
19
  if (new_height < parent_height) new_height = parent_height;
20
 
21
+ if (current_height < new_height) {
22
+ $frame.height(new_height);
23
+
24
+ var frame_id = $frame.attr('id');
25
+ if (frame_id && frame_id.indexOf('ngg-iframe-') == 0) {
26
+ var tab_id = frame_id.substr(11);
27
+
28
+ if (tab_id) {
29
+ jQuery('#' + tab_id).height(new_height);
30
+ }
31
+ }
32
+ }
 
 
33
 
34
  if (callback != undefined)
35
+ return callback(parent_window, current_window, new_height);
36
  else
37
  return true;
38
  }
products/photocrati_nextgen/modules/attach_to_post/static/iframely.css CHANGED
@@ -1,4 +1,9 @@
1
- #iframely, #iframely body{
 
 
 
 
 
2
  padding: 0px;
3
  width: 100%;
4
  height: 100%;
1
+ /* keep the ATP background white */
2
+ html#iframely {
3
+ background: white !important;
4
+ }
5
+
6
+ #iframely, #iframely body {
7
  padding: 0px;
8
  width: 100%;
9
  height: 100%;
products/photocrati_nextgen/modules/attach_to_post/static/iframely.js CHANGED
@@ -1,7 +1,6 @@
1
  if (window.frameElement) {
2
  document.getElementsByTagName('html')[0].id = 'iframely';
3
  jQuery(function($){
4
- // Concentrate only on the content of the page
5
  $('#wpwrap').html($('#wpbody').html($('#wpbody-content').html($('#ngg_page_content'))));
6
 
7
  // We need to ensure that any POST operation includes the "attach_to_post"
@@ -10,14 +9,55 @@ if (window.frameElement) {
10
  $(this).append("<input type='hidden' name='attach_to_post' value='1'/>");
11
  });
12
 
13
- // Adjust the height of the frame
14
- parent.adjust_height_for_frame(window.frameElement, function(){
15
- $('#iframely').css({
16
- position: 'static',
17
- visibility: 'visible'
18
- }).animate({
19
- opacity: 1.0
20
- });
21
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  });
23
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  if (window.frameElement) {
2
  document.getElementsByTagName('html')[0].id = 'iframely';
3
  jQuery(function($){
 
4
  $('#wpwrap').html($('#wpbody').html($('#wpbody-content').html($('#ngg_page_content'))));
5
 
6
  // We need to ensure that any POST operation includes the "attach_to_post"
9
  $(this).append("<input type='hidden' name='attach_to_post' value='1'/>");
10
  });
11
 
12
+ var parent = window.parent;
13
+
14
+ if (parent == null || typeof(parent.adjust_height_for_frame) == "undefined") {
15
+ if (window != null && typeof(window.adjust_height_for_frame) != "undefined") {
16
+ parent = window;
17
+ }
18
+ }
19
+
20
+ // Adjust the height of the frame
21
+ var recursive_check = true;
22
+ if (recursive_check) {
23
+ if (typeof(parent.adjust_height_for_frame) != "undefined") {
24
+ parent.adjust_height_for_frame(parent, window, iframely_callback);
25
+ }
26
+ }
27
+ else {
28
+ if (typeof(parent.adjust_height_for_frame) != "undefined") {
29
+ // Adjust the height of the frame
30
+ parent.adjust_height_for_frame(parent, window, function(){
31
+ $('#iframely').css({
32
+ position: 'static',
33
+ visibility: 'visible'
34
+ }).animate({
35
+ opacity: 1.0
36
+ });
37
+ });
38
+ }
39
+ }
40
  });
41
  }
42
+
43
+ function iframely_callback(parent_window, current_window, new_height)
44
+ {
45
+ var $current_window = jQuery(current_window);
46
+
47
+ if (typeof($current_window.data('iframely')) == 'undefined') $current_window.data('iframely', {attempts: 1});
48
+ var iframely = $current_window.data('iframely');
49
+
50
+ // After we've attempted to resize the frame 3 times, give up
51
+ if (iframely.attempts == 3) {
52
+ jQuery('#iframely').css({
53
+ position: 'static',
54
+ visibility: 'visible'
55
+ }).animate({ opacity: 1.0 });
56
+ }
57
+ else {
58
+ iframely.attempts += 1;
59
+ setTimeout(function(){
60
+ parent_window.adjust_height_for_frame(parent_window, current_window, iframely_callback);
61
+ }, 400);
62
+ }
63
+ }
products/photocrati_nextgen/modules/attach_to_post/static/ngg_attach_to_post_tinymce_plugin.js CHANGED
@@ -1,6 +1,10 @@
1
  // Self-executing function to create and register the TinyMCE plugin
2
  (function(siteurl) {
3
 
 
 
 
 
4
  // Create the plugin. We'll register it afterwards
5
  tinymce.create('tinymce.plugins.NextGEN_AttachToPost', {
6
 
@@ -14,7 +18,7 @@
14
  */
15
  getInfo: function() {
16
  return {
17
- longname: 'NextGen - Attach Gallery',
18
  author: 'Photocrati Media',
19
  authorurl: 'http://www.photocrati.com',
20
  infourl: 'http://www.nextgen-gallery.com',
@@ -36,7 +40,7 @@
36
 
37
  // Add a button to trigger the above command
38
  editor.addButton('NextGEN_AttachToPost', {
39
- title: 'NextGEN Gallery - Attach To Post',
40
  cmd: 'ngg_attach_to_post',
41
  image: plugin_url+'/nextgen.gif'
42
  });
@@ -75,7 +79,6 @@
75
  }
76
  clearTimeout(click_timer);
77
  drag_in_progress = false;
78
- return false;
79
  });
80
  },
81
 
1
  // Self-executing function to create and register the TinyMCE plugin
2
  (function(siteurl) {
3
 
4
+ tinyMCE.addI18n('en.ngg_attach_to_post', {
5
+ title: 'Attach NextGEN Gallery to Post'
6
+ });
7
+
8
  // Create the plugin. We'll register it afterwards
9
  tinymce.create('tinymce.plugins.NextGEN_AttachToPost', {
10
 
18
  */
19
  getInfo: function() {
20
  return {
21
+ longname: 'NextGEN Gallery',
22
  author: 'Photocrati Media',
23
  authorurl: 'http://www.photocrati.com',
24
  infourl: 'http://www.nextgen-gallery.com',
40
 
41
  // Add a button to trigger the above command
42
  editor.addButton('NextGEN_AttachToPost', {
43
+ title: 'ngg_attach_to_post.title',
44
  cmd: 'ngg_attach_to_post',
45
  image: plugin_url+'/nextgen.gif'
46
  });
79
  }
80
  clearTimeout(click_timer);
81
  drag_in_progress = false;
 
82
  });
83
  },
84
 
products/photocrati_nextgen/modules/attach_to_post/templates/display_tab_js.php CHANGED
@@ -260,7 +260,7 @@ jQuery(function($){
260
  * A collection that can fetch it's entities from the server
261
  **/
262
  Ngg.Models.Remote_Collection = Ngg.Models.SelectableItems.extend({
263
- fetch_limit: 50,
264
  in_progress: false,
265
  fetch_url: photocrati_ajax.url,
266
  action: '',
@@ -296,6 +296,7 @@ jQuery(function($){
296
  var self = this;
297
  this.in_progress = true;
298
  $.post(this.fetch_url, this._create_request(limit, offset), function(response){
 
299
  if (!_.isObject(response)) response = JSON.parse(response);
300
 
301
  if (response.items) {
@@ -808,6 +809,9 @@ jQuery(function($){
808
  this.entities.remove(model, {silent: true});
809
  this.entities.add(model, {at: model.changed.sortorder, silent: true});
810
  this.displayed_gallery.set('sortorder', this.entities.entity_ids());
 
 
 
811
  this.displayed_gallery.set('order_by', 'sortorder');
812
  }, this);
813
 
@@ -1014,6 +1018,8 @@ jQuery(function($){
1014
  }
1015
  ]);
1016
  this.sortdirection_options.on('change:selected', this.sortdirection_changed, this);
 
 
1017
  },
1018
 
1019
  populate_sorting_fields: function(){
@@ -1038,6 +1044,7 @@ jQuery(function($){
1038
 
1039
  fill_image_sortorder_options: function(){
1040
  this.sortorder_options.reset();
 
1041
  this.sortorder_options.push(this.create_sortorder_option('sortorder', 'Custom'));
1042
  this.sortorder_options.push(this.create_sortorder_option(Ngg.DisplayTab.instance.image_key, 'Image ID'));
1043
  this.sortorder_options.push(this.create_sortorder_option('filename', 'Filename'));
@@ -1047,16 +1054,38 @@ jQuery(function($){
1047
 
1048
  fill_gallery_sortorder_options: function(){
1049
  this.sortorder_options.reset();
 
1050
  this.sortorder_options.push(this.create_sortorder_option('sortorder' ,'Custom'));
1051
  this.sortorder_options.push(this.create_sortorder_option('name', 'Name'));
1052
  this.sortorder_options.push(this.create_sortorder_option('galdesc', 'Description'));
1053
  },
1054
 
 
 
 
 
 
 
 
 
 
1055
  sortoption_changed: function(model){
1056
  this.sortorder_options.each(function(item){
1057
  item.set('selected', model.get('value') == item.get('value') ? true : false, {silent: true});
1058
  });
1059
- this.displayed_gallery.set('order_by', model.get('value'));
 
 
 
 
 
 
 
 
 
 
 
 
1060
  this.entities.reset();
1061
  this.$el.find('a.sortorder').each(function(){
1062
  var $item = $(this);
@@ -1068,6 +1097,7 @@ jQuery(function($){
1068
  },
1069
 
1070
  sortdirection_changed: function(model){
 
1071
  this.sortdirection_options.each(function(item){
1072
  item.set('selected', model.get('value') == item.get('value') ? true : false, {silent: true});
1073
  });
@@ -1147,10 +1177,15 @@ jQuery(function($){
1147
  this[key] = value;
1148
  }, this);
1149
  this.model.on('change', this.render, this);
 
 
 
1150
  this.id = this.model.get('id_field')+'_'+this.model.entity_id()
1151
  },
1152
 
1153
  item_dropped: function(e, index){
 
 
1154
  this.model.set('sortorder', index);
1155
  },
1156
 
@@ -1360,7 +1395,7 @@ jQuery(function($){
1360
  var request = <?php echo $sec_token?>;
1361
  request = _.extend(request, {
1362
  action: 'save_displayed_gallery',
1363
- displayed_gallery: this.displayed_gallery.toJSON()
1364
  });
1365
 
1366
  var self = this;
@@ -1457,10 +1492,11 @@ jQuery(function($){
1457
  this.display_types = new Ngg.DisplayTab.Models.Display_Type_Collection(
1458
  <?php echo $display_types ?>
1459
  );
1460
- this.display_type_order_base = <?php echo NEXTGEN_DISPLAY_PRIORITY_BASE; ?>;
1461
- this.display_type_order_step = <?php echo NEXTGEN_DISPLAY_PRIORITY_STEP; ?>;
1462
  this.entities = new Ngg.DisplayTab.Models.Entity_Collection();
1463
  this.entities.extra_data.displayed_gallery = this.displayed_gallery;
 
1464
 
1465
  // Pre-select current displayed gallery values
1466
  if (this.displayed_gallery.get('source')) {
@@ -1648,6 +1684,8 @@ jQuery(function($){
1648
  });
1649
  Ngg.DisplayTab.instance = new Ngg.DisplayTab.App();
1650
  Ngg.DisplayTab.instance.render();
 
 
1651
 
1652
  // Invoke styling libraries
1653
  $('span.tooltip, label.tooltip').tooltip();
260
  * A collection that can fetch it's entities from the server
261
  **/
262
  Ngg.Models.Remote_Collection = Ngg.Models.SelectableItems.extend({
263
+ fetch_limit: 5000,
264
  in_progress: false,
265
  fetch_url: photocrati_ajax.url,
266
  action: '',
296
  var self = this;
297
  this.in_progress = true;
298
  $.post(this.fetch_url, this._create_request(limit, offset), function(response){
299
+ if (typeof(_) == 'undefined') return;
300
  if (!_.isObject(response)) response = JSON.parse(response);
301
 
302
  if (response.items) {
809
  this.entities.remove(model, {silent: true});
810
  this.entities.add(model, {at: model.changed.sortorder, silent: true});
811
  this.displayed_gallery.set('sortorder', this.entities.entity_ids());
812
+ if (typeof(console) != 'undefined' && typeof(console.log) != 'undefined') {
813
+ console.log(this.entities.entity_ids());
814
+ }
815
  this.displayed_gallery.set('order_by', 'sortorder');
816
  }, this);
817
 
1018
  }
1019
  ]);
1020
  this.sortdirection_options.on('change:selected', this.sortdirection_changed, this);
1021
+ this.displayed_gallery.on('change:order_by', this.displayed_gallery_order_changed, this);
1022
+ this.displayed_gallery.on('change.order_direction', this.displayed_gallery_order_dir_changed, this);
1023
  },
1024
 
1025
  populate_sorting_fields: function(){
1044
 
1045
  fill_image_sortorder_options: function(){
1046
  this.sortorder_options.reset();
1047
+ this.sortorder_options.push(this.create_sortorder_option('', 'None'));
1048
  this.sortorder_options.push(this.create_sortorder_option('sortorder', 'Custom'));
1049
  this.sortorder_options.push(this.create_sortorder_option(Ngg.DisplayTab.instance.image_key, 'Image ID'));
1050
  this.sortorder_options.push(this.create_sortorder_option('filename', 'Filename'));
1054
 
1055
  fill_gallery_sortorder_options: function(){
1056
  this.sortorder_options.reset();
1057
+ this.sortorder_options.push(this.create_sortorder_option('', 'None'));
1058
  this.sortorder_options.push(this.create_sortorder_option('sortorder' ,'Custom'));
1059
  this.sortorder_options.push(this.create_sortorder_option('name', 'Name'));
1060
  this.sortorder_options.push(this.create_sortorder_option('galdesc', 'Description'));
1061
  },
1062
 
1063
+ displayed_gallery_order_changed: function(e){
1064
+ this.sortorder_options.findWhere({value: e.get('order_by')}).set('selected', true);
1065
+ },
1066
+
1067
+
1068
+ displayed_gallery_order_dir_changed: function(e){
1069
+ this.sortdirection_options.findWhere({value: e.get('order_direction')}).set('selected', true);
1070
+ },
1071
+
1072
  sortoption_changed: function(model){
1073
  this.sortorder_options.each(function(item){
1074
  item.set('selected', model.get('value') == item.get('value') ? true : false, {silent: true});
1075
  });
1076
+
1077
+ this.displayed_gallery.set('sortorder', []);
1078
+
1079
+ var sort_by = model.get('value');
1080
+
1081
+ // If "None" was selected, then clear the "sortorder" property
1082
+ if (model.get('value').length == 0) {
1083
+ sort_by = 'sortorder';
1084
+ }
1085
+
1086
+ // Change the "sort by" parameter
1087
+ this.displayed_gallery.set('order_by', sort_by);
1088
+
1089
  this.entities.reset();
1090
  this.$el.find('a.sortorder').each(function(){
1091
  var $item = $(this);
1097
  },
1098
 
1099
  sortdirection_changed: function(model){
1100
+
1101
  this.sortdirection_options.each(function(item){
1102
  item.set('selected', model.get('value') == item.get('value') ? true : false, {silent: true});
1103
  });
1177
  this[key] = value;
1178
  }, this);
1179
  this.model.on('change', this.render, this);
1180
+ if (this.model.get('sortorder') == 0) {
1181
+ this.model.set('sortorder', -1, {silent: true});
1182
+ }
1183
  this.id = this.model.get('id_field')+'_'+this.model.entity_id()
1184
  },
1185
 
1186
  item_dropped: function(e, index){
1187
+ Ngg.DisplayTab.instance.displayed_gallery.set('order_by', 'sortorder');
1188
+ //Ngg.DisplayTab.instance.displayed_gallery.set('order_direction', 'ASC');
1189
  this.model.set('sortorder', index);
1190
  },
1191
 
1395
  var request = <?php echo $sec_token?>;
1396
  request = _.extend(request, {
1397
  action: 'save_displayed_gallery',
1398
+ displayed_gallery: JSON.stringify(this.displayed_gallery.toJSON())
1399
  });
1400
 
1401
  var self = this;
1492
  this.display_types = new Ngg.DisplayTab.Models.Display_Type_Collection(
1493
  <?php echo $display_types ?>
1494
  );
1495
+ this.display_type_order_base = <?php echo NGG_DISPLAY_PRIORITY_BASE; ?>;
1496
+ this.display_type_order_step = <?php echo NGG_DISPLAY_PRIORITY_STEP; ?>;
1497
  this.entities = new Ngg.DisplayTab.Models.Entity_Collection();
1498
  this.entities.extra_data.displayed_gallery = this.displayed_gallery;
1499
+ this.image_key = "<?php echo $image_primary_key ?>";
1500
 
1501
  // Pre-select current displayed gallery values
1502
  if (this.displayed_gallery.get('source')) {
1684
  });
1685
  Ngg.DisplayTab.instance = new Ngg.DisplayTab.App();
1686
  Ngg.DisplayTab.instance.render();
1687
+
1688
+ window.Ngg = Ngg;
1689
 
1690
  // Invoke styling libraries
1691
  $('span.tooltip, label.tooltip').tooltip();
products/photocrati_nextgen/modules/cache/class.cache.php CHANGED
@@ -59,10 +59,10 @@ class Mixin_Cache extends Mixin
59
 
60
  foreach ($iterator as $file) {
61
  if ($file->isFile() || $file->isLink()) {
62
- unlink($file->getPathname());
63
  }
64
  elseif ($file->isDir() && !$file->isDot() && $recursive) {
65
- rmdir($file->getPathname());
66
  }
67
  }
68
  }
59
 
60
  foreach ($iterator as $file) {
61
  if ($file->isFile() || $file->isLink()) {
62
+ @unlink($file->getPathname());
63
  }
64
  elseif ($file->isDir() && !$file->isDot() && $recursive) {
65
+ @rmdir($file->getPathname());
66
  }
67
  }
68
  }
products/photocrati_nextgen/modules/cache/module.cache.php CHANGED
@@ -15,7 +15,7 @@ class M_Cache extends C_Base_Module
15
  'photocrati-cache',
16
  'Cache',
17
  'Handles clearing of NextGen caches',
18
- '0.1',
19
  'http://www.nextgen-gallery.com',
20
  'Photocrati Media',
21
  'http://www.photocrati.com'
15
  'photocrati-cache',
16
  'Cache',
17
  'Handles clearing of NextGen caches',
18
+ '0.2',
19
  'http://www.nextgen-gallery.com',
20
  'Photocrati Media',
21
  'http://www.photocrati.com'
products/photocrati_nextgen/modules/datamapper/class.custompost_datamapper_driver.php CHANGED
@@ -30,6 +30,7 @@ class Mixin_CustomPost_DataMapper_Driver extends Mixin
30
  'is_select' => TRUE,
31
  'is_delete' => FALSE
32
  );
 
33
  return $this->object;
34
  }
35
 
@@ -252,18 +253,22 @@ class Mixin_CustomPost_DataMapper_Driver extends Mixin
252
  */
253
  function convert_post_to_entity($post, $model=FALSE)
254
  {
255
-
256
  $entity = new stdClass();
257
- foreach ($post as $key => $value) {
258
- if ($key == 'post_content') {
259
- $post_content = $this->object->unserialize($value);
260
- if ($post_content) {
261
- foreach ($post_content as $key2 => $value2) {
262
- $entity->$key2 = $value2;
263
- }
264
  }
265
  }
266
- else $entity->$key = $value;
 
 
 
 
 
 
267
  }
268
  $this->object->_convert_to_entity($entity);
269
  return $model? $this->object->convert_to_model($entity) : $entity;
@@ -282,10 +287,12 @@ class Mixin_CustomPost_DataMapper_Driver extends Mixin
282
  if (!($entity instanceof stdClass)) $post = $entity->get_entity();
283
 
284
  // Create the post content
 
 
285
  unset($post->id_field);
286
  unset($post->post_content_filtered);
287
  unset($post->post_content);
288
- $post->post_content = $this->object->serialize($post);
289
  $post->post_content_filtered = $post->post_content;
290
  $post->post_type = $this->object->get_object_name();
291
 
@@ -335,7 +342,14 @@ class Mixin_CustomPost_DataMapper_Driver extends Mixin
335
  /* @var $wpdb wpdb */
336
  global $wpdb;
337
  if (!is_array($omit)) $omit = array($omit);
 
 
 
 
 
338
  $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE post_id = %s", $post_id));
 
 
339
  $sql_parts = array();
340
  foreach($entity as $key => $value) {
341
  if (in_array($key, $omit)) continue;
@@ -367,8 +381,9 @@ class Mixin_CustomPost_DataMapper_Driver extends Mixin
367
  $post_id,
368
  $entity instanceof stdClass ? $entity : $entity->get_entity()
369
  );
370
- }
371
 
 
 
372
  $entity->id_field = $primary_key;
373
 
374
  return $post_id;
@@ -423,17 +438,28 @@ class Mixin_CustomPost_DataMapper_Driver extends Mixin
423
  }
424
 
425
  // Execute the query
426
- $query = new WP_Query($this->object->_query_args);
 
 
 
427
  foreach ($query->get_posts() as $row) {
428
- $row = $this->object->convert_post_to_entity($this->scrub_result($row), $model);
429
- if (!$model)
430
- $row->id_field = $this->object->get_primary_key_column();
431
- $retval[] = $row;
432
  }
 
433
 
434
  return $retval;
435
  }
436
 
 
 
 
 
 
 
 
 
 
 
437
  /**
438
  * Fetches the last row
439
  * @param array $conditions
@@ -509,17 +535,13 @@ class C_CustomPost_DataMapper_Driver extends C_DataMapper_Driver_Base
509
 
510
  function define($object_name, $context=FALSE)
511
  {
 
 
512
  parent::define($object_name, $context);
513
  $this->add_mixin('Mixin_CustomPost_DataMapper_Driver');
514
  $this->implement('I_CustomPost_DataMapper');
515
  }
516
 
517
- function initialize($object_name)
518
- {
519
- if (strlen($object_name) > 20) throw new Exception("The custom post name can be no longer than 20 characters long");
520
- parent::initialize($object_name);
521
- }
522
-
523
 
524
  /**
525
  * Gets the name of the table
30
  'is_select' => TRUE,
31
  'is_delete' => FALSE
32
  );
33
+
34
  return $this->object;
35
  }
36
 
253
  */
254
  function convert_post_to_entity($post, $model=FALSE)
255
  {
 
256
  $entity = new stdClass();
257
+
258
+ // Unserialize the post content field
259
+ if (is_string($post->post_content)) {
260
+ if (($post_content = $this->object->unserialize($post->post_content))) {
261
+ foreach ($post_content as $key => $value) {
262
+ $post->$key = $value;
 
263
  }
264
  }
265
+
266
+ }
267
+ unset($post->post_content);
268
+
269
+ // Copy all fields to the entity
270
+ foreach ($post as $key => $value) {
271
+ $entity->$key = $value;
272
  }
273
  $this->object->_convert_to_entity($entity);
274
  return $model? $this->object->convert_to_model($entity) : $entity;
287
  if (!($entity instanceof stdClass)) $post = $entity->get_entity();
288
 
289
  // Create the post content
290
+ $post_content = clone $post;
291
+ foreach ($this->object->_table_columns as $column) unset($post_content->$column);
292
  unset($post->id_field);
293
  unset($post->post_content_filtered);
294
  unset($post->post_content);
295
+ $post->post_content = $this->object->serialize($post_content);
296
  $post->post_content_filtered = $post->post_content;
297
  $post->post_type = $this->object->get_object_name();
298
 
342
  /* @var $wpdb wpdb */
343
  global $wpdb;
344
  if (!is_array($omit)) $omit = array($omit);
345
+
346
+ // By default, we omit creating meta values for columns in the posts table
347
+ $omit = array_merge($omit, $this->object->_table_columns);
348
+
349
+ // Delete the existing meta values
350
  $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE post_id = %s", $post_id));
351
+
352
+ // Create query for new meta values
353
  $sql_parts = array();
354
  foreach($entity as $key => $value) {
355
  if (in_array($key, $omit)) continue;
381
  $post_id,
382
  $entity instanceof stdClass ? $entity : $entity->get_entity()
383
  );
 
384
 
385
+ $entity->$primary_key = $post_id;
386
+ }
387
  $entity->id_field = $primary_key;
388
 
389
  return $post_id;
438
  }
439
 
440
  // Execute the query
441
+ $query = new WP_Query();
442
+ if (isset($this->object->debug)) $this->object->_query_args['debug'] = TRUE;
443
+ $query->query_vars = $this->object->_query_args;
444
+ add_action('pre_get_posts', array(&$this, 'set_query_args'), PHP_INT_MAX-1, 1);
445
  foreach ($query->get_posts() as $row) {
446
+ $retval[] = $this->object->convert_post_to_entity($row, $model);
 
 
 
447
  }
448
+ remove_action('pre_get_posts', array(&$this, 'set_query_args'), PHP_INT_MAX-1, 1);
449
 
450
  return $retval;
451
  }
452
 
453
+ /**
454
+ * Ensure that the query args are set. We need to do this in case a third-party
455
+ * plugin overrides our query
456
+ * @param $query
457
+ */
458
+ function set_query_args($query)
459
+ {
460
+ if ($query->get('datamapper')) $query->query_vars = $this->object->_query_args;
461
+ }
462
+
463
  /**
464
  * Fetches the last row
465
  * @param array $conditions
535
 
536
  function define($object_name, $context=FALSE)
537
  {
538
+ if (strlen($object_name) > 20) throw new Exception("The custom post name can be no longer than 20 characters long");
539
+
540
  parent::define($object_name, $context);
541
  $this->add_mixin('Mixin_CustomPost_DataMapper_Driver');
542
  $this->implement('I_CustomPost_DataMapper');
543
  }
544
 
 
 
 
 
 
 
545
 
546
  /**
547
  * Gets the name of the table
products/photocrati_nextgen/modules/datamapper/class.customtable_datamapper_driver.php CHANGED
@@ -18,10 +18,11 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin
18
  * specify DB columns
19
  * @param string $fields
20
  */
21
- function select($fields='*')
22
  {
23
  // Create a fresh slate
24
  $this->object->_init();
 
25
  $this->object->_select_clause = "SELECT {$fields}";
26
 
27
  return $this->object;
@@ -168,7 +169,7 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin
168
  * Returns the generated SQL query to be executed
169
  * @return string
170
  */
171
- function get_generated_query()
172
  {
173
  $sql = array();
174
 
@@ -182,8 +183,8 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin
182
  if ($where_clauses) $sql[] = 'WHERE '.implode(' AND ', $where_clauses);
183
 
184
  if ($this->object->is_select_statement()) {
185
- if ($this->object->_order_clauses) $sql[] = 'ORDER BY '.implode(', ', $this->object->_order_clauses);
186
  if ($this->object->_group_by_columns) $sql[] = 'GROUP BY '.implode(', ', $this->object->_group_by_columns);
 
187
  if ($this->object->_limit_clause) $sql[] = $this->object->_limit_clause;
188
  }
189
  return implode(' ', $sql);
@@ -201,13 +202,14 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin
201
 
202
  // Or generate SQL query
203
  if (!$sql)
204
- $sql = $this->object->get_generated_query();
205
 
206
  // If we have a SQL statement to execute, then heck, execute it!
207
  if ($sql)
208
  {
209
- if ($this->object->debug)
210
- var_dump($sql);
 
211
 
212
  $this->_wpdb()->query($sql);
213
 
@@ -220,11 +222,19 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin
220
  $retval = $this->_wpdb()->last_result;
221
  }
222
  else {
 
223
  foreach ($this->_wpdb()->last_result as $row) {
224
- $retval[] = $this->_convert_to_entity($this->scrub_result($row));
 
 
 
 
225
  }
226
  }
227
  }
 
 
 
228
  }
229
 
230
  return $retval;
@@ -240,7 +250,7 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin
240
 
241
  unset($entity->id_field);
242
  $primary_key = $this->object->get_primary_key_column();
243
- if (isset($entity->$primary_key)) {
244
  if($this->object->_update($entity)) $retval = intval($entity->$primary_key);
245
  }
246
  else {
@@ -359,68 +369,48 @@ class C_CustomTable_DataMapper_Driver_Mixin extends Mixin
359
  return $retval;
360
  }
361
 
362
-
363
- /**
364
- * Looks up using SQL the columns existing in the database
365
- */
366
- function lookup_columns()
367
  {
368
- $this->object->_columns = array();
369
- $sql = "SHOW COLUMNS FROM `{$this->object->get_table_name()}`";
370
- foreach ($this->object->run_query($sql, TRUE) as $row) {
371
- $this->object->_columns[] = $row->Field;
372
  }
373
- return $this->object->_columns;
374
  }
375
 
376
- /**
377
- * Determines whether a column is present for the table
378
- * @param string $column_name
379
- * @return string
380
- */
381
- function has_column($column_name)
382
  {
383
- if (empty($this->object->_columns)) $this->object->lookup_columns();
384
- return array_search($column_name, $this->object->_columns);
385
  }
386
 
387
  /**
388
- * Defines a column for this table
389
- * @param string $column_name
390
- * @param string $datatype
391
  */
392
- function define_column($column_name, $datatype)
393
  {
394
- $this->object->_defined_columns[$column_name] = $datatype;
395
- }
396
-
397
- function add_column($column_name, $datatype=FALSE)
398
- {
399
- // If no datatype was specified, perhaps the column was already defined
400
- if (!$datatype && isset($this->object->_defined_columns[$column_name])) {
401
- $datatype = $this->object->_defined_columns[$column_name];
402
  }
403
 
404
- // Ensure that we have a datatype before continuing...
405
- if ($datatype) {
406
- $sql = "ALTER TABLE `{$this->get_table_name()}` ADD COLUMN ``{$column_name}` {$datatype}";
407
- $this->object->run_query($sql);
408
- }
409
 
410
- $this->object->lookup_columns();
411
- }
 
 
 
 
412
 
413
- /**
414
- * Migrates the schema of the database
415
- */
416
- function migrate()
417
- {
418
- if (empty($this->object->_columns)) $this->object->lookup_columns();
419
- foreach ($this->object->_columns as $column_name) {
420
- if (!$this->object->has_column($column_name)) {
421
- $this->object->add_column($column_name);
422
  }
423
  }
 
 
424
  }
425
 
426
 
@@ -446,21 +436,20 @@ class C_CustomTable_DataMapper_Driver extends C_DataMapper_Driver_Base
446
  var $_limit_clause = '';
447
  var $_select_clause = '';
448
  var $_delete_clause = '';
449
- var $_columns = array();
450
- var $_defined_columns = array();
451
 
452
  function define($object_name, $context=FALSE)
453
  {
454
- parent::define($context);
455
  $this->add_mixin('C_CustomTable_DataMapper_Driver_Mixin');
456
  $this->implement('I_CustomTable_DataMapper');
457
  }
458
 
459
- function initialize($object_name)
460
  {
461
  parent::initialize($object_name);
462
  if (!isset($this->_primary_key_column))
463
  $this->_primary_key_column = $this->_lookup_primary_key_column();
 
464
  }
465
 
466
  /**
18
  * specify DB columns
19
  * @param string $fields
20
  */
21
+ function select($fields=NULL)
22
  {
23
  // Create a fresh slate
24
  $this->object->_init();
25
+ if (!$fields OR $fields == '*') $fields = $this->get_table_name().'.*';
26
  $this->object->_select_clause = "SELECT {$fields}";
27
 
28
  return $this->object;
169
  * Returns the generated SQL query to be executed
170
  * @return string
171
  */
172
+ function get_generated_query($no_entities=FALSE)
173
  {
174
  $sql = array();
175
 
183
  if ($where_clauses) $sql[] = 'WHERE '.implode(' AND ', $where_clauses);
184
 
185
  if ($this->object->is_select_statement()) {
 
186
  if ($this->object->_group_by_columns) $sql[] = 'GROUP BY '.implode(', ', $this->object->_group_by_columns);
187
+ if ($this->object->_order_clauses) $sql[] = 'ORDER BY '.implode(', ', $this->object->_order_clauses);
188
  if ($this->object->_limit_clause) $sql[] = $this->object->_limit_clause;
189
  }
190
  return implode(' ', $sql);
202
 
203
  // Or generate SQL query
204
  if (!$sql)
205
+ $sql = $this->object->get_generated_query($no_entities);
206
 
207
  // If we have a SQL statement to execute, then heck, execute it!
208
  if ($sql)
209
  {
210
+ if ($this->object->debug) {
211
+ var_dump($sql);
212
+ }
213
 
214
  $this->_wpdb()->query($sql);
215
 
222
  $retval = $this->_wpdb()->last_result;
223
  }
224
  else {
225
+ $id_field = $this->get_primary_key_column();
226
  foreach ($this->_wpdb()->last_result as $row) {
227
+ if ($row) {
228
+ if (isset($row->$id_field)) {
229
+ $retval[] = $this->object->_convert_to_entity($row);
230
+ }
231
+ }
232
  }
233
  }
234
  }
235
+ elseif ($this->object->debug) {
236
+ var_dump("No entities returned from query");
237
+ }
238
  }
239
 
240
  return $retval;
250
 
251
  unset($entity->id_field);
252
  $primary_key = $this->object->get_primary_key_column();
253
+ if (isset($entity->$primary_key) && $entity->$primary_key > 0) {
254
  if($this->object->_update($entity)) $retval = intval($entity->$primary_key);
255
  }
256
  else {
369
  return $retval;
370
  }
371
 
372
+ function _add_column($column_name, $datatype, $default_value=NULL)
 
 
 
 
373
  {
374
+ $sql = "ALTER TABLE `{$this->get_table_name()}` ADD COLUMN `{$column_name}` {$datatype}";
375
+ if ($default_value) {
376
+ if (is_string($default_value)) $default_value = str_replace("'", "\\'", $default_value);
377
+ $sql .= " NOT NULL DEFAULT " . (is_string($default_value) ? "'{$default_value}" : "{$default_value}");
378
  }
379
+ $this->object->_wpdb()->query($sql);
380
  }
381
 
382
+ function _remove_column($column_name)
 
 
 
 
 
383
  {
384
+ $sql = "ALTER TABLE `{$this->get_table_name()}` DROP COLUMN `{$column_name}`";
385
+ $this->object->_wpdb()->query($sql);
386
  }
387
 
388
  /**
389
+ * Migrates the schema of the database
 
 
390
  */
391
+ function migrate($lookup=TRUE)
392
  {
393
+ if (!$this->object->_columns) {
394
+ throw new E_ColumnsNotDefinedException("Columns not defined for {$this->get_table_name()}");
 
 
 
 
 
 
395
  }
396
 
397
+ if ($lookup) $this->lookup_columns();
 
 
 
 
398
 
399
+ // Add any missing columns
400
+ foreach ($this->object->_columns as $key => $properties) {
401
+ if (!in_array($key, $this->object->_table_columns)) {
402
+ $this->object->_add_column($key, $properties['type'], $properties['default_value']);
403
+ }
404
+ }
405
 
406
+ // Remove any columns not defined
407
+ foreach ($this->object->_table_columns as $key) {
408
+ if (!isset($this->object->_columns[$key])) {
409
+ //$this->object->_remove_column($key);
 
 
 
 
 
410
  }
411
  }
412
+
413
+ $this->object->lookup_columns();
414
  }
415
 
416
 
436
  var $_limit_clause = '';
437
  var $_select_clause = '';
438
  var $_delete_clause = '';
 
 
439
 
440
  function define($object_name, $context=FALSE)
441
  {
442
+ parent::define($object_name, $context);
443
  $this->add_mixin('C_CustomTable_DataMapper_Driver_Mixin');
444
  $this->implement('I_CustomTable_DataMapper');
445
  }
446
 
447
+ function initialize($object_name=FALSE)
448
  {
449
  parent::initialize($object_name);
450
  if (!isset($this->_primary_key_column))
451
  $this->_primary_key_column = $this->_lookup_primary_key_column();
452
+ $this->migrate(FALSE);
453
  }
454
 
455
  /**
products/photocrati_nextgen/modules/datamapper/class.datamapper_driver_base.php CHANGED
@@ -3,7 +3,13 @@
3
  /**
4
  * Thrown when an entity does not exist
5
  */
6
- class E_EntityNotFoundException extends RuntimeException
 
 
 
 
 
 
7
  {
8
 
9
  }
@@ -13,7 +19,7 @@ class E_EntityNotFoundException extends RuntimeException
13
  * array which is not yet supported due to a problem with references and the
14
  * call_user_func_array() function.
15
  */
16
- class E_InvalidEntityException extends RuntimeException
17
  {
18
  function __construct($message_or_previous=FALSE, $code=0, $previous=NULL)
19
  {
@@ -56,6 +62,24 @@ class Mixin_DataMapper_Driver_Base extends Mixin
56
  );
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  /**
60
  * Serializes the data
61
  * @param mixed $value
@@ -76,6 +100,7 @@ class Mixin_DataMapper_Driver_Base extends Mixin
76
  function unserialize($value)
77
  {
78
  $retval = NULL;
 
79
  if (is_string($value))
80
  {
81
  $retval = stripcslashes($value);
@@ -267,9 +292,10 @@ class Mixin_DataMapper_Driver_Base extends Mixin
267
  // A bind could be an array, used for the 'IN' operator
268
  // or a simple scalar value. We need to convert arrays
269
  // into scalar values
270
- if (is_object($bind)) $bind = (array)$bind;
271
- if (is_array($bind)) {
272
- if (empty($bind)) return FALSE;
 
273
  foreach ($bind as &$val) {
274
  if (!is_numeric($val)) {
275
  $val = '"'.addslashes($val).'"';
@@ -278,7 +304,12 @@ class Mixin_DataMapper_Driver_Base extends Mixin
278
  }
279
  $bind = implode(',', $bind);
280
  }
281
- elseif(!is_numeric($bind)) $numeric = FALSE;
 
 
 
 
 
282
  }
283
  $condition = $wpdb->prepare($condition, $binds);
284
 
@@ -337,9 +368,15 @@ class Mixin_DataMapper_Driver_Base extends Mixin
337
  // Add name of the id_field to the entity, and convert
338
  // the ID to an integer
339
  $stdObject->id_field = $key = $this->object->get_primary_key_column();
340
- if (isset($stdObject->$key)) {
341
- $stdObject->$key = (int) $stdObject->$key;
342
- }
 
 
 
 
 
 
343
 
344
  // Set defaults for this entity
345
  $this->object->set_defaults($stdObject);
@@ -347,6 +384,47 @@ class Mixin_DataMapper_Driver_Base extends Mixin
347
  return $stdObject;
348
  }
349
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  /**
351
  * Converts a stdObject entity to a model
352
  * @param stdObject $stdObject
@@ -380,7 +458,7 @@ class Mixin_DataMapper_Driver_Base extends Mixin
380
  $entity = new stdClass;
381
  foreach ($properties as $k=>$v) $entity->$k = $v;
382
  }
383
- return $factory->create($this->object->get_model_factory_method(), $this->object, $entity, $context);
384
  }
385
 
386
 
@@ -502,45 +580,79 @@ class Mixin_DataMapper_Driver_Base extends Mixin
502
  }
503
  }
504
 
505
- function scrub_result($result)
506
- {
507
- if (is_object($result))
508
- {
509
- $new_result = new stdClass();
510
- foreach ($result as $key => $value) {
511
- $new_value = $this->scrub_result($value);
512
- $new_result->$key = $new_value;
513
- }
514
- return $new_result;
515
- }
516
- else if (is_array($result)) {
517
- $new_array = array();
518
- foreach ($result as $key => $value) {
519
- $new_array[$key] = $this->scrub_result($value);
520
- }
521
- return $new_array;
522
- } else {
523
- return stripslashes($result);
524
- }
525
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  }
527
 
528
  class C_DataMapper_Driver_Base extends C_Component
529
  {
530
  var $_object_name;
531
  var $_model_factory_method = FALSE;
 
 
 
532
 
533
  function define($object_name, $context=FALSE)
534
  {
535
  parent::define($context);
536
  $this->add_mixin('Mixin_DataMapper_Driver_Base');
537
  $this->implement('I_DataMapper_Driver');
 
538
  }
539
 
540
- function initialize($object_name)
541
  {
542
  parent::initialize();
543
- $this->_object_name = $object_name;
 
 
 
 
 
544
  }
545
 
546
  /**
@@ -563,6 +675,32 @@ class C_DataMapper_Driver_Base extends C_Component
563
  return $table_prefix.$this->_object_name;
564
  }
565
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
566
  /**
567
  * Sets the name of the factory method used to create a model for this entity
568
  * @param string $method_name
3
  /**
4
  * Thrown when an entity does not exist
5
  */
6
+ class E_EntityNotFoundException extends E_NggErrorException
7
+ {
8
+
9
+ }
10
+
11
+
12
+ class E_ColumnsNotDefinedException extends E_NggErrorException
13
  {
14
 
15
  }
19
  * array which is not yet supported due to a problem with references and the
20
  * call_user_func_array() function.
21
  */
22
+ class E_InvalidEntityException extends E_NggErrorException
23
  {
24
  function __construct($message_or_previous=FALSE, $code=0, $previous=NULL)
25
  {
62
  );
63
  }
64
 
65
+ /**
66
+ * Notes that a particular columns is serialized, and should be unserialized when converted to an entity
67
+ * @param $column
68
+ */
69
+ function add_serialized_column($column)
70
+ {
71
+ $this->object->_serialized_columns[] = $column;
72
+ }
73
+
74
+ function unserialize_columns($object)
75
+ {
76
+ foreach ($this->object->_serialized_columns as $column) {
77
+ if (isset($object->$column) && is_string($object->$column)) {
78
+ $object->$column = $this->unserialize($object->$column);
79
+ }
80
+ }
81
+ }
82
+
83
  /**
84
  * Serializes the data
85
  * @param mixed $value
100
  function unserialize($value)
101
  {
102
  $retval = NULL;
103
+
104
  if (is_string($value))
105
  {
106
  $retval = stripcslashes($value);
292
  // A bind could be an array, used for the 'IN' operator
293
  // or a simple scalar value. We need to convert arrays
294
  // into scalar values
295
+ if (is_object($bind))
296
+ $bind = (array)$bind;
297
+
298
+ if (is_array($bind) && !empty($bind)) {
299
  foreach ($bind as &$val) {
300
  if (!is_numeric($val)) {
301
  $val = '"'.addslashes($val).'"';
304
  }
305
  $bind = implode(',', $bind);
306
  }
307
+ else if (is_array($bind) && empty($bind)) {
308
+ $bind = 'NULL';
309
+ }
310
+ else if(!is_numeric($bind)) {
311
+ $numeric = FALSE;
312
+ }
313
  }
314
  $condition = $wpdb->prepare($condition, $binds);
315
 
368
  // Add name of the id_field to the entity, and convert
369
  // the ID to an integer
370
  $stdObject->id_field = $key = $this->object->get_primary_key_column();
371
+
372
+ // Cast columns to their appropriate data type
373
+ $this->cast_columns($stdObject);
374
+
375
+ // Strip slashes
376
+ $this->strip_slashes($stdObject);
377
+
378
+ // Unserialize columns
379
+ $this->unserialize_columns($stdObject);
380
 
381
  // Set defaults for this entity
382
  $this->object->set_defaults($stdObject);
384
  return $stdObject;
385
  }
386
 
387
+
388
+ function strip_slashes($stdObject)
389
+ {
390
+ foreach (get_object_vars($stdObject) as $key => $value) {
391
+ if (is_string($value)) {
392
+ $stdObject->$key = str_replace("\\'", "'", str_replace('\"', '"', str_replace("\\\\", "\\", $value)));
393
+ }
394
+ elseif(is_object($value)) {
395
+ $stdObject->$key = $this->strip_slashes_deep($value);
396
+ }
397
+ elseif(is_array($value)) {
398
+ $stdObject->$key = $this->strip_slashes_deep($value);
399
+ }
400
+ }
401
+
402
+ return $stdObject;
403
+ }
404
+
405
+ function strip_slashes_deep($input)
406
+ {
407
+ $retval = $input;
408
+
409
+ if (is_object($input)) {
410
+ foreach (get_object_vars($input) as $key => $value) {
411
+ $retval->$key = $this->strip_slashes_deep($value);
412
+ }
413
+ }
414
+ elseif(is_array($input)) {
415
+ foreach ($input as $key => $value) {
416
+ $retval[$key] = $this->strip_slashes_deep($value);
417
+ }
418
+ }
419
+ elseif(is_string($input)) {
420
+ $retval = str_replace("\\'", "'", str_replace('\"', '"', str_replace("\\\\", "\\", $input)));
421
+
422
+ }
423
+
424
+ return $retval;
425
+ }
426
+
427
+
428
  /**
429
  * Converts a stdObject entity to a model
430
  * @param stdObject $stdObject
458
  $entity = new stdClass;
459
  foreach ($properties as $k=>$v) $entity->$k = $v;
460
  }
461
+ return $factory->create($this->object->get_model_factory_method(), $entity, $this->object, $context);
462
  }
463
 
464
 
580
  }
581
  }
582
 
583
+ function define_column($name, $type, $default_value=NULL)
584
+ {
585
+ $this->object->_columns[$name] = array(
586
+ 'type' => $type,
587
+ 'default_value' => $default_value
588
+ );
589
+ }
590
+
591
+ function has_defined_column($name)
592
+ {
593
+ $columns = $this->object->_columns;
594
+ return isset($columns[$name]);
595
+ }
596
+
597
+ function cast_columns($entity)
598
+ {
599
+ foreach ($this->object->_columns as $key => $properties) {
600
+ $value = isset($entity->$key) ? $entity->$key : NULL;
601
+ $default_value = $properties['default_value'];
602
+ if ($value && $value != $default_value) {
603
+ $column_type = $this->object->_columns[$key]['type'];
604
+ if (preg_match("/varchar|text/i", $column_type)) {
605
+ if (!is_array($value) && !is_object($value))
606
+ $entity->$key = strval($value);
607
+ }
608
+ else if (preg_match("/decimal|numeric|double/i", $column_type)) {
609
+ $entity->$key = doubleval($value);
610
+ }
611
+ else if (preg_match("/float/i", $column_type)) {
612
+ $entity->$key = floatval($value);
613
+ }
614
+ else if (preg_match("/int/i", $column_type)) {
615
+ $entity->$key = intval($value);
616
+ }
617
+ else if (preg_match("/bool/i", $column_type)) {
618
+ $entity->$key = ($value ? TRUE : FALSE);
619
+ }
620
+ }
621
+
622
+ // Add property and default value
623
+ else {
624
+ $entity->$key = $default_value;
625
+ }
626
+ }
627
+ return $entity;
628
+ }
629
  }
630
 
631
  class C_DataMapper_Driver_Base extends C_Component
632
  {
633
  var $_object_name;
634
  var $_model_factory_method = FALSE;
635
+ var $_columns = array();
636
+ var $_table_columns = array();
637
+ var $_serialized_columns = array();
638
 
639
  function define($object_name, $context=FALSE)
640
  {
641
  parent::define($context);
642
  $this->add_mixin('Mixin_DataMapper_Driver_Base');
643
  $this->implement('I_DataMapper_Driver');
644
+ $this->_object_name = $object_name;
645
  }
646
 
647
+ function initialize()
648
  {
649
  parent::initialize();
650
+
651
+ if ($this->has_method('define_columns')) {
652
+ $this->define_columns();
653
+ }
654
+
655
+ $this->lookup_columns();
656
  }
657
 
658
  /**
675
  return $table_prefix.$this->_object_name;
676
  }
677
 
678
+
679
+ /**
680
+ * Looks up using SQL the columns existing in the database
681
+ */
682
+ function lookup_columns()
683
+ {
684
+ global $wpdb;
685
+ $this->_table_columns = array();
686
+ $sql = "SHOW COLUMNS FROM `{$this->get_table_name()}`";
687
+ foreach ($wpdb->get_results($sql) as $row) {
688
+ $this->_table_columns[] = $row->Field;
689
+ }
690
+ return $this->_table_columns;
691
+ }
692
+
693
+ /**
694
+ * Determines whether a column is present for the table
695
+ * @param string $column_name
696
+ * @return string
697
+ */
698
+ function has_column($column_name)
699
+ {
700
+ if (empty($this->object->_table_columns)) $this->object->lookup_columns();
701
+ return array_search($column_name, $this->object->_table_columns) !== FALSE;
702
+ }
703
+
704
  /**
705
  * Sets the name of the factory method used to create a model for this entity
706
  * @param string $method_name
products/photocrati_nextgen/modules/datamapper/class.datamapper_installer.php CHANGED
@@ -4,7 +4,7 @@ class C_DataMapper_Installer
4
  {
5
  function __construct()
6
  {
7
- $this->settings = C_NextGen_Global_Settings::get_instance();
8
  }
9
 
10
  function install()
4
  {
5
  function __construct()
6
  {
7
+ $this->settings = C_NextGen_Settings::get_instance();
8
  }
9
 
10
  function install()
products/photocrati_nextgen/modules/datamapper/class.datamapper_model.php CHANGED
@@ -8,7 +8,7 @@ class C_DataMapper_Model extends C_Component
8
  /**
9
  * Define the model
10
  */
11
- function define($mapper, $properties, $context=FALSE)
12
  {
13
  parent::define($context);
14
  $this->add_mixin('Mixin_Validation');
@@ -23,7 +23,7 @@ class C_DataMapper_Model extends C_Component
23
  * @param array|stdClass $properties
24
  * @param string $context
25
  */
26
- function initialize($mapper, $properties=FALSE)
27
  {
28
  $this->_mapper = $mapper;
29
  $this->_stdObject = $properties ? (object)$properties : new stdClass();
@@ -97,7 +97,9 @@ class C_DataMapper_Model extends C_Component
97
  */
98
  function set_defaults()
99
  {
100
- $this->get_mapper()->set_defaults($this);
 
 
101
  }
102
 
103
  /**
@@ -105,7 +107,7 @@ class C_DataMapper_Model extends C_Component
105
  */
106
  function destroy()
107
  {
108
- $this->get_mapper()->destroy($this->_stdObject);
109
  }
110
 
111
 
@@ -121,16 +123,14 @@ class C_DataMapper_Model extends C_Component
121
  /**
122
  * Gets/sets the primary key
123
  */
124
- function id()
125
  {
126
  $key = $this->get_mapper()->get_primary_key_column();
127
- $args = func_get_args();
128
- if ($args) {
129
- return $this->__set($key, $args[0]);
130
- }
131
- else {
132
- return $this->__get($key);
133
  }
 
134
  }
135
  }
136
 
8
  /**
9
  * Define the model
10
  */
11
+ function define($mapper=NULL, $properties=array(), $context=FALSE)
12
  {
13
  parent::define($context);
14
  $this->add_mixin('Mixin_Validation');
23
  * @param array|stdClass $properties
24
  * @param string $context
25
  */
26
+ function initialize($mapper=NULL, $properties=FALSE)
27
  {
28
  $this->_mapper = $mapper;
29
  $this->_stdObject = $properties ? (object)$properties : new stdClass();
97
  */
98
  function set_defaults()
99
  {
100
+ $mapper = $this->get_mapper();
101
+ if ($mapper->has_method('set_defaults'))
102
+ $mapper->set_defaults($this);
103
  }
104
 
105
  /**
107
  */
108
  function destroy()
109
  {
110
+ return $this->get_mapper()->destroy($this->_stdObject);
111
  }
112
 
113
 
123
  /**
124
  * Gets/sets the primary key
125
  */
126
+ function id($value=NULL)
127
  {
128
  $key = $this->get_mapper()->get_primary_key_column();
129
+ if ($value) {
130
+ $this->__set($key, $value);
131
+
 
 
 
132
  }
133
+ return $this->__get($key);
134
  }
135
  }
136
 
products/photocrati_nextgen/modules/datamapper/module.datamapper.php CHANGED
@@ -14,7 +14,7 @@ class M_DataMapper extends C_Base_Module
14
  'photocrati-datamapper',
15
  'DataMapper',
16
  'Provides a database abstraction layer following the DataMapper pattern',
17
- '0.1',
18
  'http://www.photocrati.com',
19
  'Photocrati Media',
20
  'http://www.photocrati.com'
@@ -48,14 +48,19 @@ class M_DataMapper extends C_Base_Module
48
  */
49
  function set_custom_wp_query($sql, &$wp_query)
50
  {
51
- // Set the custom query
52
- if (($custom_sql = $wp_query->get('custom_sql'))) {
53
- $sql = $custom_sql;
54
- }
 
 
55
 
56
- // Perhaps we're to initiate a delete query instead?
57
- elseif ($wp_query->get('is_delete')) {
58
- $sql = preg_replace("/^SELECT.*FROM/i", "DELETE FROM", $sql);
 
 
 
59
  }
60
 
61
  return $sql;
@@ -69,8 +74,13 @@ class M_DataMapper extends C_Base_Module
69
  */
70
  function set_custom_wp_query_fields($fields, &$wp_query)
71
  {
72
- $custom_fields = $wp_query->get('fields');
73
- return $custom_fields ? $custom_fields : $fields;
 
 
 
 
 
74
  }
75
 
76
 
@@ -82,8 +92,11 @@ class M_DataMapper extends C_Base_Module
82
  */
83
  function set_custom_wp_query_where($where, &$wp_query)
84
  {
85
- $this->add_post_title_where_clauses($where, $wp_query);
86
- $this->add_post_name_where_clauses($where, $wp_query);
 
 
 
87
  return $where;
88
  }
89
 
@@ -106,6 +119,12 @@ class M_DataMapper extends C_Base_Module
106
  }
107
  $retval = "GROUP BY ".implode(', ', $group_by_columns);
108
  }
 
 
 
 
 
 
109
  return $retval;
110
  }
111
 
@@ -178,7 +197,7 @@ class M_DataMapper extends C_Base_Module
178
  return array(
179
  'A_Datamapper_Factory' => 'adapter.datamapper_factory.php',
180
  'C_Datamapper_Installer' => 'class.datamapper_installer.php',
181
- 'C_Datamapper' => 'class.datamapper.php',
182
  'C_Custompost_Datamapper_Driver' => 'class.custompost_datamapper_driver.php',
183
  'C_Customtable_Datamapper_Driver' => 'class.customtable_datamapper_driver.php',
184
  'C_Datamapper_Driver_Base' => 'class.datamapper_driver_base.php',
14
  'photocrati-datamapper',
15
  'DataMapper',
16
  'Provides a database abstraction layer following the DataMapper pattern',
17
+ '0.6',
18
  'http://www.photocrati.com',
19
  'Photocrati Media',
20
  'http://www.photocrati.com'
48
  */
49
  function set_custom_wp_query($sql, &$wp_query)
50
  {
51
+ if ($wp_query->get('datamapper')) {
52
+
53
+ // Set the custom query
54
+ if (($custom_sql = $wp_query->get('custom_sql'))) {
55
+ $sql = $custom_sql;
56
+ }
57
 
58
+ // Perhaps we're to initiate a delete query instead?
59
+ elseif ($wp_query->get('is_delete')) {
60
+ $sql = preg_replace("/^SELECT.*FROM/i", "DELETE FROM", $sql);
61
+ }
62
+
63
+ if ($wp_query->get('debug')) var_dump($sql);
64
  }
65
 
66
  return $sql;
74
  */
75
  function set_custom_wp_query_fields($fields, &$wp_query)
76
  {
77
+ if ($wp_query->get('datamapper')) {
78
+ if (($custom_fields = $wp_query->get('fields'))) {
79
+ $fields = $custom_fields;
80
+ }
81
+ }
82
+
83
+ return $fields;
84
  }
85
 
86
 
92
  */
93
  function set_custom_wp_query_where($where, &$wp_query)
94
  {
95
+ if ($wp_query->get('datamapper')) {
96
+ $this->add_post_title_where_clauses($where, $wp_query);
97
+ $this->add_post_name_where_clauses($where, $wp_query);
98
+ }
99
+
100
  return $where;
101
  }
102
 
119
  }
120
  $retval = "GROUP BY ".implode(', ', $group_by_columns);
121
  }
122
+ // Not all mysql servers allow access to create temporary tables which are used when doing GROUP BY
123
+ // statements; this can potentially ruin basic queries. If no group_by_columns is set AND the query originates
124
+ // within the datamapper we strip the "GROUP BY" clause entirely in this filter.
125
+ else if ($wp_query->get('datamapper')) {
126
+ $retval = '';
127
+ }
128
  return $retval;
129
  }
130
 
197
  return array(
198
  'A_Datamapper_Factory' => 'adapter.datamapper_factory.php',
199
  'C_Datamapper_Installer' => 'class.datamapper_installer.php',
200
+ 'C_Datamapper' => 'class.datamapper.php',
201
  'C_Custompost_Datamapper_Driver' => 'class.custompost_datamapper_driver.php',
202
  'C_Customtable_Datamapper_Driver' => 'class.customtable_datamapper_driver.php',
203
  'C_Datamapper_Driver_Base' => 'class.datamapper_driver_base.php',
products/photocrati_nextgen/modules/dynamic_stylesheet/class.dynamic_stylesheet_controller.php CHANGED
@@ -17,7 +17,7 @@ class C_Dynamic_Stylesheet_Controller extends C_MVC_Controller
17
  function initialize()
18
  {
19
  parent::initialize();
20
- $this->_app = C_NextGen_Global_Settings::get_instance()->dynamic_stylesheet_slug;
21
  }
22
 
23
  static function &get_instance($context=FALSE)
@@ -75,8 +75,8 @@ class Mixin_Dynamic_Stylesheet_Instance_Methods extends Mixin
75
  $data = $data->get_entity();
76
  $data = $this->object->encode($data);
77
  wp_enqueue_style(
78
- 'dyncss-' . $index . '@dynamic',
79
- $this->object->get_router()->get_url("/{$this->object->_app}", FALSE) . "/{$index}/{$data}"
80
  );
81
  }
82
  }
17
  function initialize()
18
  {
19
  parent::initialize();
20
+ $this->_app = C_NextGen_Settings::get_instance()->dynamic_stylesheet_slug;
21
  }
22
 
23
  static function &get_instance($context=FALSE)
75
  $data = $data->get_entity();
76
  $data = $this->object->encode($data);
77
  wp_enqueue_style(
78
+ 'dyncss-' . $index . $data . '@dynamic',
79
+ $this->object->get_router()->get_url("/{$this->object->_app}", FALSE) . "?index={$index}&data={$data}"
80
  );
81
  }
82
  }
products/photocrati_nextgen/modules/dynamic_stylesheet/class.dynamic_stylesheet_installer.php CHANGED
@@ -4,7 +4,7 @@ class C_Dynamic_Stylesheet_Installer
4
  {
5
  function __construct()
6
  {
7
- $this->settings = C_NextGen_Global_Settings::get_instance();
8
  }
9
 
10
  function install()
4
  {
5
  function __construct()
6
  {
7
+ $this->settings = C_NextGen_Settings::get_instance();
8
  }
9
 
10
  function install()
products/photocrati_nextgen/modules/dynamic_stylesheet/module.dynamic_stylesheet.php CHANGED
@@ -14,7 +14,7 @@ class M_Dynamic_Stylesheet extends C_Base_Module
14
  'photocrati-dynamic_stylesheet',
15
  'Dynamic Stylesheet',
16
  'Provides the ability to generate and enqueue a dynamic stylesheet',
17
- '0.2',
18
  'http://www.nextgen-gallery.com',
19
  'Photocrati Media',
20
  'http://www.photocrati.com',
14
  'photocrati-dynamic_stylesheet',
15
  'Dynamic Stylesheet',
16
  'Provides the ability to generate and enqueue a dynamic stylesheet',
17
+ '0.3',
18
  'http://www.nextgen-gallery.com',
19
  'Photocrati Media',
20
  'http://www.photocrati.com',
products/photocrati_nextgen/modules/dynamic_thumbnails/adapter.dynamic_thumbnails_storage_driver.php CHANGED
@@ -22,11 +22,13 @@ class A_Dynamic_Thumbnails_Storage_Driver extends Mixin
22
  $params = $dynthumbs->get_params_from_name($size, true);
23
  $image_filename = $dynthumbs->get_image_name($image, $params);
24
 
25
- $image_path = path_join($folder_path, $image_filename);
 
 
26
 
27
  if ($check_existance)
28
  {
29
- if (file_exists($image_path))
30
  {
31
  $retval = $image_path;
32
  }
@@ -45,23 +47,30 @@ class A_Dynamic_Thumbnails_Storage_Driver extends Mixin
45
  return $retval;
46
  }
47
 
48
- function get_image_url($image, $size='full')
49
  {
50
  $retval = NULL;
51
  $dynthumbs = $this->object->get_registry()->get_utility('I_Dynamic_Thumbnails_Manager');
52
 
53
  if ($dynthumbs && $dynthumbs->is_size_dynamic($size)) {
54
-
55
  $abspath = $this->object->get_image_abspath($image, $size, true);
56
 
57
- if ($abspath == null) {
 
58
  $params = $dynthumbs->get_params_from_name($size, true);
59
  $retval = $dynthumbs->get_image_url($image, $params);
60
  }
61
  }
62
 
63
  if ($retval == null) {
64
- $retval = $this->call_parent('get_image_url', $image, $size);
 
 
 
 
 
 
 
65
  }
66
 
67
  return $retval;
22
  $params = $dynthumbs->get_params_from_name($size, true);
23
  $image_filename = $dynthumbs->get_image_name($image, $params);
24
 
25
+ $image_path = implode(DIRECTORY_SEPARATOR, array(
26
+ rtrim($folder_path, "\\/"), $image_filename
27
+ ));
28
 
29
  if ($check_existance)
30
  {
31
+ if (@file_exists($image_path))
32
  {
33
  $retval = $image_path;
34
  }
47
  return $retval;
48
  }
49
 
50
+ function get_image_url($image, $size='full', $check_existance=FALSE)
51
  {
52
  $retval = NULL;
53
  $dynthumbs = $this->object->get_registry()->get_utility('I_Dynamic_Thumbnails_Manager');
54
 
55
  if ($dynthumbs && $dynthumbs->is_size_dynamic($size)) {
 
56
  $abspath = $this->object->get_image_abspath($image, $size, true);
57
 
58
+ // If abspath is NULL, then we assume we're dealing with a dynamic image
59
+ if ($abspath == null) {
60
  $params = $dynthumbs->get_params_from_name($size, true);
61
  $retval = $dynthumbs->get_image_url($image, $params);
62
  }
63
  }
64
 
65
  if ($retval == null) {
66
+ $retval = $this->call_parent('get_image_url', $image, $size, $check_existance);
67
+ }
68
+
69
+ // Try generating the thumbnail
70
+ if ($retval == null) {
71
+ $params = array('watermark' => false, 'reflection' => false, 'crop' => true);
72
+ $result = $this->generate_thumbnail($image, $params);
73
+ if ($result) $retval = $this->call_parent('get_image_url', $image, $size, $check_existance);
74
  }
75
 
76
  return $retval;
products/photocrati_nextgen/modules/dynamic_thumbnails/class.dynamic_thumbnails_installer.php CHANGED
@@ -4,7 +4,7 @@ class C_Dynamic_Thumbnails_Installer
4
  {
5
  function __construct()
6
  {
7
- $this->settings = C_NextGen_Global_Settings::get_instance();
8
  }
9
 
10
  function install()
4
  {
5
  function __construct()
6
  {
7
+ $this->settings = C_NextGen_Settings::get_instance();
8
  }
9
 
10
  function install()
products/photocrati_nextgen/modules/dynamic_thumbnails/class.dynamic_thumbnails_manager.php CHANGED
@@ -4,7 +4,7 @@ class Mixin_Dynamic_Thumbnails_Manager extends Mixin
4
  {
5
  function get_route_name()
6
  {
7
- return C_NextGen_Global_Settings::get_instance()->get('dynamic_thumbnail_slug');
8
  }
9
 
10
  function _get_params_sanitized($params)
4
  {
5
  function get_route_name()
6
  {
7
+ return C_NextGen_Settings::get_instance()->get('dynamic_thumbnail_slug');
8
  }
9
 
10
  function _get_params_sanitized($params)
products/photocrati_nextgen/modules/dynamic_thumbnails/module.dynamic_thumbnails.php CHANGED
@@ -13,7 +13,7 @@ class M_Dynamic_Thumbnails extends C_Base_Module
13
  'photocrati-dynamic_thumbnails',
14
  'Dynamic Thumbnails',
15
  'Adds support for dynamic thumbnails',
16
- '0.1',
17
  'http://www.nextgen-gallery.com',
18
  'Photocrati Media',
19
  'http://www.photocrati.com'
13
  'photocrati-dynamic_thumbnails',
14
  'Dynamic Thumbnails',
15
  'Adds support for dynamic thumbnails',
16
+ '0.5',
17
  'http://www.nextgen-gallery.com',
18
  'Photocrati Media',
19
  'http://www.photocrati.com'
products/photocrati_nextgen/modules/frame_communication/class.frame_communication_installer.php CHANGED
@@ -4,7 +4,7 @@ class C_Frame_Communication_Installer
4
  {
5
  function __construct()
6
  {
7
- $this->settings = C_NextGen_Global_Settings::get_instance();
8
  }
9
 
10
  function install()
4
  {
5
  function __construct()
6
  {
7
+ $this->settings = C_NextGen_Settings::get_instance();
8
  }
9
 
10
  function install()
products/photocrati_nextgen/modules/frame_communication/class.frame_event_publisher.php CHANGED
@@ -15,7 +15,7 @@ class C_Frame_Event_Publisher extends C_Component
15
  function initialize()
16
  {
17
  parent::initialize();
18
- $this->setting_name = C_NextGen_Global_Settings::get_instance()->frame_communication_option_name;
19
  }
20
 
21
  /**
@@ -64,7 +64,15 @@ class Mixin_Frame_Event_Publisher extends Mixin
64
  {
65
  $id = md5(serialize($data));
66
  $data['context'] = $this->object->context;
67
- setrawcookie($this->object->setting_name.'_'.$id,$this->object->_encode($data));
 
 
 
 
 
 
 
 
68
 
69
  return $data;
70
  }
15
  function initialize()
16
  {
17
  parent::initialize();
18
+ $this->setting_name = C_NextGen_Settings::get_instance()->frame_communication_option_name;
19
  }
20
 
21
  /**
64
  {
65
  $id = md5(serialize($data));
66
  $data['context'] = $this->object->context;
67
+
68
+ $write_cookie = TRUE;
69
+ if (defined('XMLRPC_REQUEST')) {
70
+ $write_cookie = XMLRPC_REQUEST == FALSE;
71
+ }
72
+
73
+ if ($write_cookie) {
74
+ setrawcookie($this->object->setting_name.'_'.$id,$this->object->_encode($data));
75
+ }
76
 
77
  return $data;
78
  }
products/photocrati_nextgen/modules/frame_communication/module.frame_communication.php CHANGED
@@ -15,7 +15,7 @@ class M_Frame_Communication extends C_Base_Module
15
  'photocrati-frame_communication',
16
  'Frame/iFrame Inter-Communication',
17
  'Provides a means for HTML frames to share server-side events with each other',
18
- '0.1',
19
  'http://www.nextgen-gallery.com',
20
  'Photocrati Media',
21
  'http://www.photocrati.com',
@@ -35,7 +35,7 @@ class M_Frame_Communication extends C_Base_Module
35
 
36
  function _register_hooks()
37
  {
38
- add_action('admin_enqueue_scripts', array(&$this, 'enqueue_admin_scripts'));
39
 
40
  }
41
 
@@ -48,7 +48,9 @@ class M_Frame_Communication extends C_Base_Module
48
  $router->get_static_url('photocrati-frame_communication#frame_event_publisher.js'),
49
  array('jquery')
50
  );
51
- wp_enqueue_script('frame_event_publisher');
 
 
52
  }
53
 
54
  function get_type_list()
15
  'photocrati-frame_communication',
16
  'Frame/iFrame Inter-Communication',
17
  'Provides a means for HTML frames to share server-side events with each other',
18
+ '0.3',
19
  'http://www.nextgen-gallery.com',
20
  'Photocrati Media',
21
  'http://www.photocrati.com',
35
 
36
  function _register_hooks()
37
  {
38
+ add_action('init', array($this, 'enqueue_admin_scripts'));
39
 
40
  }
41
 
48
  $router->get_static_url('photocrati-frame_communication#frame_event_publisher.js'),
49
  array('jquery')
50
  );
51
+
52
+ if (is_admin())
53
+ wp_enqueue_script('frame_event_publisher');
54
  }
55
 
56
  function get_type_list()
products/photocrati_nextgen/modules/fs/class.fs.php CHANGED
@@ -33,7 +33,7 @@ class C_Fs extends C_Component
33
  function initialize()
34
  {
35
  parent::initialize();
36
- $this->_document_root = $this->set_document_root($_SERVER['DOCUMENT_ROOT']);
37
  }
38
  }
39
 
@@ -42,8 +42,7 @@ class Mixin_Fs_Instance_Methods extends Mixin
42
 
43
  function add_trailing_slash($path)
44
  {
45
- if (substr($path, -1) != '/') $path .= '/';
46
- return $path;
47
  }
48
 
49
 
@@ -107,8 +106,7 @@ class Mixin_Fs_Instance_Methods extends Mixin
107
  */
108
  function remove_path_segment($path, $segment)
109
  {
110
- if (substr($segment, -1) == '/') $segment = substr($segment, 0, -1);
111
- $parts = explode($segment, $path);
112
  return $this->join_paths($parts);
113
  }
114
 
@@ -129,7 +127,7 @@ class Mixin_Fs_Instance_Methods extends Mixin
129
  if (!$module)
130
  list($path, $module) = $this->object->parse_formatted_path($path);
131
 
132
- if (file_exists($path))
133
  {
134
  $retval = $path;
135
  }
@@ -141,7 +139,7 @@ class Mixin_Fs_Instance_Methods extends Mixin
141
 
142
  // See if the file is located under one of the search paths directly
143
  foreach ($search_paths as $dir) {
144
- if (file_exists($this->join_paths($dir, $path))) {
145
  $retval = $this->join_paths($dir, $path);
146
  break;
147
  }
@@ -218,7 +216,7 @@ class Mixin_Fs_Instance_Methods extends Mixin
218
  {
219
  $retval = NULL;
220
 
221
- $results = file_exists($this->join_paths($base_path, $file));
222
 
223
  // Must be located in a sub-directory
224
  if (!$results)
@@ -272,23 +270,42 @@ class Mixin_Fs_Instance_Methods extends Mixin
272
  {
273
  $segments = array();
274
  $retval = array();
 
275
  $params = func_get_args();
276
  $this->_flatten_array($params, $segments);
277
 
278
  foreach ($segments as $segment) {
279
- $segment = trim($segment, '/\\');
280
- if (!empty($segment))
281
- $retval = array_unique(array_merge($retval, preg_split('/[\/\\\]/', $segment)));
282
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
- $retval = implode('/', $retval);
285
 
286
- if ('WINNT' !== PHP_OS
287
- && strpos($retval, '/') !== 0
288
- && !preg_match("#^http(s)?://#", $retval) && !file_exists($retval))
289
- $retval = '/' . $retval;
 
290
 
291
- return $retval;
292
  }
293
 
294
  function _flatten_array($obj, &$arr)
@@ -331,7 +348,6 @@ class Mixin_Fs_Instance_Methods extends Mixin
331
  */
332
  function set_document_root($value)
333
  {
334
- // Even for windows hosts we force '/' as the path separator
335
- return $this->_document_root = untrailingslashit(str_replace('\\', '/', $value));
336
  }
337
  }
33
  function initialize()
34
  {
35
  parent::initialize();
36
+ $this->_document_root = $this->set_document_root(ABSPATH);
37
  }
38
  }
39
 
42
 
43
  function add_trailing_slash($path)
44
  {
45
+ return rtrim($path, "/\\").DIRECTORY_SEPARATOR;
 
46
  }
47
 
48
 
106
  */
107
  function remove_path_segment($path, $segment)
108
  {
109
+ $parts = explode($segment, rtrim($path, "/\\"));
 
110
  return $this->join_paths($parts);
111
  }
112
 
127
  if (!$module)
128
  list($path, $module) = $this->object->parse_formatted_path($path);
129
 
130
+ if (@file_exists($path))
131
  {
132
  $retval = $path;
133
  }
139
 
140
  // See if the file is located under one of the search paths directly
141
  foreach ($search_paths as $dir) {
142
+ if (@file_exists($this->join_paths($dir, $path))) {
143
  $retval = $this->join_paths($dir, $path);
144
  break;
145
  }
216
  {
217
  $retval = NULL;
218
 
219
+ $results = @file_exists($this->join_paths($base_path, $file));
220
 
221
  // Must be located in a sub-directory
222
  if (!$results)
270
  {
271
  $segments = array();
272
  $retval = array();
273
+ $protocol = NULL;
274
  $params = func_get_args();
275
  $this->_flatten_array($params, $segments);
276
 
277
  foreach ($segments as $segment) {
278
+ $segment = trim($segment, "/\\");
279
+ $pieces = array_values(preg_split('#[/\\\\]#', $segment));
280
+
281
+ // determine if each piece should be appended to $retval
282
+ foreach ($pieces as $ndx => $val) {
283
+ if ($val === '') continue;
284
+ $one = array_search($val, $retval);
285
+ $two = array_search($val, $pieces);
286
+ $one = (FALSE === $one ? 0 : count($one) + 1);
287
+ $two = (FALSE === $two ? 0 : count($two) + 1);
288
+ if (!empty($protocol)) {
289
+ $existing_val = isset($retval[$ndx]) ? $retval[$ndx] : NULL;
290
+ if ($existing_val !== $val || $two >= $one)
291
+ $retval[] = $val;
292
+ }
293
+ else {
294
+ $existing_val = isset($retval[$ndx]) ? $retval[$ndx] : NULL;
295
+ if ($existing_val !== $val && $two >= $one)
296
+ $retval[] = $val;
297
+ }
298
+ }
299
 
300
+ }
301
 
302
+ // Join the paths together
303
+ $retval = implode(DIRECTORY_SEPARATOR, $retval);
304
+ if (strpos($retval, $this->get_document_root()) !== 0) {
305
+ $retval = DIRECTORY_SEPARATOR . trim($retval, "/\\");
306
+ }
307
 
308
+ return $retval;
309
  }
310
 
311
  function _flatten_array($obj, &$arr)
348
  */
349
  function set_document_root($value)
350
  {
351
+ return ($this->_document_root = rtrim($value, "/\\"));
 
352
  }
353
  }
products/photocrati_nextgen/modules/fs/module.fs.php CHANGED
@@ -12,7 +12,7 @@ class M_Fs extends C_Base_Module
12
  'photocrati-fs',
13
  'Filesystem',
14
  'Provides a filesystem abstraction layer for Pope modules',
15
- '0.1',
16
  'http://www.photocrati.com',
17
  'Photocrati Media',
18
  'http://www.photocrati.com'
12
  'photocrati-fs',
13
  'Filesystem',
14
  'Provides a filesystem abstraction layer for Pope modules',
15
+ '0.4',
16
  'http://www.photocrati.com',
17
  'Photocrati Media',
18
  'http://www.photocrati.com'
products/photocrati_nextgen/modules/lightbox/adapter.lightbox_factory.php CHANGED
@@ -2,13 +2,13 @@
2
 
3
  class A_Lightbox_Factory extends Mixin
4
  {
5
- function lightbox_library($mapper=FALSE, $properties=array(), $context=FALSE)
6
  {
7
- return new C_Lightbox_Library($mapper, $properties, $context);
8
  }
9
 
10
- function lightbox($mapper=FALSE, $properties=array(), $context=FALSE)
11
  {
12
- return $this->object->lightbox_library($mapper, $properties, $context);
13
  }
14
  }
2
 
3
  class A_Lightbox_Factory extends Mixin
4
  {
5
+ function lightbox_library($properties=array(), $mapper=FALSE, $context=FALSE)
6
  {
7
+ return new C_Lightbox_Library($properties, $mapper, $context);
8
  }
9
 
10
+ function lightbox($properties=array(), $mapper=FALSE, $context=FALSE)
11
  {
12
+ return $this->object->lightbox_library($properties, $mapper, $context);
13
  }
14
  }
products/photocrati_nextgen/modules/lightbox/adapter.lightbox_library_form.php CHANGED
@@ -17,7 +17,7 @@ class A_Lightbox_Library_Form extends Mixin
17
  {
18
  return array(
19
  'lightbox_library_code',
20
- 'lightbox_library_css_stylesheets',
21
  'lightbox_library_scripts'
22
  );
23
  }
@@ -40,13 +40,13 @@ class A_Lightbox_Library_Form extends Mixin
40
  * @param $lightbox
41
  * @return mixed
42
  */
43
- function _render_lightbox_library_css_stylesheets_field($lightbox)
44
  {
45
  return $this->_render_textarea_field(
46
  $lightbox,
47
- 'css_stylesheets',
48
  'Stylesheet URL',
49
- $lightbox->css_stylesheets
50
  );
51
  }
52
 
17
  {
18
  return array(
19
  'lightbox_library_code',
20
+ 'lightbox_library_styles',
21
  'lightbox_library_scripts'
22
  );
23
  }
40
  * @param $lightbox
41
  * @return mixed
42
  */
43
+ function _render_lightbox_library_styles_field($lightbox)
44
  {
45
  return $this->_render_textarea_field(
46
  $lightbox,
47
+ 'styles',
48
  'Stylesheet URL',
49
+ $lightbox->styles
50
  );
51
  }
52
 
products/photocrati_nextgen/modules/lightbox/class.lightbox_installer.php CHANGED
@@ -2,166 +2,185 @@
2
 
3
  class C_Lightbox_Installer
4
  {
5
- function __construct()
6
- {
7
- $this->registry = C_Component_Registry::get_instance();
8
- $this->router = $this->registry->get_utility('I_Router');
9
- $this->mapper = $this->registry->get_utility('I_Lightbox_Library_Mapper');
10
- }
11
-
12
-
13
- function set_attr(&$obj, $key, $val)
14
- {
15
- if (!isset($obj->$key))
16
- $obj->$key = $val;
17
- }
18
-
19
- /**
20
- * Installs a lightbox library
21
- * @param string $name
22
- * @param string $code
23
- * @param array $stylesheet_paths
24
- * @param array $script_paths
25
- * @param array $values
26
- */
27
- function install_lightbox($name, $title, $code, $stylesheet_paths=array(), $script_paths=array(), $values=array())
28
- {
29
- // Try to find the existing lightbox. If we can't find it, we'll create
30
- $lightbox = $this->mapper->find_by_name($name);
31
- if (!$lightbox)
32
- $lightbox = new stdClass;
33
-
34
- $styles = array();
35
- foreach ($stylesheet_paths as $stylesheet) {
36
- if (preg_match("/http(s)?/", $stylesheet))
37
- $styles[] = $stylesheet;
38
- else
39
- $styles[] = $this->router->get_static_url($stylesheet);
40
- }
41
-
42
- $scripts = array();
43
- foreach ($script_paths as $script) {
44
- if (preg_match("/http(s)?/", $script))
45
- $scripts[] = $script;
46
- else
47
- $scripts[] = $this->router->get_static_url($script);
48
- }
49
-
50
- // Set properties
51
- $lightbox->name = $name;
52
  $this->set_attr($lightbox, 'title', $title);
53
- $this->set_attr($lightbox, 'code', $code);
54
- $this->set_attr($lightbox, 'values', $values);
55
- $this->set_attr($lightbox, 'css_stylesheets', implode("\n", $styles));
56
- $this->set_attr($lightbox, 'scripts', implode("\n", $scripts));
57
-
58
- // Save the lightbox
59
- $this->mapper->save($lightbox);
60
- }
61
-
62
- /**
63
- * Uninstalls an existing lightbox
64
- * @param string $name
65
- */
66
- function uninstall_lightbox($name)
67
- {
68
- if (($lightbox = $this->mapper->find_by_name($name))) {
69
- $this->mapper->destroy($lightbox);
70
- }
71
- }
72
-
73
- /**
74
- * Installs all of the lightbox provided by this module
75
- */
76
- function install()
77
- {
78
- $this->install_lightbox(
79
- 'lightbox',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  'Lightbox',
81
- "class='ngg_lightbox'",
82
- array('photocrati-lightbox#jquery.lightbox/jquery.lightbox-0.5.css'),
83
- array(
84
- 'photocrati-lightbox#jquery.lightbox/jquery.lightbox-0.5.min.js',
85
- 'photocrati-lightbox#jquery.lightbox/nextgen_lightbox_init.js'
86
- ),
87
- array(
88
- 'nextgen_lightbox_loading_img_url' =>
89
- $this->router->get_static_url('photocrati-lightbox#jquery.lightbox/lightbox-ico-loading.gif'),
90
-
91
- 'nextgen_lightbox_close_btn_url' =>
92
- $this->router->get_static_url('photocrati-lightbox#jquery.lightbox/lightbox-btn-close.gif'),
93
-
94
- 'nextgen_lightbox_btn_prev_url' =>
95
- $this->router->get_static_url('photocrati-lightbox#jquery.lightbox/lightbox-btn-prev.gif'),
96
-
97
- 'nextgen_lightbox_btn_next_url' =>
98
- $this->router->get_static_url('photocrati-lightbox#jquery.lightbox/lightbox-btn-next.gif'),
99
-
100
- 'nextgen_lightbox_blank_img_url' =>
101
- $this->router->get_static_url('photocrati-lightbox#jquery.lightbox/lightbox-blank.gif')
102
- )
103
- );
104
-
105
- // Install Fancybox 1.3.4
106
- $this->install_lightbox(
107
- 'fancybox',
108
  'Fancybox',
109
- 'class="ngg-fancybox" rel="%GALLERY_NAME%"',
110
- array('photocrati-lightbox#fancybox/jquery.fancybox-1.3.4.css'),
111
- array(
112
- 'photocrati-lightbox#fancybox/jquery.easing-1.3.pack.js',
113
- 'photocrati-lightbox#fancybox/jquery.fancybox-1.3.4.pack.js',
114
- 'photocrati-lightbox#fancybox/nextgen_fancybox_init.js'
115
- )
116
- );
117
-
118
- // Install highslide
119
- $this->install_lightbox(
120
- 'highslide',
121
  'Highslide',
122
- 'class="highslide" onclick="return hs.expand(this, galleryOptions);"',
123
- array('photocrati-lightbox#highslide/highslide.css'),
124
- array('photocrati-lightbox#highslide/highslide-full.packed.js', 'photocrati-lightbox#highslide/nextgen_highslide_init.js'),
125
- array('nextgen_highslide_graphics_dir' => $this->router->get_static_url('photocrati-lightbox#highslide/graphics'))
126
- );
127
-
128
- // Install Shutter
129
- $this->install_lightbox(
130
- 'shutter',
 
131
  'Shutter',
132
- 'class="shutterset_%GALLERY_NAME%"',
133
- array('photocrati-lightbox#shutter/shutter.css'),
134
- array('photocrati-lightbox#shutter/shutter.js', 'photocrati-lightbox#shutter/nextgen_shutter.js'),
135
- array(
136
- 'msgLoading' => 'L O A D I N G',
137
- 'msgClose' => 'Click to Close',
138
- )
139
- );
140
-
141
- // Install Shutter Reloaded
142
- $this->install_lightbox(
143
- 'shutter2',
 
144
  'Shutter 2',
145
- 'class="shutterset_%GALLERY_NAME%"',
146
- array('photocrati-lightbox#shutter_reloaded/shutter.css'),
147
- array('photocrati-lightbox#shutter_reloaded/shutter.js', 'photocrati-lightbox#shutter_reloaded/nextgen_shutter_reloaded.js')
148
- );
149
-
150
- // Install Thickbox
151
- $this->install_lightbox(
152
- 'thickbox',
 
153
  'Thickbox',
154
- "class='thickbox' rel='%GALLERY_NAME%'",
155
- array(includes_url('/js/thickbox/thickbox.css')),
156
- array('photocrati-lightbox#thickbox/nextgen_thickbox_init.js', includes_url('/js/thickbox/thickbox.js'))
157
- );
158
- }
159
-
160
- /**
161
- * Uninstalls all lightboxes
162
- */
163
- function uninstall($hard = FALSE)
164
- {
165
- if ($hard) $this->mapper->delete()->run_query();
166
- }
167
- }
 
2
 
3
  class C_Lightbox_Installer
4
  {
5
+ function __construct()
6
+ {
7
+ $this->registry = C_Component_Registry::get_instance();
8
+ $this->router = $this->registry->get_utility('I_Router');
9
+ $this->mapper = $this->registry->get_utility('I_Lightbox_Library_Mapper');
10
+ }
11
+
12
+
13
+ function set_attr(&$obj, $key, $val)
14
+ {
15
+ if (!isset($obj->$key))
16
+ $obj->$key = $val;
17
+ }
18
+
19
+ /**
20
+ * Installs a lightbox library
21
+ * @param string $name
22
+ * @param string $code
23
+ * @param array $stylesheet_paths
24
+ * @param array $script_paths
25
+ * @param array $values
26
+ */
27
+ function install_lightbox($name, $title, $code, $stylesheet_paths=array(), $script_paths=array(), $values=array())
28
+ {
29
+ // Try to find the existing lightbox. If we can't find it, we'll create
30
+ $lightbox = $this->mapper->find_by_name($name);
31
+ if (!$lightbox)
32
+ $lightbox = new stdClass;
33
+
34
+ // Set properties
35
+ $lightbox->name = $name;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  $this->set_attr($lightbox, 'title', $title);
37
+ $this->set_attr($lightbox, 'code', $code);
38
+ $this->set_attr($lightbox, 'values', $values);
39
+ $this->set_attr($lightbox, 'styles', implode("\n", $stylesheet_paths));
40
+ $this->set_attr($lightbox, 'scripts', implode("\n", $script_paths));
41
+
42
+ // Save the lightbox
43
+ $this->mapper->save($lightbox);
44
+ }
45
+
46
+ /**
47
+ * Uninstalls an existing lightbox
48
+ * @param string $name
49
+ */
50
+ function uninstall_lightbox($name)
51
+ {
52
+ if (($lightbox = $this->mapper->find_by_name($name))) {
53
+ $this->mapper->destroy($lightbox);
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Given a newline separated list this turns absolute URL relative *if* they match includes_url()
59
+ *
60
+ * @param string $urls
61
+ * @return string $urls
62
+ */
63
+ function _convert_urls($urls)
64
+ {
65
+ $urls = explode("\n", $urls);
66
+ $site_url = site_url();
67
+ foreach ($urls as &$url) {
68
+ if (0 === strpos($url, includes_url()))
69
+ {
70
+ $count = 1;
71
+ $url = str_replace($site_url, '', $url, $count);
72
+ }
73
+ }
74
+
75
+ return implode("\n", $urls);
76
+ }
77
+
78
+ /**
79
+ * Installs all of the lightbox provided by this module
80
+ */
81
+ function install()
82
+ {
83
+ // scan existing libraries and replace absolute HTTP paths with relative paths
84
+ foreach ($this->mapper->find_all(TRUE) as $lightbox) {
85
+ if (!empty($lightbox->css_stylesheets))
86
+ {
87
+ $lightbox->styles = $this->_convert_urls($lightbox->css_stylesheets);
88
+ $lightbox->scripts = $this->_convert_urls($lightbox->scripts);
89
+ }
90
+ $lightbox->save();
91
+ }
92
+
93
+ // Install "None" option
94
+ $this->install_lightbox(
95
+ 'none',
96
+ 'No lightbox',
97
+ '',
98
+ array(),
99
+ array()
100
+ );
101
+
102
+ $this->install_lightbox(
103
+ 'lightbox',
104
  'Lightbox',
105
+ "class='ngg_lightbox'",
106
+ array('photocrati-lightbox#jquery.lightbox/jquery.lightbox-0.5.css'),
107
+ array(
108
+ 'photocrati-lightbox#jquery.lightbox/jquery.lightbox-0.5.min.js',
109
+ 'photocrati-lightbox#jquery.lightbox/nextgen_lightbox_init.js'
110
+ ),
111
+ array(
112
+ 'nextgen_lightbox_loading_img_url' => 'photocrati-lightbox#jquery.lightbox/lightbox-ico-loading.gif',
113
+ 'nextgen_lightbox_close_btn_url' => 'photocrati-lightbox#jquery.lightbox/lightbox-btn-close.gif',
114
+ 'nextgen_lightbox_btn_prev_url' => 'photocrati-lightbox#jquery.lightbox/lightbox-btn-prev.gif',
115
+ 'nextgen_lightbox_btn_next_url' => 'photocrati-lightbox#jquery.lightbox/lightbox-btn-next.gif',
116
+ 'nextgen_lightbox_blank_img_url' => 'photocrati-lightbox#jquery.lightbox/lightbox-blank.gif'
117
+ )
118
+ );
119
+
120
+ // Install Fancybox 1.3.4
121
+ $this->install_lightbox(
122
+ 'fancybox',
 
 
 
 
 
 
 
 
 
123
  'Fancybox',
124
+ 'class="ngg-fancybox" rel="%GALLERY_NAME%"',
125
+ array('photocrati-lightbox#fancybox/jquery.fancybox-1.3.4.css'),
126
+ array(
127
+ 'photocrati-lightbox#fancybox/jquery.easing-1.3.pack.js',
128
+ 'photocrati-lightbox#fancybox/jquery.fancybox-1.3.4.pack.js',
129
+ 'photocrati-lightbox#fancybox/nextgen_fancybox_init.js'
130
+ )
131
+ );
132
+
133
+ // Install highslide
134
+ $this->install_lightbox(
135
+ 'highslide',
136
  'Highslide',
137
+ 'class="highslide" onclick="return hs.expand(this, {slideshowGroup: ' . "'%GALLERY_NAME%'" . '});"',
138
+ array('photocrati-lightbox#highslide/highslide.css'),
139
+ array('photocrati-lightbox#highslide/highslide-full.packed.js',
140
+ 'photocrati-lightbox#highslide/nextgen_highslide_init.js'),
141
+ array('nextgen_highslide_graphics_dir' => 'photocrati-lightbox#highslide/graphics')
142
+ );
143
+
144
+ // Install Shutter
145
+ $this->install_lightbox(
146
+ 'shutter',
147
  'Shutter',
148
+ 'class="shutterset_%GALLERY_NAME%"',
149
+ array('photocrati-lightbox#shutter/shutter.css'),
150
+ array('photocrati-lightbox#shutter/shutter.js',
151
+ 'photocrati-lightbox#shutter/nextgen_shutter.js'),
152
+ array(
153
+ 'msgLoading' => 'L O A D I N G',
154
+ 'msgClose' => 'Click to Close',
155
+ )
156
+ );
157
+
158
+ // Install Shutter Reloaded
159
+ $this->install_lightbox(
160
+ 'shutter2',
161
  'Shutter 2',
162
+ 'class="shutterset_%GALLERY_NAME%"',
163
+ array('photocrati-lightbox#shutter_reloaded/shutter.css'),
164
+ array('photocrati-lightbox#shutter_reloaded/shutter.js',
165
+ 'photocrati-lightbox#shutter_reloaded/nextgen_shutter_reloaded.js')
166
+ );
167
+
168
+ // Install Thickbox
169
+ $this->install_lightbox(
170
+ 'thickbox',
171
  'Thickbox',
172
+ "class='thickbox' rel='%GALLERY_NAME%'",
173
+ array('wordpress#thickbox'),
174
+ array('photocrati-lightbox#thickbox/nextgen_thickbox_init.js',
175
+ 'wordpress#thickbox')
176
+ );
177
+ }
178
+
179
+ /**
180
+ * Uninstalls all lightboxes
181
+ */
182
+ function uninstall($hard = FALSE)
183
+ {
184
+ $this->mapper->delete()->run_query();
185
+ }
186
+ }
products/photocrati_nextgen/modules/lightbox/class.lightbox_library.php CHANGED
@@ -11,12 +11,23 @@
11
  */
12
  class C_Lightbox_Library extends C_DataMapper_Model
13
  {
14
- function define($mapper, $properties, $context=FALSE)
15
  {
16
  parent::define($mapper, $properties, $context);
17
  $this->add_mixin('Mixin_Lightbox_Library_Validation');
18
  $this->implement('I_Lightbox_Library');
19
  }
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
  class Mixin_Lightbox_Library_Validation extends Mixin
11
  */
12
  class C_Lightbox_Library extends C_DataMapper_Model
13
  {
14
+ function define($properties=array(), $mapper=FALSE, $context=FALSE)
15
  {
16
  parent::define($mapper, $properties, $context);
17
  $this->add_mixin('Mixin_Lightbox_Library_Validation');
18
  $this->implement('I_Lightbox_Library');
19
  }
20
+
21
+ function initialize($properties=array(), $mapper=FALSE, $context=FALSE)
22
+ {
23
+ // Get the mapper is not specified
24
+ if (!$mapper) {
25
+ $mapper = $this->get_registry()->get_utility($this->_mapper_interface);
26
+ }
27
+
28
+ // Initialize
29
+ parent::initialize($mapper, $properties);
30
+ }
31
  }
32
 
33
  class Mixin_Lightbox_Library_Validation extends Mixin
products/photocrati_nextgen/modules/lightbox/class.lightbox_library_mapper.php CHANGED
@@ -76,7 +76,7 @@ class Mixin_Lightbox_Library_Mapper
76
  */
77
  function set_defaults($entity)
78
  {
79
- $this->object->_set_default_value($entity, 'css_stylesheets', '');
80
  $this->object->_set_default_value($entity, 'scripts', '');
81
  $this->object->_set_default_value($entity, 'display_settings', array());
82
  }
76
  */
77
  function set_defaults($entity)
78
  {
79
+ $this->object->_set_default_value($entity, 'styles', '');
80
  $this->object->_set_default_value($entity, 'scripts', '');
81
  $this->object->_set_default_value($entity, 'display_settings', array());
82
  }
products/photocrati_nextgen/modules/lightbox/module.lightbox.php CHANGED
@@ -7,18 +7,20 @@
7
  }
8
  ***/
9
 
10
- define('NEXTGEN_LIGHTBOX_OPTIONS_SLUG', 'ngg_lightbox_options');
11
- define('NEXTGEN_LIGHTBOX_ADVANCED_OPTIONS_SLUG', 'ngg_lightbox_advanced_options');
12
 
13
  class M_Lightbox extends C_Base_Module
14
  {
 
 
15
  function define()
16
  {
17
  parent::define(
18
  'photocrati-lightbox',
19
  'Lightbox',
20
- _("Provides integration with JQuery's lightbox plugin"),
21
- '0.1',
22
  'http://leandrovieira.com/projects/jquery/lightbox/',
23
  'Photocrati Media',
24
  'http://www.photocrati.com'
@@ -31,14 +33,19 @@ class M_Lightbox extends C_Base_Module
31
  function initialize()
32
  {
33
  parent::initialize();
 
 
 
 
34
 
35
- // Add a configuration form to each library
 
 
 
 
36
  foreach ($this->get_registry()->get_utility('I_Lightbox_Library_Mapper')->find_all() as $lib) {
37
- $this->get_registry()
38
- ->add_adapter('I_Form', 'A_Lightbox_Library_Form', $lib->name);
39
- $this->get_registry()
40
- ->get_utility('I_Form_Manager')
41
- ->add_form(NEXTGEN_LIGHTBOX_ADVANCED_OPTIONS_SLUG, $lib->name);
42
  }
43
  }
44
 
@@ -59,6 +66,228 @@ class M_Lightbox extends C_Base_Module
59
  // Provides an installer for lightbox libraries
60
  $this->get_registry()->add_adapter('I_Installer', 'A_Lightbox_Installer');
61
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  function get_type_list()
64
  {
7
  }
8
  ***/
9
 
10
+ define('NGG_LIGHTBOX_OPTIONS_SLUG', 'ngg_lightbox_options');
11
+ define('NGG_LIGHTBOX_ADVANCED_OPTIONS_SLUG', 'ngg_lightbox_advanced_options');
12
 
13
  class M_Lightbox extends C_Base_Module
14
  {
15
+ static $_registered_lightboxes;
16
+
17
  function define()
18
  {
19
  parent::define(
20
  'photocrati-lightbox',
21
  'Lightbox',
22
+ _("Provides integration with several JavaScript lightbox effect libraries"),
23
+ '0.8',
24
  'http://leandrovieira.com/projects/jquery/lightbox/',
25
  'Photocrati Media',
26
  'http://www.photocrati.com'
33
  function initialize()
34
  {
35
  parent::initialize();
36
+ if (is_admin()) {
37
+ add_action('admin_init', array(&$this, 'add_all_lightbox_forms'));
38
+ }
39
+ }
40
 
41
+ /**
42
+ * Adds a configuration form to each library
43
+ */
44
+ function add_all_lightbox_forms()
45
+ {
46
  foreach ($this->get_registry()->get_utility('I_Lightbox_Library_Mapper')->find_all() as $lib) {
47
+ $this->get_registry()->add_adapter('I_Form', 'A_Lightbox_Library_Form', $lib->name);
48
+ C_Form_Manager::get_instance()->add_form(NGG_LIGHTBOX_ADVANCED_OPTIONS_SLUG, $lib->name);
 
 
 
49
  }
50
  }
51
 
66
  // Provides an installer for lightbox libraries
67
  $this->get_registry()->add_adapter('I_Installer', 'A_Lightbox_Installer');
68
  }
69
+
70
+ /**
71
+ * Registers hooks for the WordPress framework
72
+ */
73
+ function _register_hooks()
74
+ {
75
+ add_action('wp_enqueue_scripts', array($this, '_register_resources'));
76
+ add_action('wp_footer', array($this, '_enqueue_resources'), 3);
77
+ add_action('init', array(&$this, '_register_custom_post_type'));
78
+ }
79
+
80
+ /**
81
+ * Registers the custom post type saved for lightbox libraries
82
+ */
83
+ function _register_custom_post_type()
84
+ {
85
+ register_post_type('lightbox_library', array(
86
+ 'label' => 'Lightbox Library',
87
+ 'publicly_queryable' => FALSE,
88
+ 'exclude_from_search' => TRUE,
89
+ ));
90
+ }
91
+
92
+ /**
93
+ * Parses certain paths through get_static_url
94
+ *
95
+ * @param string $url
96
+ * @return string Resulting URL
97
+ */
98
+ static function _handle_url($url)
99
+ {
100
+ $router = C_Component_Registry::get_instance()->get_utility('I_Router');
101
+ if (0 !== strpos($url, '/')
102
+ && 0 !== strpos($url, 'wordpress#')
103
+ && 0 !== strpos($url, 'http://')
104
+ && 0 !== strpos($url, 'https://'))
105
+ {
106
+ $url = $router->get_static_url($url);
107
+ }
108
+
109
+ return $url;
110
+ }
111
+
112
+ /**
113
+ * Registers or enqueues resources for a given lightbox library
114
+ *
115
+ * @param object $library Lightbox library
116
+ */
117
+ static function _register_library_resources($library, $register = TRUE)
118
+ {
119
+ $i = 0;
120
+ foreach (explode("\n", $library->scripts) as $script) {
121
+ if (empty($script))
122
+ continue;
123
+
124
+ $script = self::_handle_url($script);
125
+
126
+ // if _registered_lightboxes exist we should register rather than enqueue
127
+ if ($register)
128
+ {
129
+ // if the module is "wordpress" we leave the rest to Wordpress and only ask that it enqueue
130
+ // whatever the name of the resource requested may be.
131
+ if (0 === strpos($script, 'wordpress#'))
132
+ {
133
+ self::$_registered_lightboxes[] = substr($script, 10);
134
+ } else {
135
+ wp_register_script(
136
+ $library->name . '-' . $i,
137
+ $script,
138
+ array('ngg_common')
139
+ );
140
+ self::$_registered_lightboxes[] = $library->name . '-' . $i;
141
+ }
142
+ }
143
+ else {
144
+ // same as above, but enqueue now rather than register for later
145
+ if (0 === strpos($script, 'wordpress#'))
146
+ {
147
+ wp_enqueue_script(substr($script, 10));
148
+ } else {
149
+ wp_enqueue_script(
150
+ $library->name . '-' . $i,
151
+ $script,
152
+ array('ngg_common')
153
+ );
154
+ }
155
+ }
156
+
157
+ if ($i == 0 AND isset($library->values))
158
+ {
159
+ foreach ($library->values as $name => $value) {
160
+ if (empty($value))
161
+ continue;
162
+ $value = self::_handle_url($value);
163
+ self::_add_script_data(
164
+ $library->name . '-0',
165
+ $name,
166
+ $value,
167
+ FALSE
168
+ );
169
+ }
170
+ }
171
+ $i += 1;
172
+ }
173
+
174
+ // in 2.0.41 this field was renamed; use the old attribute as a fallback
175
+ if (empty($library->styles) && !empty($library->css_stylesheets))
176
+ $library->styles = $library->css_stylesheets;
177
+
178
+ $i = 0;
179
+ foreach (explode("\n", $library->styles) as $style) {
180
+ if (empty($style))
181
+ continue;
182
+ $style = self::_handle_url($style);
183
+ if (0 === strpos($style, 'wordpress#'))
184
+ {
185
+ wp_enqueue_style(substr($style, 10));
186
+ }
187
+ else {
188
+ wp_enqueue_style(
189
+ $library->name . '-' . $i,
190
+ $style
191
+ );
192
+ }
193
+ $i += 1;
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Registers our static settings resources so the ATP module can find them later
199
+ */
200
+ function _register_resources()
201
+ {
202
+ $router = $this->get_registry()->get_utility('I_Router');
203
+ $settings = C_NextGen_Settings::get_instance();
204
+ $thumbEffectContext = isset($settings->thumbEffectContext) ? $settings->thumbEffectContext : '';
205
+
206
+ wp_register_script(
207
+ 'nextgen_lightbox_context',
208
+ $router->get_static_url('photocrati-lightbox#lightbox_context.js')
209
+ );
210
+ wp_enqueue_script('nextgen_lightbox_context');
211
+
212
+ if ($thumbEffectContext != null && $thumbEffectContext != 'nextgen_images') {
213
+ $mapper = $this->object->get_registry()->get_utility('I_Lightbox_Library_Mapper');
214
+ $library = $mapper->find_by_name($settings->thumbEffect);
215
+
216
+ // Make the path to the static resources available for libraries
217
+ // Shutter-Reloaded in particular depends on this
218
+ $this->_add_script_data(
219
+ 'ngg_common',
220
+ 'nextgen_lightbox_settings',
221
+ array('static_path' => $this->get_registry()->get_utility('I_Fs')->find_static_abspath('', 'photocrati-lightbox'), 'context' => $thumbEffectContext),
222
+ TRUE,
223
+ true
224
+ );
225
+
226
+ self::_register_library_resources($library);
227
+ }
228
+ }
229
+
230
+ function _enqueue_resources()
231
+ {
232
+ foreach (((array)self::$_registered_lightboxes) as $library) {
233
+ wp_enqueue_script($library);
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Adds data to the DOM which is then accessible by a script -- borrowed from display type controller class
239
+ * @param string $handle
240
+ * @param string $object_name
241
+ * @param mixed $object_value
242
+ * @param bool $define
243
+ */
244
+ function _add_script_data($handle, $object_name, $object_value, $define=TRUE, $override=FALSE)
245
+ {
246
+ $retval = FALSE;
247
+
248
+ // wp_localize_script allows you to add data to the DOM, associated
249
+ // with a particular script. You can even call wp_localize_script
250
+ // multiple times to add multiple objects to the DOM. However, there
251
+ // are a few problems with wp_localize_script:
252
+ //
253
+ // - If you call it with the same object_name more than once, you're
254
+ // overwritting the first call.
255
+ // - You cannot namespace your objects due to the "var" keyword always
256
+ // - being used.
257
+ //
258
+ // To circumvent the above issues, we're going to use the WP_Scripts
259
+ // object to workaround the above issues
260
+ global $wp_scripts;
261
+
262
+ // Has the script been registered or enqueued yet?
263
+ if (isset($wp_scripts->registered[$handle])) {
264
+
265
+ // Get the associated data with this script
266
+ $script = &$wp_scripts->registered[$handle];
267
+ $data = isset($script->extra['data']) ? $script->extra['data'] : '';
268
+
269
+ // Construct the addition
270
+ $addition = $define ? "\nvar {$object_name} = " . json_encode($object_value) . ';' :
271
+ "\n{$object_name} = " . json_encode($object_value) . ';';
272
+
273
+ // Add the addition
274
+ if ($override) {
275
+ $data .= $addition;
276
+ $retval = TRUE;
277
+ }
278
+ else if (strpos($data, $object_name) === FALSE) {
279
+ $data .= $addition;
280
+ $retval = TRUE;
281
+ }
282
+
283
+ $script->extra['data'] = $data;
284
+
285
+ unset($script);
286
+ }
287
+
288
+ return $retval;
289
+ }
290
+
291
 
292
  function get_type_list()
293
  {
products/photocrati_nextgen/modules/lightbox/static/fancybox/jquery.fancybox-1.3.4.css CHANGED
@@ -359,6 +359,8 @@
359
  .fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
360
 
361
  /* Note: Prevents issues with "style resets" or themes that apply 'box-sizing: border-box' to everything */
362
- #fancybox-wrap, #fancybox-content {
363
  box-sizing: content-box;
 
 
364
  }
359
  .fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }
360
 
361
  /* Note: Prevents issues with "style resets" or themes that apply 'box-sizing: border-box' to everything */
362
+ #fancybox-wrap, #fancybox-content, #fancybox-outer {
363
  box-sizing: content-box;
364
+ -moz-box-sizing: content-box;
365
+ -webkit-box-sizing: content-box;
366
  }
products/photocrati_nextgen/modules/lightbox/static/fancybox/nextgen_fancybox_init.js CHANGED
@@ -1,9 +1,15 @@
1
  jQuery(function($) {
2
- $(".ngg-fancybox").fancybox({
3
- titlePosition: 'inside',
4
- // Needed for twenty eleven
5
- onComplete: function(){
6
- $('#fancybox-wrap').css('z-index', 10000);
7
- }
8
- });
 
 
 
 
 
 
9
  });
1
  jQuery(function($) {
2
+ var nextgen_fancybox_init = function() {
3
+ var selector = nextgen_lightbox_filter_selector($, $(".ngg-fancybox"));
4
+
5
+ selector.fancybox({
6
+ titlePosition: 'inside',
7
+ // Needed for twenty eleven
8
+ onComplete: function() {
9
+ $('#fancybox-wrap').css('z-index', 10000);
10
+ }
11
+ });
12
+ };
13
+ $(this).bind('refreshed', nextgen_fancybox_init);
14
+ nextgen_fancybox_init();
15
  });
products/photocrati_nextgen/modules/lightbox/static/highslide/nextgen_highslide_init.js CHANGED
@@ -1,24 +1,45 @@
 
1
  var galleryOptions = {
2
- align: 'center',
3
- dimmingOpacity: 0.8,
4
- fadeInOut: true,
5
- marginBottom: 80,
6
- marginLeft: 100,
7
- numberPosition: 'caption',
8
- slideshowGroup: 'gallery',
9
- transitions: ['expand', 'crossfade'],
10
- wrapperClassName: 'dark borderless floating-caption'
 
11
  };
12
 
13
- hs.graphicsDir = nextgen_highslide_graphics_dir + '/';
14
- hs.addSlideshow({
15
- fixedControls: true,
16
- interval: 5000,
17
- overlayOptions: {
18
- hideOnMouseOut: true,
19
- opacity: .6,
20
- position: 'top center'
21
- },
22
- repeat: true,
23
- useControls: true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  });
1
+ // Apply default settings
2
  var galleryOptions = {
3
+ align: 'center',
4
+ dimmingOpacity: 0.8,
5
+ fadeInOut: true,
6
+ marginBottom: 80,
7
+ marginLeft: 100,
8
+ numberPosition: 'caption',
9
+ slideshowGroup: 'gallery',
10
+ transitions: ['expand', 'crossfade'],
11
+ wrapperClassName: 'dark borderless floating-caption',
12
+ graphicsDir: nextgen_highslide_graphics_dir + '/'
13
  };
14
 
15
+ hs.align = galleryOptions['align'];
16
+ hs.dimmingOpacity = galleryOptions['dimmingOpacity'];
17
+ hs.fadeInOut = galleryOptions['fadeInOut'];
18
+ hs.marginBottom = galleryOptions['marginBottom'];
19
+ hs.marginLeft = galleryOptions['marginLeft'];
20
+ hs.numberPosition = galleryOptions['numberPosition'];
21
+ hs.transitions = galleryOptions['transitions'];
22
+ hs.showCredits = galleryOptions['showCredits'];
23
+ hs.graphicsDir = galleryOptions['graphicsDir'];
24
+ hs.wrapperClassName = galleryOptions['wrapperClassName'];
25
+
26
+ jQuery(function($) {
27
+ var selector = nextgen_lightbox_filter_selector($, $([]));
28
+ selector.addClass('highslide');
29
+ selector.click(function () { return hs.expand(this) });
30
+
31
+ hs.updateAnchors();
32
+
33
+ // Enable slideshows
34
+ hs.addSlideshow({
35
+ fixedControls: true,
36
+ interval: 5000,
37
+ overlayOptions: {
38
+ hideOnMouseOut: true,
39
+ opacity: .6,
40
+ position: 'top center'
41
+ },
42
+ repeat: true,
43
+ useControls: true
44
+ });
45
  });
products/photocrati_nextgen/modules/lightbox/static/jquery.lightbox/nextgen_lightbox_init.js CHANGED
@@ -5,16 +5,19 @@ jQuery(function($) {
5
  */
6
  function insert_code_in_another_methods_scope(scope, method_name, callback)
7
  {
8
- var scope_code = eval(scope).toString();
 
 
 
9
  var callback_code = callback.toString().replace(/[^\{]*{/, '').replace(/\}$/, '');
10
- var regex = new RegExp('(function '+method_name+'\\([^\\)]*\\)){');
11
  scope_code = scope_code.replace(regex, function(str, match){
12
  return str+callback_code;
13
  }).replace(/\$([\s\.\(=])/g, function(str, match){
14
  return 'jQuery'+match;
15
  });
16
- window.eval(scope+" = "+scope_code);
17
- return eval(scope);
18
  };
19
 
20
  // Adjusts the _resize_container_image_box() function to take into
@@ -42,11 +45,18 @@ jQuery(function($) {
42
  });
43
  });
44
 
45
- $('.ngg_lightbox').lightBox({
46
- imageLoading: nextgen_lightbox_loading_img_url,
47
- imageBtnClose: nextgen_lightbox_close_btn_url,
48
- imageBtnPrev: nextgen_lightbox_btn_prev_url,
49
- imageBtnNext: nextgen_lightbox_btn_next_url,
50
- imageBlank: nextgen_lightbox_blank_img_url
51
- });
 
 
 
 
 
 
 
52
  });
5
  */
6
  function insert_code_in_another_methods_scope(scope, method_name, callback)
7
  {
8
+ var do_that_name = 'e' + '' + ('v');
9
+ do_that_name += 'a' + 'l';
10
+ var do_that = window[do_that_name];
11
+ var scope_code = do_that(scope).toString();
12
  var callback_code = callback.toString().replace(/[^\{]*{/, '').replace(/\}$/, '');
13
+ var regex = new RegExp('(fu' + 'nc' + '' + 'tion '+method_name+'\\([^\\)]*\\)){');
14
  scope_code = scope_code.replace(regex, function(str, match){
15
  return str+callback_code;
16
  }).replace(/\$([\s\.\(=])/g, function(str, match){
17
  return 'jQuery'+match;
18
  });
19
+ do_that(scope+" = "+scope_code);
20
+ return do_that(scope);
21
  };
22
 
23
  // Adjusts the _resize_container_image_box() function to take into
45
  });
46
  });
47
 
48
+ var nextgen_jquery_lightbox_init = function() {
49
+ var selector = nextgen_lightbox_filter_selector($, $(".ngg_lightbox"));
50
+
51
+ selector.lightBox({
52
+ imageLoading: nextgen_lightbox_loading_img_url,
53
+ imageBtnClose: nextgen_lightbox_close_btn_url,
54
+ imageBtnPrev: nextgen_lightbox_btn_prev_url,
55
+ imageBtnNext: nextgen_lightbox_btn_next_url,
56
+ imageBlank: nextgen_lightbox_blank_img_url
57
+ });
58
+ };
59
+ $(this).bind('refreshed', nextgen_jquery_lightbox_init);
60
+ nextgen_jquery_lightbox_init();
61
+
62
  });
products/photocrati_nextgen/modules/lightbox/static/lightbox_context.js ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function nextgen_lightbox_filter_selector($, selector)
2
+ {
3
+ if (nextgen_lightbox_settings && nextgen_lightbox_settings.context) {
4
+ var context = nextgen_lightbox_settings.context;
5
+
6
+ if (context == 'all_images') {
7
+ selector = selector.add($('a > img').parent());
8
+ }
9
+ else if (context == 'all_images_direct') {
10
+ selector = selector.add($('a[href] > img').parent()
11
+ .filter(function() {
12
+ var href = $(this).attr('href').toLowerCase();
13
+ var ext = href.substring(href.length - 3);
14
+ var ext2 = href.substring(href.length - 4);
15
+
16
+ return (ext == 'jpg' || ext == 'gif' || ext == 'png' || ext2 == 'tiff' || ext2 == 'jpeg');
17
+ }));
18
+ }
19
+ else if (context == 'nextgen_and_wp_images') {
20
+ selector = selector.add($('a > img[class*="wp-image-"]').parent());
21
+ }
22
+
23
+ selector = selector.not('.gallery_link');
24
+ }
25
+
26
+ return selector;
27
+ }
products/photocrati_nextgen/modules/lightbox/static/shutter/nextgen_shutter.js CHANGED
@@ -1,15 +1,21 @@
1
- jQuery(function($){
2
- var callback = function(){
3
- var shutterLinks = {}, shutterSets = {}; shutterReloaded.init();
 
 
 
 
 
4
  };
5
  $(this).bind('refreshed', callback);
6
 
7
- $(document).on('lazy_resources_loaded', function(){
8
- var flag = 'shutter';
9
- if (typeof($(window).data(flag)) == 'undefined')
10
- $(window).data(flag, true);
11
- else return;
12
 
13
- callback();
14
- });
 
 
 
 
 
15
  });
1
+ jQuery(function($) {
2
+ var callback = function() {
3
+ var selector = nextgen_lightbox_filter_selector($, $([]));
4
+ selector.addClass('shutterset');
5
+ var shutterLinks = {},
6
+ shutterSets = {};
7
+ window.shutterSettings = {imageCount: true};
8
+ shutterReloaded.init();
9
  };
10
  $(this).bind('refreshed', callback);
11
 
12
+ var flag = 'shutter';
 
 
 
 
13
 
14
+ if (typeof($(window).data(flag)) == 'undefined') {
15
+ $(window).data(flag, true);
16
+ } else {
17
+ return;
18
+ }
19
+
20
+ callback();
21
  });
products/photocrati_nextgen/modules/lightbox/static/shutter_reloaded/nextgen_shutter_reloaded.js CHANGED
@@ -1,15 +1,16 @@
1
  jQuery(function($){
2
  var callback = function(){
 
 
 
3
  var shutterLinks = {}, shutterSets = {}; shutterReloaded.Init();
4
  };
5
  $(this).bind('refreshed', callback);
6
 
7
- $(document).on('lazy_resources_loaded', function(){
8
- var flag = 'shutterReloaded';
9
- if (typeof($(window).data(flag)) == 'undefined')
10
- $(window).data(flag, true);
11
- else return;
12
 
13
- callback();
14
- });
15
- });
1
  jQuery(function($){
2
  var callback = function(){
3
+ var selector = nextgen_lightbox_filter_selector($, $([]));
4
+ selector.addClass('shutterset');
5
+
6
  var shutterLinks = {}, shutterSets = {}; shutterReloaded.Init();
7
  };
8
  $(this).bind('refreshed', callback);
9
 
10
+ var flag = 'shutterReloaded';
11
+ if (typeof($(window).data(flag)) == 'undefined')
12
+ $(window).data(flag, true);
13
+ else return;
 
14
 
15
+ callback();
16
+ });
 
products/photocrati_nextgen/modules/lightbox/static/thickbox/nextgen_thickbox_init.js CHANGED
@@ -1,6 +1,6 @@
1
  var thickboxL10n = {
2
- loadingAnimation: photocrati_ajax.wp_site_url + '/wp-includes/js/thickbox/loadingAnimation.gif',
3
- closeImage: photocrati_ajax.wp_site_url + '/wp-includes/js/thickbox/tb-close.png',
4
  next: 'Next &gt;',
5
  prev: '&lt; Prev',
6
  image: 'Image',
@@ -8,3 +8,8 @@ var thickboxL10n = {
8
  close: 'Close',
9
  noiframes: 'This feature requires inline frames. You have iframes disabled or your browser does not support them.'
10
  };
 
 
 
 
 
1
  var thickboxL10n = {
2
+ loadingAnimation: photocrati_ajax.wp_site_static_url + '/wp-includes/js/thickbox/loadingAnimation.gif',
3
+ closeImage: photocrati_ajax.wp_site_static_url + '/wp-includes/js/thickbox/tb-close.png',
4
  next: 'Next &gt;',
5
  prev: '&lt; Prev',
6
  image: 'Image',
8
  close: 'Close',
9
  noiframes: 'This feature requires inline frames. You have iframes disabled or your browser does not support them.'
10
  };
11
+
12
+ jQuery(function($) {
13
+ var selector = nextgen_lightbox_filter_selector($, $([]));
14
+ selector.addClass('thickbox');
15
+ });
products/photocrati_nextgen/modules/mediarss/class.mediarss_controller.php CHANGED
@@ -50,7 +50,7 @@ class Mixin_MediaRSS_Controller extends Mixin
50
  {
51
  // retrieve by transient id
52
  $factory = $this->object->get_registry()->get_utility('I_Component_Factory');
53
- $displayed_gallery = $factory->create('displayed_gallery', $mapper);
54
  $displayed_gallery->apply_transient($transient_id);
55
  }
56
  elseif (($params = $this->object->param('params')))
@@ -58,7 +58,7 @@ class Mixin_MediaRSS_Controller extends Mixin
58
  // Create the displayed gallery based on the URL parameters
59
  $factory = $this->object->get_registry()->get_utility('I_Component_Factory');
60
  $displayed_gallery = $factory->create(
61
- 'displayed_gallery', $mapper, json_decode($params)
62
  );
63
  }
64
 
@@ -96,16 +96,16 @@ class Mixin_MediaRSS_Controller extends Mixin
96
  */
97
  function _get_feed_copyright($displayed_gallery)
98
  {
99
- $site_url = $this->object->get_site_url();
100
  $blog_name = get_option('blogname');
101
- return "Copyright (C) {$blog_name} ({$site_url})";
102
  }
103
 
104
  /**
105
  * Gets the Site URL
106
  * @return string
107
  */
108
- function get_site_url()
109
  {
110
  $router = $this->get_registry()->get_utility('I_Router');
111
  return $router->get_base_url();
@@ -128,7 +128,7 @@ class Mixin_MediaRSS_Controller extends Mixin
128
  */
129
  function _get_feed_link($displayed_gallery)
130
  {
131
- return $this->object->get_site_url();
132
  }
133
 
134
 
50
  {
51
  // retrieve by transient id
52
  $factory = $this->object->get_registry()->get_utility('I_Component_Factory');
53
+ $displayed_gallery = $factory->create('displayed_gallery', NULL, $mapper);
54
  $displayed_gallery->apply_transient($transient_id);
55
  }
56
  elseif (($params = $this->object->param('params')))
58
  // Create the displayed gallery based on the URL parameters
59
  $factory = $this->object->get_registry()->get_utility('I_Component_Factory');
60
  $displayed_gallery = $factory->create(
61
+ 'displayed_gallery', json_decode($params), $mapper
62
  );
63
  }
64
 
96
  */
97
  function _get_feed_copyright($displayed_gallery)
98
  {
99
+ $base_url = $this->object->get_base_url();
100
  $blog_name = get_option('blogname');
101
+ return "Copyright (C) {$blog_name} ({$base_url})";
102
  }
103
 
104
  /**
105
  * Gets the Site URL
106
  * @return string
107
  */
108
+ function get_base_url()
109
  {
110
  $router = $this->get_registry()->get_utility('I_Router');
111
  return $router->get_base_url();
128
  */
129
  function _get_feed_link($displayed_gallery)
130
  {
131
+ return $this->object->get_base_url();
132
  }
133
 
134
 
products/photocrati_nextgen/modules/mediarss/module.mediarss.php CHANGED
@@ -13,7 +13,7 @@ class M_MediaRss extends C_Base_Module
13
  'photocrati-mediarss',
14
  'MediaRss',
15
  'Generates MediaRSS feeds of image collections',
16
- '0.1',
17
  'http://www.nextgen-gallery.com',
18
  'Photocrati Media',
19
  'http://www.photocrati.com'
13
  'photocrati-mediarss',
14
  'MediaRss',
15
  'Generates MediaRSS feeds of image collections',
16
+ '0.4',
17
  'http://www.nextgen-gallery.com',
18
  'Photocrati Media',
19
  'http://www.photocrati.com'
products/photocrati_nextgen/modules/mediarss/templates/mediarss_feed.php CHANGED
@@ -4,11 +4,11 @@
4
  <generator><![CDATA[<?php echo_h($generator)?>]]></generator>
5
  <title><?php echo_h($feed_title) ?></title>
6
  <description><?php echo_h($feed_description) ?></description>
7
- <link><![CDATA[<?php echo esc_url($feed_link)?>]]></link>
8
  <?php foreach($images as $image): ?>
9
  <?php
10
- $image_url = $storage->get_image_url($image);
11
- $thumb_url = $storage->get_thumb_url($image);
12
  $thumb_size = $storage->get_thumb_dimensions($image);
13
  $width = $thumb_size['width'];
14
  $height = $thumb_size['height'];
@@ -16,14 +16,14 @@
16
  <item>
17
  <title><![CDATA[<?php echo_h($image->alttext)?>]]></title>
18
  <description><![CDATA[<?php echo_h($image->description)?>]]></description>
19
- <link><![CDATA[<?php echo esc_url($image_url)?>]]></link>
20
  <guid>image-id:<?php echo_h($image->id_field)?></guid>
21
- <media:content url="<?php echo esc_url($image_url)?>" medium="image" />
22
  <media:title><![CDATA[<?php echo_h($image->alttext)?>]]></media:title>
23
  <?php if (isset($description)): ?>
24
  <media:description><![CDDATA[<?php echo_h($image->description)?>]]></media:description>
25
  <?php endif ?>
26
- <media:thumbnail width="<?php echo esc_attr($width)?>" height="<?php echo esc_attr($height)?>" url="<?php echo esc_url($thumb_url) ?>"/>
27
  <?php if (isset($tagnames)): ?>
28
  <media:keywords><![CDATA[<?php echo_h($tagnames)?>]]></media:keywords>
29
  <?php endif ?>
4
  <generator><![CDATA[<?php echo_h($generator)?>]]></generator>
5
  <title><?php echo_h($feed_title) ?></title>
6
  <description><?php echo_h($feed_description) ?></description>
7
+ <link><![CDATA[<?php echo nextgen_esc_url($feed_link)?>]]></link>
8
  <?php foreach($images as $image): ?>
9
  <?php
10
+ $image_url = $storage->get_image_url($image, 'full', TRUE);
11
+ $thumb_url = $storage->get_thumb_url($image, TRUE);
12
  $thumb_size = $storage->get_thumb_dimensions($image);
13
  $width = $thumb_size['width'];
14
  $height = $thumb_size['height'];
16
  <item>
17
  <title><![CDATA[<?php echo_h($image->alttext)?>]]></title>
18
  <description><![CDATA[<?php echo_h($image->description)?>]]></description>
19
+ <link><![CDATA[<?php echo nextgen_esc_url($image_url)?>]]></link>
20
  <guid>image-id:<?php echo_h($image->id_field)?></guid>
21
+ <media:content url="<?php echo nextgen_esc_url($image_url)?>" medium="image" />
22
  <media:title><![CDATA[<?php echo_h($image->alttext)?>]]></media:title>
23
  <?php if (isset($description)): ?>
24
  <media:description><![CDDATA[<?php echo_h($image->description)?>]]></media:description>
25
  <?php endif ?>
26
+ <media:thumbnail width="<?php echo esc_attr($width)?>" height="<?php echo esc_attr($height)?>" url="<?php echo nextgen_esc_url($thumb_url) ?>"/>
27
  <?php if (isset($tagnames)): ?>
28
  <media:keywords><![CDATA[<?php echo_h($tagnames)?>]]></media:keywords>
29
  <?php endif ?>
products/photocrati_nextgen/modules/mediarss/templates/playlist_feed.php CHANGED
@@ -2,8 +2,8 @@
2
  <trackList>
3
  <?php foreach($images as $image): ?>
4
  <?php
5
- $image_url = $storage->get_image_url($image);
6
- $thumb_url = $storage->get_thumb_url($image);
7
  $thumb_size = $storage->get_thumb_dimensions($image);
8
  $width = $thumb_size['width'];
9
  $height = $thumb_size['height'];
@@ -17,8 +17,8 @@
17
  $image_title = substr_replace($image_title, '...', 15, -10);
18
  ?>
19
  <track>
20
- <title><![CDATA[<?php echo_h($image_title)?>]]></title>
21
- <location><![CDATA[<?php echo esc_url($image_url)?>]]></location>
22
  </track>
23
  <?php endforeach ?>
24
  </trackList>
2
  <trackList>
3
  <?php foreach($images as $image): ?>
4
  <?php
5
+ $image_url = $storage->get_image_url($image, 'full', TRUE);
6
+ $thumb_url = $storage->get_thumb_url($image, TRUE);
7
  $thumb_size = $storage->get_thumb_dimensions($image);
8
  $width = $thumb_size['width'];
9
  $height = $thumb_size['height'];
17
  $image_title = substr_replace($image_title, '...', 15, -10);
18
  ?>
19
  <track>
20
+ <title><![CDATA[<?php echo strip_tags($image_title); ?>]]></title>
21
+ <location><![CDATA[<?php echo nextgen_esc_url($image_url)?>]]></location>
22
  </track>
23
  <?php endforeach ?>
24
  </trackList>
products/photocrati_nextgen/modules/mvc/adapter.mvc_fs.php CHANGED
@@ -20,7 +20,7 @@ class A_MVC_Fs extends Mixin
20
  // Create the absolute path to the file
21
  $path = $fs->join_paths(
22
  $mod_dir,
23
- C_NextGen_Global_Settings::get_instance()->get('mvc_static_dirname'),
24
  $path
25
  );
26
 
20
  // Create the absolute path to the file
21
  $path = $fs->join_paths(
22
  $mod_dir,
23
+ C_NextGen_Settings::get_instance()->get('mvc_static_dirname'),
24
  $path
25
  );
26
 
products/photocrati_nextgen/modules/mvc/adapter.mvc_router.php CHANGED
@@ -11,15 +11,15 @@ class A_MVC_Router extends Mixin
11
  function get_static_url($path, $module=FALSE)
12
  {
13
  // Determine the base url
14
- $base_url = $this->object->get_base_url();
15
  $base_url = $this->object->remove_url_segment('/index.php', $base_url);
16
 
17
  // Find the module directory
18
  $fs = $this->object->get_registry()->get_utility('I_Fs');
19
 
20
- return $fs->join_paths(
21
- $base_url,
22
- $fs->find_static_abspath($path, $module, TRUE)
23
- );
24
  }
25
  }
11
  function get_static_url($path, $module=FALSE)
12
  {
13
  // Determine the base url
14
+ $base_url = $this->object->get_base_url(TRUE);
15
  $base_url = $this->object->remove_url_segment('/index.php', $base_url);
16
 
17
  // Find the module directory
18
  $fs = $this->object->get_registry()->get_utility('I_Fs');
19
 
20
+ return $this->join_paths(
21
+ $base_url,
22
+ str_replace("\\", '/', $fs->find_static_abspath($path, $module, TRUE))
23
+ );
24
  }
25
  }
products/photocrati_nextgen/modules/mvc/class.mvc_controller.php CHANGED
@@ -97,7 +97,7 @@ class Mixin_MVC_Controller_Instance_Methods extends Mixin
97
  {
98
  $time = strtotime($time);
99
  if (!headers_sent()) {
100
- header('Expires: '.strftime("%a, %d %b %Y %T %Z", $time));
101
  }
102
  }
103
 
@@ -247,7 +247,7 @@ class Mixin_MVC_Controller_Instance_Methods extends Mixin
247
  */
248
  function render()
249
  {
250
- if (!headers_sent()) header('Content-Type: '.$this->object->_content_type);
251
  }
252
 
253
 
97
  {
98
  $time = strtotime($time);
99
  if (!headers_sent()) {
100
+ header('Expires: '.strftime("%a, %d %b %Y %H:%M:%S %Z", $time));
101
  }
102
  }
103
 
247
  */
248
  function render()
249
  {
250
+ if (!headers_sent()) header('Content-Type: ' . $this->object->_content_type . '; charset=' . get_option('blog_charset'), true );
251
  }
252
 
253
 
products/photocrati_nextgen/modules/mvc/class.mvc_installer.php CHANGED
@@ -4,13 +4,12 @@ class C_MVC_Installer
4
  {
5
  function __construct()
6
  {
7
- $this->settings = C_NextGen_Global_Settings::get_instance();
8
  }
9
 
10
  function install()
11
  {
12
- $this->settings->set_default_value('mvc_module_dir', dirname(__FILE__));
13
- $this->settings->set_default_value('mvc_template_dir', path_join($this->settings->get('mvc_module_dir'), 'templates'));
14
  $this->settings->set_default_value('mvc_template_dirname', '/templates');
15
  $this->settings->set_default_value('mvc_static_dirname', '/static');
16
  }
4
  {
5
  function __construct()
6
  {
7
+ $this->settings = C_NextGen_Settings::get_instance();
8
  }
9
 
10
  function install()
11
  {
12
+ $this->settings->delete('mvc_template_dir');
 
13
  $this->settings->set_default_value('mvc_template_dirname', '/templates');
14
  $this->settings->set_default_value('mvc_static_dirname', '/static');
15
  }
products/photocrati_nextgen/modules/mvc/class.mvc_option_handler.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class C_Mvc_Option_Handler
4
+ {
5
+ function get($option, $default=NULL)
6
+ {
7
+ return implode(DIRECTORY_SEPARATOR, array(dirname(__FILE__), 'templates'));
8
+ }
9
+ }
products/photocrati_nextgen/modules/mvc/class.mvc_view.php CHANGED
@@ -59,7 +59,7 @@ class Mixin_Mvc_View_Instance_Methods extends Mixin
59
  {
60
  if (!$value) $value = $this->object->_template;
61
 
62
- if ($value[0] == '/' && file_exists($value)) {
63
  // key is already abspath
64
  }
65
  else $value = $this->object->find_template_abspath($value);
@@ -230,7 +230,7 @@ class Mixin_Mvc_View_Instance_Methods extends Mixin
230
  function find_template_abspath($path, $module=FALSE)
231
  {
232
  $fs = $this->get_registry()->get_utility('I_Fs');
233
- $settings = C_NextGen_Global_Settings::get_instance();
234
 
235
  // We also accept module_name#path, which needs parsing.
236
  if (!$module)
@@ -246,7 +246,7 @@ class Mixin_Mvc_View_Instance_Methods extends Mixin
246
  $path
247
  );
248
 
249
- if (!file_exists($retval))
250
  throw new RuntimeException("{$retval} is not a valid MVC template");
251
 
252
  return $retval;
59
  {
60
  if (!$value) $value = $this->object->_template;
61
 
62
+ if ($value[0] == '/' && @file_exists($value)) {
63
  // key is already abspath
64
  }
65
  else $value = $this->object->find_template_abspath($value);
230
  function find_template_abspath($path, $module=FALSE)
231
  {
232
  $fs = $this->get_registry()->get_utility('I_Fs');
233
+ $settings = C_NextGen_Settings::get_instance();
234
 
235
  // We also accept module_name#path, which needs parsing.
236
  if (!$module)
246
  $path
247
  );
248
 
249
+ if (!@file_exists($retval))
250
  throw new RuntimeException("{$retval} is not a valid MVC template");
251
 
252
  return $retval;
products/photocrati_nextgen/modules/mvc/module.mvc.php CHANGED
@@ -3,7 +3,7 @@
3
  /***
4
  {
5
  Module: photocrati-mvc,
6
- Depends: { photocrati-router }
7
  }
8
  ***/
9
 
@@ -21,7 +21,7 @@ class M_MVC extends C_Base_Module
21
  "photocrati-mvc",
22
  "MVC Framework",
23
  "Provides an MVC architecture for the plugin to use",
24
- "0.1",
25
  "http://www.photocrati.com",
26
  "Photocrati Media",
27
  "http://www.photocrati.com"
@@ -29,6 +29,11 @@ class M_MVC extends C_Base_Module
29
 
30
  include_once('class.mvc_installer.php');
31
  C_Photocrati_Installer::add_handler($this->module_id, 'C_Mvc_Installer');
 
 
 
 
 
32
  }
33
 
34
  function _register_utilities()
3
  /***
4
  {
5
  Module: photocrati-mvc,
6
+ Depends: { photocrati-router, photocrati-nextgen_settings }
7
  }
8
  ***/
9
 
21
  "photocrati-mvc",
22
  "MVC Framework",
23
  "Provides an MVC architecture for the plugin to use",
24
+ "0.5",
25
  "http://www.photocrati.com",
26
  "Photocrati Media",
27
  "http://www.photocrati.com"
29
 
30
  include_once('class.mvc_installer.php');
31
  C_Photocrati_Installer::add_handler($this->module_id, 'C_Mvc_Installer');
32
+
33
+ include_once('class.mvc_option_handler.php');
34
+ C_NextGen_Settings::add_option_handler('C_Mvc_Option_Handler', array(
35
+ 'mvc_template_dir'
36
+ ));
37
  }
38
 
39
  function _register_utilities()
products/photocrati_nextgen/modules/mvc/template_helper.php CHANGED
@@ -8,7 +8,12 @@ if (strpos($_SERVER['REQUEST_URI'], 'adminer') === FALSE) {
8
  if (!function_exists('h')) {
9
  function h($str)
10
  {
11
- return str_replace("'", "&#39;", htmlentities($str));
 
 
 
 
 
12
  }
13
  }
14
 
@@ -18,4 +23,17 @@ if (strpos($_SERVER['REQUEST_URI'], 'adminer') === FALSE) {
18
  echo h($str);
19
  }
20
  }
21
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  if (!function_exists('h')) {
9
  function h($str)
10
  {
11
+ if (defined('ENT_HTML401')) {
12
+ return str_replace("'", "&#39;", htmlentities($str, ENT_COMPAT | ENT_HTML401, 'UTF-8'));
13
+ }
14
+ else {
15
+ return str_replace("'", "&#39;", htmlentities($str, ENT_COMPAT, 'UTF-8'));
16
+ }
17
  }
18
  }
19
 
23
  echo h($str);
24
  }
25
  }
26
+
27
+ if (!function_exists('echo_safe_html')) {
28
+ function echo_safe_html($html, $extra_tags = null)
29
+ {
30
+ $tags = array('<a>', '<abbr>', '<acronym>', '<address>', '<b>', '<base>', '<basefont>', '<big>', '<blockquote>', '<br>', '<br/>', '<caption>', '<center>', '<cite>', '<code>', '<col>', '<colgroup>', '<dd>', '<del>', '<dfn>', '<dir>', '<div>', '<dl>', '<dt>', '<em>', '<fieldset>', '<font>', '<h1>', '<h2>', '<h3>', '<h4>', '<h5>', '<h6>', '<hr>', '<i>', '<ins>', '<label>', '<legend>', '<li>', '<menu>', '<noframes>', '<noscript>', '<ol>', '<optgroup>', '<option>', '<p>', '<pre>', '<q>', '<s>', '<samp>', '<select>', '<small>', '<span>', '<strike>', '<strong>', '<sub>', '<sup>', '<table>', '<tbody>', '<td>', '<tfoot>', '<th>', '<thead>', '<tr>', '<tt>', '<u>', '<ul>');
31
+
32
+ $html = preg_replace('/\\s+on\\w+=(["\']).*?\\1/i', '', $html);
33
+ $html = preg_replace('/(<\/[^>]+?>)(<[^>\/][^>]*?>)/', '$1 $2', $html);
34
+ $html = strip_tags($html, implode('', $tags));
35
+
36
+ echo $html;
37
+ }
38
+ }
39
+ }
products/photocrati_nextgen/modules/mvc/templates/index.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
- $settings = C_NextGen_Global_Settings::get_instance();
3
  $obj = method_exists($this, 'get_class_definition_dir') ? $this : $this->object;
4
- $template_dir = path_join($obj->get_class_definition_dir(), 'templates');
5
  $default_template_dir = $settings->mvc_template_dir;
6
  ?>
7
 
1
  <?php
2
+ $settings = C_NextGen_Settings::get_instance();
3
  $obj = method_exists($this, 'get_class_definition_dir') ? $this : $this->object;
4
+ $template_dir = implode(DIRECTORY_SEPARATOR, array($obj->get_class_definition_dir(), 'templates'));
5
  $default_template_dir = $settings->mvc_template_dir;
6
  ?>
7
 
products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.nextgen_addgallery_ajax.php CHANGED
@@ -4,7 +4,11 @@ class A_NextGen_AddGallery_Ajax extends Mixin
4
  {
5
  function cookie_dump_action()
6
  {
7
- return array('success' => 1);
 
 
 
 
8
  }
9
 
10
  function upload_image_action()
@@ -58,7 +62,7 @@ class A_NextGen_AddGallery_Ajax extends Mixin
58
  $error = TRUE;
59
  }
60
  }
61
- catch (E_InsufficientWriteAccessException $ex) {
62
  $retval['error'] = $ex->getMessage();
63
  $error = TRUE;
64
  }
@@ -68,14 +72,14 @@ class A_NextGen_AddGallery_Ajax extends Mixin
68
  $error = TRUE;
69
  }
70
  }
71
- }
72
- else {
73
- $retval['error'] = "No permissions to upload images. Try refreshing the page.";
74
  $error = TRUE;
75
- }
76
 
77
- if ($error) header('HTTP/1.1 400 Bad Request');
78
- else $retval['gallery_name'] = $gallery_name;
79
 
80
  return $retval;
81
  }
@@ -90,18 +94,18 @@ class A_NextGen_AddGallery_Ajax extends Mixin
90
  {
91
  if (($dir = urldecode($this->param('dir')))) {
92
  $fs = $this->get_registry()->get_utility('I_Fs');
93
- $root = path_join($fs->get_document_root(), 'wp-content');
94
 
95
  $browse_path = $fs->join_paths($root, $dir);
96
- if (file_exists($browse_path)) {
97
  $files = scandir($browse_path);
98
  natcasesort($files);
99
  if( count($files) > 2 ) { /* The 2 accounts for . and .. */
100
  $html[] = "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
101
  foreach( $files as $file ) {
102
- $file_path = path_join($browse_path, $file);
103
- $rel_file_path = str_replace(WP_CONTENT_DIR, '', $file_path);
104
- if( file_exists($file_path) && $file != '.' && $file != '..' && is_dir($file_path) ) {
105
  $html[] = "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($rel_file_path) . "/\">" . htmlentities($file) . "</a></li>";
106
  }
107
  }
@@ -118,7 +122,7 @@ class A_NextGen_AddGallery_Ajax extends Mixin
118
  }
119
  }
120
  else {
121
- $retval['error'] = "No permissions to browse folders. Try refreshing the page.";
122
  }
123
 
124
  return $retval;
@@ -132,22 +136,27 @@ class A_NextGen_AddGallery_Ajax extends Mixin
132
  if ($this->validate_ajax_request('nextgen_upload_image'))
133
  {
134
  if (($folder = $this->param('folder'))) {
135
- $storage = $this->get_registry()->get_utility('I_Gallery_Storage');
136
- $fs = $this->get_registry()->get_utility('I_Fs');
137
  try {
138
- $retval = $storage->import_gallery_from_fs($fs->join_paths($fs->get_document_root(), 'wp-content', $folder));
 
139
  if (!$retval) $retval = array('error' => "Could not import folder. No images found.");
140
  }
141
- catch (Exception $ex) {
142
- $retval['error'] = $ex->getMessage();
143
- }
 
 
 
 
144
  }
145
  else {
146
  $retval['error'] = "No folder specified";
147
  }
148
  }
149
  else {
150
- $retval['error'] = "No permissions to import folders. Try refreshing the page.";
151
  }
152
 
153
  return $retval;
4
  {
5
  function cookie_dump_action()
6
  {
7
+ foreach ($_COOKIE as $key => &$value) {
8
+ if (is_string($value)) $value = stripslashes($value);
9
+ }
10
+
11
+ return array('success' => 1, 'cookies' => $_COOKIE);
12
  }
13
 
14
  function upload_image_action()
62
  $error = TRUE;
63
  }
64
  }
65
+ catch (E_NggErrorException $ex) {
66
  $retval['error'] = $ex->getMessage();
67
  $error = TRUE;
68
  }
72
  $error = TRUE;
73
  }
74
  }
75
+ }
76
+ else {
77
+ $retval['error'] = "No permissions to upload images. Try refreshing the page or ensuring that your user account has sufficient roles/privileges.";
78
  $error = TRUE;
79
+ }
80
 
81
+ if ($error) return $retval;
82
+ else $retval['gallery_name'] = esc_html($gallery_name);
83
 
84
  return $retval;
85
  }
94
  {
95
  if (($dir = urldecode($this->param('dir')))) {
96
  $fs = $this->get_registry()->get_utility('I_Fs');
97
+ $root = NGG_IMPORT_ROOT;
98
 
99
  $browse_path = $fs->join_paths($root, $dir);
100
+ if (@file_exists($browse_path)) {
101
  $files = scandir($browse_path);
102
  natcasesort($files);
103
  if( count($files) > 2 ) { /* The 2 accounts for . and .. */
104
  $html[] = "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
105
  foreach( $files as $file ) {
106
+ $file_path = $fs->join_paths($browse_path, $file);
107
+ $rel_file_path = str_replace($root, '', $file_path);
108
+ if(@file_exists($file_path) && $file != '.' && $file != '..' && is_dir($file_path) ) {
109
  $html[] = "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($rel_file_path) . "/\">" . htmlentities($file) . "</a></li>";
110
  }
111
  }
122
  }
123
  }
124
  else {
125
+ $retval['error'] = "No permissions to browse folders. Try refreshing the page or ensuring that your user account has sufficient roles/privileges.";
126
  }
127
 
128
  return $retval;
136
  if ($this->validate_ajax_request('nextgen_upload_image'))
137
  {
138
  if (($folder = $this->param('folder'))) {
139
+ $storage = C_Gallery_Storage::get_instance();
140
+ $fs = C_Fs::get_instance();
141
  try {
142
+ $keep_files = $this->param('keep_location') == 'on';
143
+ $retval = $storage->import_gallery_from_fs($fs->join_paths(NGG_IMPORT_ROOT, $folder), false, !$keep_files);
144
  if (!$retval) $retval = array('error' => "Could not import folder. No images found.");
145
  }
146
+ catch (E_NggErrorException $ex) {
147
+ $retval['error'] = $ex->getMessage();
148
+ }
149
+ catch (Exception $ex) {
150
+ $retval['error'] = "An unexpected error occured.";
151
+ $retval['error_details'] = $ex->getMessage();
152
+ }
153
  }
154
  else {
155
  $retval['error'] = "No folder specified";
156
  }
157
  }
158
  else {
159
+ $retval['error'] = "No permissions to import folders. Try refreshing the page or ensuring that your user account has sufficient roles/privileges.";
160
  }
161
 
162
  return $retval;
products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.nextgen_addgallery_forms.php CHANGED
@@ -4,18 +4,16 @@ class A_NextGen_AddGallery_Forms extends Mixin
4
  {
5
  function initialize()
6
  {
7
- $forms = array(
8
- 'upload_images' => 'A_Upload_Images_Form',
9
- 'import_folder' => 'A_Import_Folder_Form'
10
- );
11
-
12
  $registry = $this->object->get_registry();
 
 
 
 
 
13
  foreach ($forms as $form => $adapter) {
14
  $registry->add_adapter('I_Form', $adapter, $form);
15
- $this->object->add_form(
16
- NEXTGEN_ADD_GALLERY_SLUG,
17
- $form
18
- );
19
  }
20
  }
21
  }
4
  {
5
  function initialize()
6
  {
7
+ $settings = C_NextGen_Settings::get_instance();
 
 
 
 
8
  $registry = $this->object->get_registry();
9
+
10
+ $forms = array('upload_images' => 'A_Upload_Images_Form');
11
+ if (!is_multisite() || (is_multisite() && $settings->get('wpmuImportFolder')))
12
+ $forms['import_folder'] = 'A_Import_Folder_Form';
13
+
14
  foreach ($forms as $form => $adapter) {
15
  $registry->add_adapter('I_Form', $adapter, $form);
16
+ $this->object->add_form(NGG_ADD_GALLERY_SLUG, $form);
 
 
 
17
  }
18
  }
19
  }
products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.nextgen_addgallery_pages.php CHANGED
@@ -4,12 +4,11 @@ class A_NextGen_AddGallery_Pages extends Mixin
4
  {
5
  function initialize()
6
  {
7
- $this->object->add(
8
- NEXTGEN_ADD_GALLERY_SLUG,
9
- 'A_NextGen_AddGallery_Controller',
10
- NGGFOLDER,
11
- true,
12
- 'nggallery-manage-gallery'
13
- );
14
  }
15
  }
4
  {
5
  function initialize()
6
  {
7
+ $this->object->add(NGG_ADD_GALLERY_SLUG, array(
8
+ 'adapter' => 'A_NextGen_AddGallery_Controller',
9
+ 'parent' => NGGFOLDER,
10
+ 'add_menu' => TRUE,
11
+ 'before' => 'nggallery-manage-gallery'
12
+ ));
 
13
  }
14
  }
products/photocrati_nextgen/modules/nextgen_addgallery_page/adapter.upload_images_form.php CHANGED
@@ -10,9 +10,9 @@ class A_Upload_Images_Form extends Mixin
10
 
11
  function enqueue_static_resources()
12
  {
13
- wp_enqueue_style('plupload.queue');
14
  wp_enqueue_script('browserplus');
15
- wp_enqueue_script('plupload.queue');
16
 
17
  }
18
 
@@ -47,10 +47,14 @@ class A_Upload_Images_Form extends Mixin
47
  $imgs->extensions = "jpg,jpeg,gif,png,JPG,JPEG,GIF,PNG";
48
  $retval[] = $imgs;
49
 
50
- $zips = new stdClass;
51
- $zips->title = "Zip files";
52
- $zips->extensions = "zip,ZIP";
53
- $retval[] = $zips;
 
 
 
 
54
 
55
  return $retval;
56
  }
10
 
11
  function enqueue_static_resources()
12
  {
13
+ wp_enqueue_style('ngg.plupload.queue');
14
  wp_enqueue_script('browserplus');
15
+ wp_enqueue_script('ngg.plupload.queue');
16
 
17
  }
18
 
47
  $imgs->extensions = "jpg,jpeg,gif,png,JPG,JPEG,GIF,PNG";
48
  $retval[] = $imgs;
49
 
50
+ $settings = C_NextGen_Settings::get_instance();
51
+ if (!is_multisite() || (is_multisite() && $settings->get('wpmuZipUpload')))
52
+ {
53
+ $zips = new stdClass;
54
+ $zips->title = "Zip files";
55
+ $zips->extensions = "zip,ZIP";
56
+ $retval[] = $zips;
57
+ }
58
 
59
  return $retval;
60
  }
products/photocrati_nextgen/modules/nextgen_addgallery_page/module.nextgen_addgallery_page.php CHANGED
@@ -5,7 +5,7 @@
5
  }
6
  **/
7
 
8
- define('NEXTGEN_ADD_GALLERY_SLUG', 'ngg_addgallery');
9
 
10
  class M_NextGen_AddGallery_Page extends C_Base_Module
11
  {
@@ -15,7 +15,7 @@ class M_NextGen_AddGallery_Page extends C_Base_Module
15
  'photocrati-nextgen_addgallery_page',
16
  'NextGEN Add Gallery Page',
17
  'Provides admin page for adding a gallery and uploading images',
18
- '0.1',
19
  'http://www.nextgen-gallery.com',
20
  'Photocrati Media',
21
  'http://www.photocrati.com'
@@ -50,12 +50,14 @@ class M_NextGen_AddGallery_Page extends C_Base_Module
50
  {
51
  if (is_admin()) {
52
  $router = $this->_get_registry()->get_utility('I_Router');
53
- wp_register_script('plupload.queue', $router->get_static_url('photocrati-nextgen_addgallery_page#plupload_queue/jquery.plupload.queue.js'), array('plupload-all'));
54
- wp_register_style('plupload.queue', $router->get_static_url('photocrati-nextgen_addgallery_page#plupload_queue/css/jquery.plupload.queue.css'));
 
 
 
55
  wp_register_style('nextgen_addgallery_page', $router->get_static_url('photocrati-nextgen_addgallery_page#styles.css'));
56
  wp_register_script('jquery.filetree', $router->get_static_url('photocrati-nextgen_addgallery_page#jquery.filetree/jquery.filetree.js'), array('jquery'));
57
  wp_register_style('jquery.filetree', $router->get_static_url('photocrati-nextgen_addgallery_page#jquery.filetree/jquery.filetree.css'));
58
- wp_register_script('browserplus', 'http://bp.yahooapis.com/2.4.21/browserplus-min.js');
59
  }
60
  }
61
  }
5
  }
6
  **/
7
 
8
+ define('NGG_ADD_GALLERY_SLUG', 'ngg_addgallery');
9
 
10
  class M_NextGen_AddGallery_Page extends C_Base_Module
11
  {
15
  'photocrati-nextgen_addgallery_page',
16
  'NextGEN Add Gallery Page',
17
  'Provides admin page for adding a gallery and uploading images',
18
+ '0.5',
19
  'http://www.nextgen-gallery.com',
20
  'Photocrati Media',
21
  'http://www.photocrati.com'
50
  {
51
  if (is_admin()) {
52
  $router = $this->_get_registry()->get_utility('I_Router');
53
+ wp_register_script('browserplus', 'http://bp.yahooapis.com/2.4.21/browserplus-min.js');
54
+ wp_register_script('ngg.plupload.moxie', $router->get_static_url('photocrati-nextgen_addgallery_page#plupload-2.1.1/moxie.min.js'));
55
+ wp_register_script('ngg.plupload.full', $router->get_static_url('photocrati-nextgen_addgallery_page#plupload-2.1.1/plupload.full.min.js'), array('ngg.plupload.moxie'));
56
+ wp_register_script('ngg.plupload.queue', $router->get_static_url('photocrati-nextgen_addgallery_page#plupload-2.1.1/jquery.plupload.queue/jquery.plupload.queue.min.js'), array('ngg.plupload.full'));
57
+ wp_register_style('ngg.plupload.queue', $router->get_static_url('photocrati-nextgen_addgallery_page#plupload-2.1.1/jquery.plupload.queue/css/jquery.plupload.queue.css'));
58
  wp_register_style('nextgen_addgallery_page', $router->get_static_url('photocrati-nextgen_addgallery_page#styles.css'));
59
  wp_register_script('jquery.filetree', $router->get_static_url('photocrati-nextgen_addgallery_page#jquery.filetree/jquery.filetree.js'), array('jquery'));
60
  wp_register_style('jquery.filetree', $router->get_static_url('photocrati-nextgen_addgallery_page#jquery.filetree/jquery.filetree.css'));
 
61
  }
62
  }
63
  }
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/jquery.filetree/connectors/jqueryFileTree.php DELETED
@@ -1,36 +0,0 @@
1
- <?php
2
- //
3
- // jQuery File Tree PHP Connector
4
- //
5
- // Version 1.01
6
- //
7
- // Cory S.N. LaViska
8
- // A Beautiful Site (http://abeautifulsite.net/)
9
- // 24 March 2008
10
- //
11
- // History:
12
- //
13
- // 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
14
- // 1.00 - released (24 March 2008)
15
- //
16
- // Output a list of files for jQuery File Tree
17
- //
18
-
19
- $_POST['dir'] = urldecode($_POST['dir']);
20
-
21
- if( file_exists($root . $_POST['dir']) ) {
22
- $files = scandir($root . $_POST['dir']);
23
- natcasesort($files);
24
- if( count($files) > 2 ) { /* The 2 accounts for . and .. */
25
- echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
26
- // All dirs
27
- foreach( $files as $file ) {
28
- if( file_exists($root . $_POST['dir'] . $file) && $file != '.' && $file != '..' && is_dir($root . $_POST['dir'] . $file) ) {
29
- echo "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($_POST['dir'] . $file) . "/\">" . htmlentities($file) . "</a></li>";
30
- }
31
- }
32
- echo "</ul>";
33
- }
34
- }
35
-
36
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/Moxie.swf ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/Moxie.xap ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ar.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Arabic (ar)
2
+ plupload.addI18n({"Stop Upload":"أيقاف التحميل","Upload URL might be wrong or doesn't exist.":"عنوان التحميل ربما يكون خاطئ أو غير متوفر","tb":"تيرابايت","Size":"الحجم","Close":"أغلاق","Init error.":"خطأ في تهيئة","Add files to the upload queue and click the start button.":"أضف ملفات إلى القائمة إنتظار التحميل ثم أضغط على زر البداية","Filename":"أسم الملف","Image format either wrong or not supported.":"صيغة الصورة أما خطاء أو غير مدعومه","Status":"الحالة","HTTP Error.":"خطأ في برتوكول نقل الملفات","Start Upload":"أبدا التحميل","mb":"ميجابايت","kb":"كيلوبايت","Duplicate file error.":"خطاء في تكرار الملف","File size error.":"خطأ في حجم الملف","N/A":"لا شي","gb":"جيجابايت","Error: Invalid file extension:":"خطاء : أمتداد الملف غير صالح :","Select files":"أختر الملفات","%s already present in the queue.":"%s الملف موجود بالفعل في قائمة الانتظار","File: %s":"ملف: %s","b":"بايت","Uploaded %d/%d files":"تحميل %d/%d ملف","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"العناصر المقبوله لتحميل هي %d ملف في هذا الوقت. الملفات الاضافية أزيلة.","%d files queued":"%d الملفات في قائمة الانتظار","File: %s, size: %d, max file size: %d":"ملف: %s, أقصى حجم للملف: %d, حجم: %d","Drag files here.":"سحب الملف هنا","Runtime ran out of available memory.":"الذاكرة المتوفره أنتهت لمدة التشغيل","File count error.":"خطاء في عد الملفات","File extension error.":"خطأ في أمتداد الملف","Error: File too large:":" خطاء : حجم الملف كبير :","Add Files":"أضف ملفات"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/bs.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Bosnian (bs)
2
+ plupload.addI18n({"Stop Upload":"Prekini dodavanje","Upload URL might be wrong or doesn't exist.":"URL za dodavanje je neispravan ili ne postoji.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Inicijalizacijska greška.","Add files to the upload queue and click the start button.":"Dodajte datoteke u red i kliknite na dugme za pokretanje.","Filename":"Naziv datoteke","Image format either wrong or not supported.":"Format slike je neispravan ili nije podržan.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Započni dodavanje","mb":"mb","kb":"kb","Duplicate file error.":"Dupla datoteka.","File size error.":"Greška u veličini datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Greška! Neispravan ekstenzija datoteke:","Select files":"Odaberite datoteke","%s already present in the queue.":"%s se već nalazi u redu.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Dodano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Dodavanje trenutno dozvoljava samo %d datoteka istovremeno. Dodatne datoteke su uklonjene.","%d files queued":"%d datoteka čeka","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje.","Runtime ran out of available memory.":"Nema više dostupne memorije.","File count error.":"Greška u brojanju datoeka.","File extension error.":"Greška u ekstenziji datoteke.","Error: File too large:":"Greška! Datoteka je prevelika:","Add Files":"Dodaj datoteke"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ca.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Catalan (ca)
2
+ plupload.addI18n({"Stop Upload":"","Upload URL might be wrong or doesn't exist.":"","tb":"","Size":"","Close":"","Init error.":"","Add files to the upload queue and click the start button.":"","Filename":"","Image format either wrong or not supported.":"","Status":"","HTTP Error.":"","Start Upload":"","mb":"","kb":"","Duplicate file error.":"","File size error.":"","N/A":"","gb":"","Error: Invalid file extension:":"","Select files":"","%s already present in the queue.":"","File: %s":"","b":"","Uploaded %d/%d files":"","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"","File: %s, size: %d, max file size: %d":"","Drag files here.":"","Runtime ran out of available memory.":"","File count error.":"","File extension error.":"","Error: File too large:":"","Add Files":""});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cs.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Czech (cs)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Velikost","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Přidejte soubory do fronty a pak spusťte nahrávání.","Filename":"Název souboru","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Spustit nahrávání","mb":"","kb":"","Duplicate file error.":"","File size error.":"File size error.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Vyberte soubory","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Nahráno %d/%d souborů","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Sem přetáhněte soubory.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Přidat soubory"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/cy.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Welsh (cy)
2
+ plupload.addI18n({"Stop Upload":"Atal Lanlwytho","Upload URL might be wrong or doesn't exist.":"URL y lanlwythiad ynb anghywir neu ddim yn bodoli.","tb":"tb","Size":"Maint","Close":"Cau","Init error.":"Gwall cych.","Add files to the upload queue and click the start button.":"Ychwanegwch ffeiliau i'r ciw lanlwytho a chlicio'r botwm dechrau.","Filename":"Enw'r ffeil","Image format either wrong or not supported.":"Fformat delwedd yn anghywir neu heb ei gynnal.","Status":"Statws","HTTP Error.":"Gwall HTTP.","Start Upload":"Dechrau Lanlwytho","mb":"mb","kb":"kb","Duplicate file error.":"Gwall ffeil ddyblyg.","File size error.":"Gwall maint ffeil.","N/A":"Dd/A","gb":"gb","Error: Invalid file extension:":"Gwall: estyniad ffeil annilys:","Select files":"Dewis ffeiliau","%s already present in the queue.":"%s yn y ciw yn barod.","File: %s":"Ffeil: %s","b":"b","Uploaded %d/%d files":"Lanlwythwyd %d/%d ffeil","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Mae'r elfen lanlwytho yn derbyn %d ffeil ar y tro. Caiff ffeiliau ychwanegol eu tynnu.","%d files queued":"%d ffeil mewn ciw","File: %s, size: %d, max file size: %d":"Ffeil: %s, maint: %d, maint mwyaf ffeil: %d","Drag files here.":"Llusgwch ffeiliau yma.","Runtime ran out of available memory.":"Allan o gof.","File count error.":"Gwall cyfri ffeiliau.","File extension error.":"Gwall estyniad ffeil.","Error: File too large:":"Gwall: Ffeil yn rhy fawr:","Add Files":"Ychwanegu Ffeiliau"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/da.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Danish (da)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Størrelse","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Tilføj filer til køen","Filename":"Filnavn","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"File size error.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Vælg filer","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Træk filer her.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/de.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // German (de)
2
+ plupload.addI18n({"Stop Upload":"Hochladen stoppen","Upload URL might be wrong or doesn't exist.":"Upload-URL ist falsch oder existiert nicht.","tb":"TB","Size":"Gr&ouml;&szlig;e","Close":"Schließen","Init error.":"Initialisierungsfehler","Add files to the upload queue and click the start button.":"Dateien hinzuf&uuml;gen und auf 'Hochladen' klicken.","Filename":"Dateiname","Image format either wrong or not supported.":"Bildformat falsch oder nicht unterst&uuml;tzt.","Status":"Status","HTTP Error.":"HTTP-Fehler","Start Upload":"Upload beginnen","mb":"MB","kb":"kB","Duplicate file error.":"","File size error.":"Fehler bei Dateigr&ouml;ße","N/A":"Nicht verf&uuml;gbar","gb":"GB","Error: Invalid file extension:":"Fehler: Ungültige Dateiendung:","Select files":"Dateien hochladen","%s already present in the queue.":"","File: %s":"Datei: %s","b":"B","Uploaded %d/%d files":"%d/%d Dateien sind hochgeladen","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Der Uploader akzeptiert nur %d Datei(en) pro Durchgang. Überzählige Dateien wurden abgetrennt.","%d files queued":"%d Dateien in der Warteschlange","File: %s, size: %d, max file size: %d":"Datei: %s, Größe: %d, maximale Dateigröße: %d","Drag files here.":"Ziehen Sie die Dateien hier hin","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"Fehler bei Dateiendung","Error: File too large:":"Fehler: Datei zu groß:","Add Files":"Dateien hinzufügen"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/el.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Greek (el)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Μέγεθος","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Προσθήκη αρχείων στην ουρά μεταφόρτωσης","Filename":"Όνομα αρχείου","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Κατάσταση","HTTP Error.":"HTTP Error.","Start Upload":"Εκκίνηση μεταφόρτωσης","mb":"","kb":"","Duplicate file error.":"","File size error.":"File size error.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Επιλέξτε Αρχεία","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Ανέβηκαν %d/%d αρχεία","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Σύρετε αρχεία εδώ","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Προσθέστε αρχεία"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/en.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // English (en)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Size","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Add files to the upload queue and click the start button.","Filename":"Filename","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"mb","kb":"kb","Duplicate file error.":"Duplicate file error.","File size error.":"File size error.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Select files","%s already present in the queue.":"%s already present in the queue.","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"File: %s, size: %d, max file size: %d","Drag files here.":"Drag files here.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/es.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Spanish (es)
2
+ plupload.addI18n({"Stop Upload":"Detener Subida.","Upload URL might be wrong or doesn't exist.":"URL de carga inexistente.","tb":"TB","Size":"Tamaño","Close":"Cerrar","Init error.":"Error de inicialización.","Add files to the upload queue and click the start button.":"Agregue archivos a la lista de subida y pulse clic en el botón de Iniciar carga","Filename":"Nombre de archivo","Image format either wrong or not supported.":"Formato de imagen no soportada.","Status":"Estado","HTTP Error.":"Error de HTTP.","Start Upload":"Iniciar carga","mb":"MB","kb":"KB","Duplicate file error.":"Error, archivo duplicado","File size error.":"Error de tamaño de archivo.","N/A":"No disponible","gb":"GB","Error: Invalid file extension:":"Error: Extensión de archivo inválida:","Select files":"Elija archivos","%s already present in the queue.":"%s ya se encuentra en la lista.","File: %s":"Archivo: %s","b":"B","Uploaded %d/%d files":"Subidos %d/%d archivos","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Se aceptan sólo %d archivo(s) al tiempo. Más, no se tienen en cuenta.","%d files queued":"%d archivos en cola.","File: %s, size: %d, max file size: %d":"Archivo: %s, tamaño: %d, tamaño máximo de archivo: %d","Drag files here.":"Arrastre archivos aquí","Runtime ran out of available memory.":"No hay memoria disponible.","File count error.":"Error en contador de archivos.","File extension error.":"Error de extensión de archivo.","Error: File too large:":"Error: archivo demasiado grande:","Add Files":"Agregar archivos"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/et.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Estonian (et)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Üleslaadimise URL võib olla vale või seda pole.","tb":"","Size":"Suurus","Close":"Sulge","Init error.":"Lähtestamise viga.","Add files to the upload queue and click the start button.":"Lisa failid üleslaadimise järjekorda ja klõpsa alustamise nupule.","Filename":"Failinimi","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Olek","HTTP Error.":"HTTP ühenduse viga.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Failisuuruse viga.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Vali faile","%s already present in the queue.":"","File: %s":"Fail: %s","b":"","Uploaded %d/%d files":"Üles laaditud %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Üleslaadimise element saab vastu võtta ainult %d faili ühe korraga. Ülejäänud failid jäetakse laadimata.","%d files queued":"Järjekorras on %d faili","File: %s, size: %d, max file size: %d":"","Drag files here.":"Lohista failid siia.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Failide arvu viga.","File extension error.":"Faililaiendi viga.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fa.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Persian (fa)
2
+ plupload.addI18n({"Stop Upload":"توقف انتقال","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"سایز","Close":"بستن","Init error.":"خطا در استارت اسکریپت","Add files to the upload queue and click the start button.":"اضافه کنید فایل ها را به صف آپلود و دکمه شروع را کلیک کنید.","Filename":"نام فایل","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"وضعیت","HTTP Error.":"HTTP خطای","Start Upload":"شروع انتقال","mb":"","kb":"","Duplicate file error.":"","File size error.":"خطای سایز فایل","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"انتخاب فایل","%s already present in the queue.":"","File: %s":" فایل ها : %s","b":"","Uploaded %d/%d files":"منتقل شد %d/%d از فایلها","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"عنصر بارگذار فقط %d فایل رو در یک زمان می پذیرد. سایر فایل ها مجرد از این موضوع هستند.","%d files queued":"%d فایل در صف","File: %s, size: %d, max file size: %d":"","Drag files here.":"بکشید فایل ها رو به اینجا","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"خطای تعداد فایل","File extension error.":"خطا پیشوند فایل","Error: File too large:":"Error: File too large:","Add Files":"افزودن فایل"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fi.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Finnish (fi)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Koko","Close":"Sulje","Init error.":"Init virhe.","Add files to the upload queue and click the start button.":"Lisää tiedostoja latausjonoon ja klikkaa aloita-nappia.","Filename":"Tiedostonimi","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Tila","HTTP Error.":"HTTP virhe.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Tiedostokokovirhe.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Valitse tiedostoja","%s already present in the queue.":"","File: %s":"Tiedosto: %s","b":"","Uploaded %d/%d files":"Ladattu %d/%d tiedostoa","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Latauselementti sallii ladata vain %d tiedosto(a) kerrallaan. Ylimääräiset tiedostot ohitettiin.","%d files queued":"%d tiedostoa jonossa","File: %s, size: %d, max file size: %d":"","Drag files here.":"Raahaa tiedostot tänne.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Tiedostolaskentavirhe.","File extension error.":"Tiedostopäätevirhe.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/fr.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // French (fr)
2
+ plupload.addI18n({"Stop Upload":"Arrêter l'envoi.","Upload URL might be wrong or doesn't exist.":"L'URL d'envoi est soit erronée soit n'existe pas.","tb":"To","Size":"Taille","Close":"Fermer","Init error.":"Erreur d'initialisation.","Add files to the upload queue and click the start button.":"Ajoutez des fichiers à la file d'attente de téléchargement et appuyez sur le bouton 'Démarrer l'envoi'","Filename":"Nom du fichier","Image format either wrong or not supported.":"Le format d'image est soit erroné soit pas géré.","Status":"État","HTTP Error.":"Erreur HTTP.","Start Upload":"Démarrer l'envoi","mb":"Mo","kb":"Ko","Duplicate file error.":"Erreur: Fichier à double.","File size error.":"Erreur de taille de fichier.","N/A":"Non applicable","gb":"Go","Error: Invalid file extension:":"Erreur: Extension de fichier non valide:","Select files":"Sélectionnez les fichiers","%s already present in the queue.":"%s déjà présent dans la file d'attente.","File: %s":"Fichier: %s","b":"o","Uploaded %d/%d files":"%d fichiers sur %d ont été envoyés","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Que %d fichier(s) peuvent être envoyé(s) à la fois. Les fichiers supplémentaires ont été ignorés.","%d files queued":"%d fichiers en attente","File: %s, size: %d, max file size: %d":"Fichier: %s, taille: %d, taille max. d'un fichier: %d","Drag files here.":"Déposez les fichiers ici.","Runtime ran out of available memory.":"Le traitement a manqué de mémoire disponible.","File count error.":"Erreur: Nombre de fichiers.","File extension error.":"Erreur d'extension de fichier","Error: File too large:":"Erreur: Fichier trop volumineux:","Add Files":"Ajouter des fichiers"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/he.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Hebrew (he)
2
+ plupload.addI18n({"Stop Upload":"בטל העלאה","Upload URL might be wrong or doesn't exist.":"כתובת URL שגויה או לא קיימת.","tb":"tb","Size":"גודל","Close":"סגור","Init error.":"שגיאת איתחול","Add files to the upload queue and click the start button.":"הוסף קבצים לרשימה ולחץ על כפתור שליחה להתחלת פעולות העלאה","Filename":"שם קובץ","Image format either wrong or not supported.":"תמונה פגומה או סוג תמונה לא נתמך","Status":"אחוז","HTTP Error.":"שגיאת פרוטוקול","Start Upload":"שליחה","mb":"MB","kb":"KB","Duplicate file error.":"קובץ כפול","File size error.":"גודל קובץ חורג מהמותר","N/A":"שגיאה","gb":"GB","Error: Invalid file extension:":"שגיאה: סוג קובץ לא נתמך:","Select files":"בחר קבצים","%s already present in the queue.":"%sקובץ נמצא כבר ברשימת הקבצים.","File: %s":"קובץ: %s","b":"B","Uploaded %d/%d files":"מעלה: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"אלמנטי ההעלאה מקבלים רק %d קובץ(ים) בפעם אחת. קבצים נוספים הוסרו.","%d files queued":"%d קבצים נותרו","File: %s, size: %d, max file size: %d":"קובץ: %s, גודל: %d, גודל מקסימלי: %d","Drag files here.":"גרור קבצים לכאן","Runtime ran out of available memory.":"שגיאת מחסור בזיכרון","File count error.":"שגיאת מספר קבצים","File extension error.":"קובץ זה לא נתמך","Error: File too large:":"שגיאה: קובץ חורג מהגודל המותר:","Add Files":"הוסף קבצים"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hr.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Croatian (hr)
2
+ plupload.addI18n({"Stop Upload":"Zaustavi upload.","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Veličina","Close":"Zatvori","Init error.":"Greška inicijalizacije.","Add files to the upload queue and click the start button.":"Dodajte datoteke u listu i kliknite Upload.","Filename":"Ime datoteke","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP greška.","Start Upload":"Pokreni upload.","mb":"mb","kb":"kb","Duplicate file error.":"Pogreška dvostruke datoteke.","File size error.":"Greška veličine datoteke.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Pogreška: Nevažeći nastavak datoteke:","Select files":"Odaberite datoteke:","%s already present in the queue.":"%s je već prisutan u listi čekanja.","File: %s":"Datoteka: %s","b":"b","Uploaded %d/%d files":"Uploadano %d/%d datoteka","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d datoteka na čekanju.","File: %s, size: %d, max file size: %d":"Datoteka: %s, veličina: %d, maksimalna veličina: %d","Drag files here.":"Dovucite datoteke ovdje","Runtime ran out of available memory.":"Runtime aplikaciji je ponestalo memorije.","File count error.":"Pogreška u broju datoteka.","File extension error.":"Pogreška u nastavku datoteke.","Error: File too large:":"Pogreška: Datoteka je prevelika:","Add Files":"Dodaj datoteke"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hu.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Hungarian (hu)
2
+ plupload.addI18n({"Stop Upload":"Feltöltés leállítása","Upload URL might be wrong or doesn't exist.":"A feltöltő URL hibás vagy nem létezik.","tb":"","Size":"Méret","Close":"Bezárás","Init error.":"Init hiba.","Add files to the upload queue and click the start button.":"A fájlok feltöltési sorhoz való hozzáadása után az Indítás gombra kell kattintani.","Filename":"Fájlnév","Image format either wrong or not supported.":"Rossz vagy nem támogatott képformátum.","Status":"Állapot","HTTP Error.":"HTTP-hiba.","Start Upload":"Feltöltés indítása","mb":"","kb":"","Duplicate file error.":"Duplikáltfájl-hiba.","File size error.":"Hibás fájlméret.","N/A":"Nem elérhető","gb":"","Error: Invalid file extension:":"Hiba: érvénytelen fájlkiterjesztés:","Select files":"Fájlok kiválasztása","%s already present in the queue.":"%s már szerepel a listában.","File: %s":"Fájl: %s","b":"b","Uploaded %d/%d files":"Feltöltött fájlok: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"A feltöltés egyszerre csak %d fájlt fogad el, a többi fájl nem lesz feltöltve.","%d files queued":"%d fájl sorbaállítva","File: %s, size: %d, max file size: %d":"Fájl: %s, méret: %d, legnagyobb fájlméret: %d","Drag files here.":"Ide lehet húzni a fájlokat.","Runtime ran out of available memory.":"Futásidőben elfogyott a rendelkezésre álló memória.","File count error.":"A fájlok számával kapcsolatos hiba.","File extension error.":"Hibás fájlkiterjesztés.","Error: File too large:":"Hiba: a fájl túl nagy:","Add Files":"Fájlok hozzáadása"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/hy.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Armenian (hy)
2
+ plupload.addI18n({"Stop Upload":"Կանգնեցնել","Upload URL might be wrong or doesn't exist.":"Ավեցաված URL-ը սխալ է կամ գոյություն չունի։","tb":"տբ","Size":"Չափ","Close":"Փակել","Init error.":"Ստեղծման սխալ","Add files to the upload queue and click the start button.":"Ավելացրեք ֆայլեր ցուցակում և սեղմեք \"Վերբեռնել\"։","Filename":"Ֆայլի անուն","Image format either wrong or not supported.":"Նկարի ֆորմատը սխալ է կամ չի ընդունվում։","Status":"","HTTP Error.":"HTTP սխալ","Start Upload":"Վերբեռնել","mb":"մբ","kb":"կբ","Duplicate file error.":"Ֆայլի կրկնման սխալ","File size error.":"Ֆայլի չափի սխալ","N/A":"N/A","gb":"գբ","Error: Invalid file extension:":"Սխալ։ Ֆայլի ընդլայնումը սխալ է։","Select files":"Ընտրեք ֆայլերը","%s already present in the queue.":"%s ֆայլը արդեն ավելացված է ցուցակում.","File: %s":"Ֆայլ: %s","b":"բ","Uploaded %d/%d files":"Վերբեռնվել են %d/%d ֆայլերը","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"ցուցակում կա %d ֆայլ","File: %s, size: %d, max file size: %d":"Ֆայլ: %s, չափ: %d, ֆայլի մաքսիմում չափ: %d","Drag files here.":"Տեղափոխեք ֆայլերը այստեղ","Runtime ran out of available memory.":"","File count error.":"Ֆայլերի քանակի սխալ","File extension error.":"Ֆայլի ընդլայնման սխալ","Error: File too large:":"Սխալ։ Ֆայլի չափը մեծ է։","Add Files":"Ավելացնել ֆայլեր"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/id.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Indonesian (id)
2
+ plupload.addI18n({"Stop Upload":"Hentikan Upload","Upload URL might be wrong or doesn't exist.":"Alamat URL untuk upload tidak benar atau tidak ada","tb":"tb","Size":"Ukuran","Close":"Tutup","Init error.":"Kesalahan pada Init","Add files to the upload queue and click the start button.":"Tambahkan file kedalam antrian upload dan klik tombol Mulai","Filename":"Nama File","Image format either wrong or not supported.":"Kesalahan pada jenis gambar atau jenis file tidak didukung","Status":"Status","HTTP Error.":"HTTP Bermasalah","Start Upload":"Mulai Upload","mb":"mb","kb":"kb","Duplicate file error.":"Terjadi duplikasi file","File size error.":"Kesalahan pada ukuran file","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Kesalahan: Ekstensi file tidak dikenal","Select files":"Pilih file","%s already present in the queue.":"%s sudah ada dalam daftar antrian","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"File terupload %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Tempat untuk upload hanya menerima %d file(s) dalam setiap upload. File lainnya tidak akan disertakan","%d files queued":"%d file dalam antrian","File: %s, size: %d, max file size: %d":"File: %s, ukuran: %d, maksimum ukuran file: %d","Drag files here.":"Tarik file kesini","Runtime ran out of available memory.":"Tidak cukup memori","File count error.":"Kesalahan pada jumlah file","File extension error.":"Kesalahan pada ekstensi file","Error: File too large:":"Kesalahan: File terlalu besar","Add Files":"Tambah File"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/it.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Italian (it)
2
+ plupload.addI18n({"Stop Upload":"Ferma Upload","Upload URL might be wrong or doesn't exist.":"URL di Upload errata o non esistente","tb":"tb","Size":"Dimensione","Close":"Chiudi","Init error.":"Errore inizializzazione.","Add files to the upload queue and click the start button.":"Aggiungi i file alla coda di caricamento e clicca il pulsante di avvio.","Filename":"Nome file","Image format either wrong or not supported.":"Formato immagine errato o non supportato.","Status":"Stato","HTTP Error.":"Errore HTTP.","Start Upload":"Inizia Upload","mb":"mb","kb":"kb","Duplicate file error.":"Errore file duplicato.","File size error.":"Errore dimensione file.","N/A":"N/D","gb":"gb","Error: Invalid file extension:":"Errore: Estensione file non valida:","Select files":"Seleziona i files","%s already present in the queue.":"%s già presente nella coda.","File: %s":"File: %s","b":"byte","Uploaded %d/%d files":"Caricati %d/%d file","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d file in coda","File: %s, size: %d, max file size: %d":"File: %s, dimensione: %d, dimensione max file: %d","Drag files here.":"Trascina i files qui.","Runtime ran out of available memory.":"Runtime ha esaurito la memoria disponibile.","File count error.":"File count error.","File extension error.":"Errore estensione file.","Error: File too large:":"Errore: File troppo grande:","Add Files":"Aggiungi file"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ja.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Japanese (ja)
2
+ plupload.addI18n({"Stop Upload":"アップロード停止","Upload URL might be wrong or doesn't exist.":"アップロード先の URL が存在しません","tb":"","Size":"サイズ","Close":"閉じる","Init error.":"イニシャライズエラー","Add files to the upload queue and click the start button.":"ファイルをアップロードキューに追加してスタートボタンをクリックしてください","Filename":"ファイル名","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"ステータス","HTTP Error.":"HTTP エラー","Start Upload":"アップロード","mb":"","kb":"","Duplicate file error.":"","File size error.":"ファイルサイズエラー","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"ファイル選択","%s already present in the queue.":"","File: %s":"ファイル: %s","b":"","Uploaded %d/%d files":"アップロード中 %d/%d ファイル","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"アップロード可能なファイル数は %d です。余分なファイルは削除されました","%d files queued":"%d ファイルが追加されました","File: %s, size: %d, max file size: %d":"","Drag files here.":"ここにファイルをドラッグ","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"ファイル数エラー","File extension error.":"ファイル拡張子エラー","Error: File too large:":"Error: File too large:","Add Files":"ファイルを追加"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ka.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Georgian (ka)
2
+ plupload.addI18n({"Stop Upload":"ატვირთვის შეჩერება","Upload URL might be wrong or doesn't exist.":"ატვირთვის მისამართი არასწორია ან არ არსებობს.","tb":"ტბ","Size":"ზომა","Close":"დავხუროთ","Init error.":"ინიციალიზაციის შეცდომა.","Add files to the upload queue and click the start button.":"დაამატეთ ფაილები და დააჭირეთ ღილაკს - ატვირთვა.","Filename":"ფაილის სახელი","Image format either wrong or not supported.":"ფაილის ფორმატი არ არის მხარდაჭერილი ან არასწორია.","Status":"სტატუსი","HTTP Error.":"HTTP შეცდომა.","Start Upload":"ატვირთვა","mb":"მბ","kb":"კბ","Duplicate file error.":"ესეთი ფაილი უკვე დამატებულია.","File size error.":"ფაილის ზომა დაშვებულზე დიდია.","N/A":"N/A","gb":"გბ","Error: Invalid file extension:":"შეცდომა: ფაილს აქვს არასწორი გაფართოება.","Select files":"ფაილების მონიშვნა","%s already present in the queue.":"%s უკვე დამატებულია.","File: %s":"ფაილი: %s","b":"ბ","Uploaded %d/%d files":"ატვირთულია %d/%d ფაილი","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"ერთდროულად დაშვებულია მხოლოდ %d ფაილის დამატება.","%d files queued":"რიგშია %d ფაილი","File: %s, size: %d, max file size: %d":"ფაილი: %s, ზომა: %d, მაქსიმალური დაშვებული ზომა: %d","Drag files here.":"ჩააგდეთ ფაილები აქ.","Runtime ran out of available memory.":"ხელმისაწვდომი მეხსიერება გადაივსო.","File count error.":"აღმოჩენილია ზედმეტი ფაილები.","File extension error.":"ფაილის ფორმატი დაშვებული არ არის.","Error: File too large:":"შეცდომა: ფაილი ზედმეტად დიდია.","Add Files":"დაამატეთ ფაილები"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/kk.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Kazakh (kk)
2
+ plupload.addI18n({"Stop Upload":"Жүктеуді тоқтату","Upload URL might be wrong or doesn't exist.":"Жүктеуді қабылдаушы URL қате не мүлдем көрсетілмеген.","tb":"тб","Size":"Өлшемі","Close":"Жабу","Init error.":"Инициализация қатесі.","Add files to the upload queue and click the start button.":"Жүктеу кезегіне файлдар қосып, Бастау кнопкасын басыңыз.","Filename":"Файл аты","Image format either wrong or not supported.":"Сурет форматы қате немесе оның қолдауы жоқ.","Status":"Күйі","HTTP Error.":"HTTP қатесі.","Start Upload":"Жүктеуді бастау","mb":"мб","kb":"кб","Duplicate file error.":"Файл қайталамасының қатесі.","File size error.":"Файл өлшемінің қатесі.","N/A":"Қ/Ж","gb":"гб","Error: Invalid file extension:":"Қате: Файл кеңейтілуі қате:","Select files":"Файлдар таңдаңыз","%s already present in the queue.":"%s файлы кезекте бұрыннан бар.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Жүктелген: %d/%d файл","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Жүктеу элементі бір кезде %d файл ғана жүктей алады. Артық файлдар жүктелмейді.","%d files queued":"%d файл кезекке қойылды","File: %s, size: %d, max file size: %d":"Файл: %s, өлшемі: %d, макс. файл өлшемі: %d","Drag files here.":"Файлдарды мына жерге тастаңыз.","Runtime ran out of available memory.":"Орындау кезінде жады жетпей қалды.","File count error.":"Файл санының қатесі.","File extension error.":"Файл кеңейтілуінің қатесі.","Error: File too large:":"Қате: Файл мөлшері тым үлкен:","Add Files":"Файл қосу"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ko.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Korean (ko)
2
+ plupload.addI18n({"Stop Upload":"업로드 중지","Upload URL might be wrong or doesn't exist.":"업로드할 URL이 존재하지 않습니다","tb":"","Size":"크기","Close":"닫기","Init error.":"초기화 오류","Add files to the upload queue and click the start button.":"파일을 업로드 큐에 추가하여 시작 버튼을 클릭하십시오.","Filename":"파일 이름","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"상태","HTTP Error.":"HTTP 오류","Start Upload":"업로드","mb":"","kb":"","Duplicate file error.":"","File size error.":"파일 크기 오류","N/A":"N/A","gb":"","Error: Invalid file extension:":"오류 : 확장자가 허용되지 않습니다 :","Select files":"파일 선택","%s already present in the queue.":"","File: %s":"파일 % s","b":"","Uploaded %d/%d files":"업로드 중 % d / % d 파일","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"업로드 가능한 파일의 수는 % d입니다. 불필요한 파일은 삭제되었습니다","%d files queued":"% d 파일이 추가되었습니다","File: %s, size: %d, max file size: %d":"","Drag files here.":"여기에 파일을 드래그","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"이미지 : 오류","File extension error.":"파일 확장자 오류","Error: File too large:":"오류 : 크기가 너무 큽니다","Add Files":"파일 추가"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lt.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Lithuanian (lt)
2
+ plupload.addI18n({"Stop Upload":"Stabdyti įkėlimą","Upload URL might be wrong or doesn't exist.":"Klaidinga arba neegzistuojanti įkėlimo nuoroda.","tb":"tb","Size":"Dydis","Close":"Uždaryti","Init error.":"Įkrovimo klaida.","Add files to the upload queue and click the start button.":"Pridėkite bylas į įkėlimo eilę ir paspauskite starto mygtuką.","Filename":"Bylos pavadinimas","Image format either wrong or not supported.":"Paveiksliuko formatas klaidingas arba nebepalaikomas.","Status":"Statusas","HTTP Error.":"HTTP klaida.","Start Upload":"Pradėti įkėlimą","mb":"mb","kb":"kb","Duplicate file error.":"Pasikartojanti byla.","File size error.":"Netinkamas bylos dydis.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Klaida: Netinkamas bylos plėtinys:","Select files":"Žymėti bylas","%s already present in the queue.":"%s jau yra eilėje.","File: %s":"Byla: %s","b":"b","Uploaded %d/%d files":"Įkelta bylų: %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Vienu metu galima įkelti tik %d bylas(ų). Papildomos bylos buvo pašalintos.","%d files queued":"%d bylų eilėje","File: %s, size: %d, max file size: %d":"Byla: %s, dydis: %d, galimas dydis: %d","Drag files here.":"Padėti bylas čia.","Runtime ran out of available memory.":"Išeikvota darbinė atmintis.","File count error.":"Netinkamas bylų kiekis.","File extension error.":"Netinkamas pletinys.","Error: File too large:":"Klaida: Byla per didelė:","Add Files":"Pridėti bylas"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/lv.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Latvian (lv)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"terrabaiti","Size":"Izmērs","Close":"Aizvērt","Init error.":"Inicializācijas kļūda.","Add files to the upload queue and click the start button.":"Pieveinojiet failus rindai un klikšķiniet uz","Filename":"Faila nosaukums","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Statuss","HTTP Error.":"HTTP kļūda.","Start Upload":"Start Upload","mb":"megabaiti","kb":"kilobaiti","Duplicate file error.":"Atkārtota faila kļūda","File size error.":"Faila izmēra kļūda.","N/A":"N/A","gb":"gigabaiti","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Izvēlieties failus","%s already present in the queue.":"%s jau ir atrodams rindā.","File: %s":"Fails: %s","b":"baiti","Uploaded %d/%d files":"Augšupielādēti %d/%d faili","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Iespējams ielādēt tikai %d failus vienā reizē. Atlikušie faili netika pievienoti","%d files queued":"%d faili pievienoti rindai","File: %s, size: %d, max file size: %d":"Fails: %s, izmērs: %d, max faila izmērs: %d","Drag files here.":"Ievelciet failus šeit","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Failu skaita kļūda","File extension error.":"Faila paplašinājuma kļūda.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/nl.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Dutch (nl)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Grootte","Close":"Close","Init error.":"Initialisatie error.","Add files to the upload queue and click the start button.":"Voeg bestanden toe aan de wachtrij en druk op 'Start'.","Filename":"Bestandsnaam","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Bestandsgrootte Error.","N/A":"Niet beschikbaar","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Selecteer bestand(en):","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"%d/%d bestanden ge-upload","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Sleep bestanden hierheen.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"Ongeldig bestandstype.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pl.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Polish (pl)
2
+ plupload.addI18n({"Stop Upload":"Przerwij transfer.","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Rozmiar","Close":"Close","Init error.":"Błąd inicjalizacji.","Add files to the upload queue and click the start button.":"Dodaj pliki i kliknij 'Rozpocznij transfer'.","Filename":"Nazwa pliku","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"Błąd HTTP.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Plik jest zbyt duży.","N/A":"Nie dostępne","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Wybierz pliki:","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Wysłano %d/%d plików","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d plików w kolejce.","File: %s, size: %d, max file size: %d":"","Drag files here.":"Przeciągnij tu pliki","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"Nieobsługiwany format pliku.","Error: File too large:":"Error: File too large:","Add Files":"Dodaj pliki"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/pt_BR.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Portuguese (Brazil) (pt_BR)
2
+ plupload.addI18n({"Stop Upload":"Parar o envio","Upload URL might be wrong or doesn't exist.":"URL de envio está errada ou não existe","tb":"","Size":"Tamanho","Close":"Fechar","Init error.":"Erro inicializando.","Add files to the upload queue and click the start button.":"Adicione os arquivos abaixo e clique no botão \"Iniciar o envio\".","Filename":"Nome do arquivo","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"Erro HTTP.","Start Upload":"Iniciar o envio","mb":"","kb":"","Duplicate file error.":"","File size error.":"Tamanho de arquivo não permitido.","N/A":"N/D","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Escolha os arquivos","%s already present in the queue.":"","File: %s":"Arquivo: %s","b":"","Uploaded %d/%d files":"Enviado(s) %d/%d arquivo(s)","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Só são aceitos %d arquivos por vez. O que passou disso foi descartado.","%d files queued":"%d arquivo(s)","File: %s, size: %d, max file size: %d":"","Drag files here.":"Arraste os arquivos pra cá","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Erro na contagem dos arquivos","File extension error.":"Tipo de arquivo não permitido.","Error: File too large:":"Error: File too large:","Add Files":"Adicionar arquivo(s)"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ro.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Romanian (ro)
2
+ plupload.addI18n({"Stop Upload":"Oprește încărcarea","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Mărime","Close":"Închide","Init error.":"Eroare inițializare.","Add files to the upload queue and click the start button.":"Adaugă fișiere în lista apoi apasă butonul \"Începe încărcarea\".","Filename":"Nume fișier","Image format either wrong or not supported.":"Formatul de imagine ori este greșit ori nu este suportat.","Status":"Stare","HTTP Error.":"Eroare HTTP","Start Upload":"Începe încărcarea","mb":"mb","kb":"kb","Duplicate file error.":"Eroare duplicat fișier.","File size error.":"Eroare dimensiune fișier.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Eroare: Extensia fișierului este invalidă:","Select files":"Selectează fișierele","%s already present in the queue.":"%s există deja în lista de așteptare.","File: %s":"Fișier: %s","b":"b","Uploaded %d/%d files":"Fișiere încărcate %d/%d","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d fișiere listate","File: %s, size: %d, max file size: %d":"Fișier: %s, mărime: %d, mărime maximă: %d","Drag files here.":"Trage aici fișierele.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"Eroare numărare fișiere.","File extension error.":"Eroare extensie fișier.","Error: File too large:":"Eroare: Fișierul este prea mare:","Add Files":"Adaugă fișiere"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/ru.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Russian (ru)
2
+ plupload.addI18n({"Stop Upload":"Остановить Загрузку","Upload URL might be wrong or doesn't exist.":"Адрес заргузки неправильный или он не существует.","tb":"тб","Size":"Размер","Close":"Закрыть","Init error.":"Ошибка инициализации.","Add files to the upload queue and click the start button.":"Добавьте файлы в очередь и нажмите кнопку \"Загрузить файлы\".","Filename":"Имя файла","Image format either wrong or not supported.":"Формат картинки неправильный или он не поддерживается.","Status":"Статус","HTTP Error.":"Ошибка HTTP.","Start Upload":"Начать загрузку","mb":"мб","kb":"кб","Duplicate file error.":"Такой файл уже присутствует в очереди.","File size error.":"Неправильный размер файла.","N/A":"N/A","gb":"гб","Error: Invalid file extension:":"Ошибка: У файла неправильное расширение:","Select files":"Выберите файлы","%s already present in the queue.":"%s уже присутствует в очереди.","File: %s":"Файл: %s","b":"б","Uploaded %d/%d files":"Загружено %d/%d файлов","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Загрузочный элемент за раз принимает только %d файл(ов). Лишние файлы были отброшены.","%d files queued":"В очереди %d файл(ов)","File: %s, size: %d, max file size: %d":"Файл: %s, размер: %d, макс. размер файла: %d","Drag files here.":"Перетащите файлы сюда.","Runtime ran out of available memory.":"Рабочая среда превысила лимит достуной памяти.","File count error.":"Слишком много файлов.","File extension error.":"Неправильное расширение файла.","Error: File too large:":"Ошибка: Файл слишком большой:","Add Files":"Добавьте файлы"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sk.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Slovak (sk)
2
+ plupload.addI18n({"Stop Upload":"Zastaviť nahrávanie","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Veľkosť","Close":"Close","Init error.":"Chyba inicializácie.","Add files to the upload queue and click the start button.":"Pridajte súbory do zoznamu a potom spustite nahrávanie.","Filename":"Názov súboru","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Stav","HTTP Error.":"HTTP Chyba.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"Súbor je príliš veľký.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Vyberte súbory","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Nahraných %d/%d súborov","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d súborov pridaných do zoznamu","File: %s, size: %d, max file size: %d":"","Drag files here.":"Sem pretiahnite súbory.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"Chybný typ súboru.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sr.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Serbian (sr)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Veličina","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Dodajte fajlove u listu i kliknite na dugme Start.","Filename":"Naziv fajla","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Počni upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"File size error.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Izaberite fajlove","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Snimljeno %d/%d fajlova","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Prevucite fajlove ovde.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Dodaj fajlove"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/sv.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Swedish (sv)
2
+ plupload.addI18n({"Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"","Size":"Storlek","Close":"Close","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Lägg till filer till kön och tryck på start.","Filename":"Filnamn","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","mb":"","kb":"","Duplicate file error.":"","File size error.":"File size error.","N/A":"N/A","gb":"","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Välj filer","%s already present in the queue.":"","File: %s":"File: %s","b":"","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"","Drag files here.":"Dra filer hit","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","Error: File too large:":"Error: File too large:","Add Files":"Add Files"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/th_TH.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Thai (Thailand) (th_TH)
2
+ plupload.addI18n({"Stop Upload":"หยุดอัพโหลด","Upload URL might be wrong or doesn't exist.":"URL ของการอัพโหลดอาจจะผิดหรือไม่มีอยู่","tb":"เทราไบต์","Size":"ขนาด","Close":"ปิด","Init error.":"Init เกิดข้อผิดพลาด","Add files to the upload queue and click the start button.":"เพิ่มไฟล์ไปยังคิวอัพโหลดและคลิกที่ปุ่มเริ่ม","Filename":"ชื่อไฟล์","Image format either wrong or not supported.":"รูปแบบรูปภาพทั้งสองผิดหรือไม่รองรับ","Status":"สถานะ","HTTP Error.":"HTTP เกิดข้อผิดพลาด","Start Upload":"เริ่มอัพโหลด","mb":"เมกะไบต์","kb":"กิโลไบต์","Duplicate file error.":"ไฟล์ที่ซ้ำกันเกิดข้อผิดพลาด","File size error.":"ขนาดไฟล์เกิดข้อผิดพลาด","N/A":"N/A","gb":"กิกะไบต์","Error: Invalid file extension:":"ข้อผิดพลาด: นามสกุลไฟล์ไม่ถูกต้อง:","Select files":"เลือกไฟล์","%s already present in the queue.":"%s อยู่ในคิวแล้ว","File: %s":"ไฟล์: %s","b":"ไบต์","Uploaded %d/%d files":"อัพโหลดแล้ว %d/%d ไฟล์","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"การอัพโหลดจะยอมรับเฉพาะ %d ไฟล์(s) ในช่วงเวลาเดียวกัน เมื่อไฟล์พิเศษถูกปลดออก","%d files queued":"%d ไฟล์ที่อยู่ในคิว","File: %s, size: %d, max file size: %d":"ไฟล์: %s, ขนาด: %d, ขนาดไฟล์สูงสุด: %d","Drag files here.":"ลากไฟล์มาที่นี่","Runtime ran out of available memory.":"รันไทม์วิ่งออกมาจากหน่วยความจำ","File count error.":"การนับไฟล์เกิดข้อผิดพลาด","File extension error.":"นามสกุลไฟล์เกิดข้อผิดพลาด","Error: File too large:":"ข้อผิดพลาด: ไฟล์ใหญ่เกินไป:","Add Files":"เพิ่มไฟล์"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/tr.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Turkish (tr)
2
+ plupload.addI18n({"Stop Upload":"Yüklemeyi durdur","Upload URL might be wrong or doesn't exist.":"URL yok ya da hatalı olabilir.","tb":"tb","Size":"Boyut","Close":"Kapat","Init error.":"Başlangıç hatası.","Add files to the upload queue and click the start button.":"Dosyaları kuyruğa ekleyin ve başlatma butonuna tıklayın.","Filename":"Dosya adı","Image format either wrong or not supported.":"Resim formatı yanlış ya da desteklenmiyor.","Status":"Durum","HTTP Error.":"HTTP hatası.","Start Upload":"Yüklemeyi başlat","mb":"mb","kb":"kb","Duplicate file error.":"Yinelenen dosya hatası.","File size error.":"Dosya boyutu hatası.","N/A":"-","gb":"gb","Error: Invalid file extension:":"Hata: Geçersiz dosya uzantısı:","Select files":"Dosyaları seç","%s already present in the queue.":"%s kuyrukta zaten mevcut.","File: %s":"Dosya: %s","b":"bayt","Uploaded %d/%d files":"%d/%d dosya yüklendi","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Yükleme elemanı aynı anda %d dosya kabul eder. Ekstra dosyalar işleme konulmaz.","%d files queued":"Kuyrukta %d dosya var.","File: %s, size: %d, max file size: %d":"Dosya: %s, boyut: %d, maksimum dosya boyutu: %d","Drag files here.":"Dosyaları buraya bırakın.","Runtime ran out of available memory.":"İşlem için yeterli bellek yok.","File count error.":"Dosya sayım hatası.","File extension error.":"Dosya uzantısı hatası.","Error: File too large:":"Hata: Dosya çok büyük:","Add Files":"Dosya ekle"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/uk_UA.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Ukrainian (Ukraine) (uk_UA)
2
+ plupload.addI18n({"Stop Upload":"Зупинити завантаження","Upload URL might be wrong or doesn't exist.":"Адреса завантаження неправильна або не існує.","tb":"","Size":"Розмір","Close":"Закрити","Init error.":"Помилка ініціалізації.","Add files to the upload queue and click the start button.":"Додайте файли в чергу та натисніть кнопку \"Завантажити файли\".","Filename":"Назва файлу","Image format either wrong or not supported.":"Формат картинки не правильний або не підтримується.","Status":"Статус","HTTP Error.":"Помилка HTTP.","Start Upload":"Почати завантаження","mb":"","kb":"","Duplicate file error.":"","File size error.":"Неправильний розмір файлу.","N/A":"Н/Д","gb":"","Error: Invalid file extension:":"Помилка: У файлу неправильне розширення:","Select files":"Оберіть файли","%s already present in the queue.":"","File: %s":"Файл: %s","b":"","Uploaded %d/%d files":"Завантажено %d/%d файлів","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"","%d files queued":"В черзі %d файл(ів)","File: %s, size: %d, max file size: %d":"","Drag files here.":"Перетягніть файли сюди.","Runtime ran out of available memory.":"Робоче середовище перевищило ліміт доступної пам'яті.","File count error.":"Занадто багато файлів.","File extension error.":"Неправильне розширення файлу.","Error: File too large:":"Помилка: Файл занадто великий:","Add Files":"Додати файли"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_CN.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Chinese (China) (zh_CN)
2
+ plupload.addI18n({"Stop Upload":"停止上传","Upload URL might be wrong or doesn't exist.":"上传的URL可能是错误的或不存在。","tb":"tb","Size":"大小","Close":"关闭","Init error.":"初始化错误。","Add files to the upload queue and click the start button.":"将文件添加到上传队列,然后点击”开始上传“按钮。","Filename":"文件名","Image format either wrong or not supported.":"图片格式错误或者不支持。","Status":"状态","HTTP Error.":"HTTP 错误。","Start Upload":"开始上传","mb":"mb","kb":"kb","Duplicate file error.":"重复文件错误。","File size error.":"文件大小错误。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"错误:无效的文件扩展名:","Select files":"选择文件","%s already present in the queue.":"%s 已经在当前队列里。","File: %s":"文件: %s","b":"b","Uploaded %d/%d files":"已上传 %d/%d 个文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只接受同时上传 %d 个文件,多余的文件将会被删除。","%d files queued":"%d 个文件加入到队列","File: %s, size: %d, max file size: %d":"文件: %s, 大小: %d, 最大文件大小: %d","Drag files here.":"把文件拖到这里。","Runtime ran out of available memory.":"运行时已消耗所有可用内存。","File count error.":"文件数量错误。","File extension error.":"文件扩展名错误。","Error: File too large:":"错误: 文件太大:","Add Files":"增加文件"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/i18n/zh_TW.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ // Chinese (Taiwan) (zh_TW)
2
+ plupload.addI18n({"Stop Upload":"停止上傳","Upload URL might be wrong or doesn't exist.":"檔案URL可能有誤或者不存在。","tb":"tb","Size":"大小","Close":"關閉","Init error.":"初始化錯誤。","Add files to the upload queue and click the start button.":"將檔案加入上傳序列,然後點選”開始上傳“按鈕。","Filename":"檔案名稱","Image format either wrong or not supported.":"圖片格式錯誤或者不支援。","Status":"狀態","HTTP Error.":"HTTP 錯誤。","Start Upload":"開始上傳","mb":"mb","kb":"kb","Duplicate file error.":"錯誤:檔案重複。","File size error.":"錯誤:檔案大小超過限制。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"錯誤:不接受的檔案格式:","Select files":"選擇檔案","%s already present in the queue.":"%s 已經存在目前的檔案序列。","File: %s":"檔案: %s","b":"b","Uploaded %d/%d files":"已上傳 %d/%d 個文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只能上傳 %d 個檔案,超過限制數量的檔案將被忽略。","%d files queued":"%d 個檔案加入到序列","File: %s, size: %d, max file size: %d":"檔案: %s, 大小: %d, 最大檔案大小: %d","Drag files here.":"把檔案拖曳到這裡。","Runtime ran out of available memory.":"執行時耗盡了所有可用的記憶體。","File count error.":"檔案數量錯誤。","File extension error.":"檔案副檔名錯誤。","Error: File too large:":"錯誤: 檔案大小太大:","Add Files":"增加檔案"});
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/css/jquery.plupload.queue.css ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Plupload
3
+ ------------------------------------------------------------------- */
4
+
5
+ .plupload_button {
6
+ display: -moz-inline-box; /* FF < 3*/
7
+ display: inline-block;
8
+ font: normal 12px sans-serif;
9
+ text-decoration: none;
10
+ color: #42454a;
11
+ border: 1px solid #bababa;
12
+ padding: 2px 8px 3px 20px;
13
+ margin-right: 4px;
14
+ background: #f3f3f3 url('../img/buttons.png') no-repeat 0 center;
15
+ outline: 0;
16
+
17
+ /* Optional rounded corners for browsers that support it */
18
+ -moz-border-radius: 3px;
19
+ -khtml-border-radius: 3px;
20
+ -webkit-border-radius: 3px;
21
+ border-radius: 3px;
22
+ }
23
+
24
+ .plupload_button:hover {
25
+ color: #000;
26
+ text-decoration: none;
27
+ }
28
+
29
+ .plupload_disabled, a.plupload_disabled:hover {
30
+ color: #737373;
31
+ border-color: #c5c5c5;
32
+ background: #ededed url('../img/buttons-disabled.png') no-repeat 0 center;
33
+ cursor: default;
34
+ }
35
+
36
+ .plupload_add {
37
+ background-position: -181px center;
38
+ }
39
+
40
+ .plupload_wrapper {
41
+ font: normal 11px Verdana,sans-serif;
42
+ width: 100%;
43
+ }
44
+
45
+ .plupload_container {
46
+ padding: 8px;
47
+ background: url('../img/transp50.png');
48
+ /*-moz-border-radius: 5px;*/
49
+ }
50
+
51
+ .plupload_container input {
52
+ border: 1px solid #DDD;
53
+ font: normal 11px Verdana,sans-serif;
54
+ width: 98%;
55
+ }
56
+
57
+ .plupload_header {background: #2A2C2E url('../img/backgrounds.gif') repeat-x;}
58
+ .plupload_header_content {
59
+ background: url('../img/backgrounds.gif') no-repeat 0 -317px;
60
+ min-height: 56px;
61
+ padding-left: 60px;
62
+ color: #FFF;
63
+ }
64
+ .plupload_header_title {
65
+ font: normal 18px sans-serif;
66
+ padding: 6px 0 3px;
67
+ }
68
+ .plupload_header_text {
69
+ font: normal 12px sans-serif;
70
+ }
71
+
72
+ .plupload_filelist {
73
+ margin: 0;
74
+ padding: 0;
75
+ list-style: none;
76
+ }
77
+
78
+ .plupload_scroll .plupload_filelist {
79
+ height: 185px;
80
+ background: #F5F5F5;
81
+ overflow-y: scroll;
82
+ }
83
+
84
+ .plupload_filelist li {
85
+ padding: 10px 8px;
86
+ background: #F5F5F5 url('../img/backgrounds.gif') repeat-x 0 -156px;
87
+ border-bottom: 1px solid #DDD;
88
+ }
89
+
90
+ .plupload_filelist_header, .plupload_filelist_footer {
91
+ background: #DFDFDF;
92
+ padding: 8px 8px;
93
+ color: #42454A;
94
+ }
95
+ .plupload_filelist_header {
96
+ border-top: 1px solid #EEE;
97
+ border-bottom: 1px solid #CDCDCD;
98
+ }
99
+
100
+ .plupload_filelist_footer {border-top: 1px solid #FFF; height: 22px; line-height: 20px; vertical-align: middle;}
101
+ .plupload_file_name {float: left; overflow: hidden}
102
+ .plupload_file_status {color: #777;}
103
+ .plupload_file_status span {color: #42454A;}
104
+ .plupload_file_size, .plupload_file_status, .plupload_progress {
105
+ float: right;
106
+ width: 80px;
107
+ }
108
+ .plupload_file_size, .plupload_file_status, .plupload_file_action {text-align: right;}
109
+
110
+ .plupload_filelist .plupload_file_name {
111
+ width: 205px;
112
+ white-space: nowrap;
113
+ text-overflow: ellipsis;
114
+ }
115
+
116
+ .plupload_file_action {
117
+ float: right;
118
+ width: 16px;
119
+ height: 16px;
120
+ margin-left: 15px;
121
+ }
122
+
123
+ .plupload_file_action * {
124
+ display: none;
125
+ width: 16px;
126
+ height: 16px;
127
+ }
128
+
129
+ li.plupload_uploading {background: #ECF3DC url('../img/backgrounds.gif') repeat-x 0 -238px;}
130
+ li.plupload_done {color:#AAA}
131
+
132
+ li.plupload_delete a {
133
+ background: url('../img/delete.gif');
134
+ }
135
+
136
+ li.plupload_failed a {
137
+ background: url('../img/error.gif');
138
+ cursor: default;
139
+ }
140
+
141
+ li.plupload_done a {
142
+ background: url('../img/done.gif');
143
+ cursor: default;
144
+ }
145
+
146
+ .plupload_progress, .plupload_upload_status {
147
+ display: none;
148
+ }
149
+
150
+ .plupload_progress_container {
151
+ margin-top: 3px;
152
+ border: 1px solid #CCC;
153
+ background: #FFF;
154
+ padding: 1px;
155
+ }
156
+ .plupload_progress_bar {
157
+ width: 0px;
158
+ height: 7px;
159
+ background: #CDEB8B;
160
+ }
161
+
162
+ .plupload_scroll .plupload_filelist_header .plupload_file_action, .plupload_scroll .plupload_filelist_footer .plupload_file_action {
163
+ margin-right: 17px;
164
+ }
165
+
166
+ /* Floats */
167
+
168
+ .plupload_clear,.plupload_clearer {clear: both;}
169
+ .plupload_clearer, .plupload_progress_bar {
170
+ display: block;
171
+ font-size: 0;
172
+ line-height: 0;
173
+ }
174
+
175
+ li.plupload_droptext {
176
+ background: transparent;
177
+ text-align: center;
178
+ vertical-align: middle;
179
+ border: 0;
180
+ line-height: 165px;
181
+ }
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/backgrounds.gif ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/buttons-disabled.png ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/buttons.png ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/delete.gif ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/done.gif ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/error.gif ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/throbber.gif ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/img/transp50.png ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/jquery.plupload.queue.js ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * jquery.plupload.queue.js
3
+ *
4
+ * Copyright 2009, Moxiecode Systems AB
5
+ * Released under GPL License.
6
+ *
7
+ * License: http://www.plupload.com/license
8
+ * Contributing: http://www.plupload.com/contributing
9
+ */
10
+
11
+ /* global jQuery:true, alert:true */
12
+
13
+ /**
14
+ jQuery based implementation of the Plupload API - multi-runtime file uploading API.
15
+
16
+ To use the widget you must include _jQuery_. It is not meant to be extended in any way and is provided to be
17
+ used as it is.
18
+
19
+ @example
20
+ <!-- Instantiating: -->
21
+ <div id="uploader">
22
+ <p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
23
+ </div>
24
+
25
+ <script>
26
+ $('#uploader').pluploadQueue({
27
+ url : '../upload.php',
28
+ filters : [
29
+ {title : "Image files", extensions : "jpg,gif,png"}
30
+ ],
31
+ rename: true,
32
+ flash_swf_url : '../../js/Moxie.swf',
33
+ silverlight_xap_url : '../../js/Moxie.xap',
34
+ });
35
+ </script>
36
+
37
+ @example
38
+ // Retrieving a reference to plupload.Uploader object
39
+ var uploader = $('#uploader').pluploadQueue();
40
+
41
+ uploader.bind('FilesAdded', function() {
42
+
43
+ // Autostart
44
+ setTimeout(uploader.start, 1); // "detach" from the main thread
45
+ });
46
+
47
+ @class pluploadQueue
48
+ @constructor
49
+ @param {Object} settings For detailed information about each option check documentation.
50
+ @param {String} settings.url URL of the server-side upload handler.
51
+ @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
52
+ @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
53
+ @param {Array} [settings.filters=[]] Set of file type filters, each one defined by hash of title and extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
54
+ @param {String} [settings.flash_swf_url] URL of the Flash swf.
55
+ @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
56
+ @param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
57
+ @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
58
+ @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
59
+ @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
60
+ @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
61
+ @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
62
+ @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
63
+ @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
64
+ @param {Number} [settings.resize.width] If image is bigger, it will be resized.
65
+ @param {Number} [settings.resize.height] If image is bigger, it will be resized.
66
+ @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
67
+ @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
68
+ @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
69
+ @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
70
+ @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
71
+
72
+ @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
73
+ @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
74
+ @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
75
+ */
76
+ (function($, o) {
77
+ var uploaders = {};
78
+
79
+ function _(str) {
80
+ return plupload.translate(str) || str;
81
+ }
82
+
83
+ function renderUI(id, target) {
84
+ // Remove all existing non plupload items
85
+ target.contents().each(function(i, node) {
86
+ node = $(node);
87
+
88
+ if (!node.is('.plupload')) {
89
+ node.remove();
90
+ }
91
+ });
92
+
93
+ target.prepend(
94
+ '<div class="plupload_wrapper plupload_scroll">' +
95
+ '<div id="' + id + '_container" class="plupload_container">' +
96
+ '<div class="plupload">' +
97
+ '<div class="plupload_header">' +
98
+ '<div class="plupload_header_content">' +
99
+ '<div class="plupload_header_title">' + _('Select files') + '</div>' +
100
+ '<div class="plupload_header_text">' + _('Add files to the upload queue and click the start button.') + '</div>' +
101
+ '</div>' +
102
+ '</div>' +
103
+
104
+ '<div class="plupload_content">' +
105
+ '<div class="plupload_filelist_header">' +
106
+ '<div class="plupload_file_name">' + _('Filename') + '</div>' +
107
+ '<div class="plupload_file_action">&nbsp;</div>' +
108
+ '<div class="plupload_file_status"><span>' + _('Status') + '</span></div>' +
109
+ '<div class="plupload_file_size">' + _('Size') + '</div>' +
110
+ '<div class="plupload_clearer">&nbsp;</div>' +
111
+ '</div>' +
112
+
113
+ '<ul id="' + id + '_filelist" class="plupload_filelist"></ul>' +
114
+
115
+ '<div class="plupload_filelist_footer">' +
116
+ '<div class="plupload_file_name">' +
117
+ '<div class="plupload_buttons">' +
118
+ '<a href="#" class="plupload_button plupload_add" id="' + id + '_browse">' + _('Add Files') + '</a>' +
119
+ '<a href="#" class="plupload_button plupload_start">' + _('Start Upload') + '</a>' +
120
+ '</div>' +
121
+ '<span class="plupload_upload_status"></span>' +
122
+ '</div>' +
123
+ '<div class="plupload_file_action"></div>' +
124
+ '<div class="plupload_file_status"><span class="plupload_total_status">0%</span></div>' +
125
+ '<div class="plupload_file_size"><span class="plupload_total_file_size">0 b</span></div>' +
126
+ '<div class="plupload_progress">' +
127
+ '<div class="plupload_progress_container">' +
128
+ '<div class="plupload_progress_bar"></div>' +
129
+ '</div>' +
130
+ '</div>' +
131
+ '<div class="plupload_clearer">&nbsp;</div>' +
132
+ '</div>' +
133
+ '</div>' +
134
+ '</div>' +
135
+ '</div>' +
136
+ '<input type="hidden" id="' + id + '_count" name="' + id + '_count" value="0" />' +
137
+ '</div>'
138
+ );
139
+ }
140
+
141
+ $.fn.pluploadQueue = function(settings) {
142
+ if (settings) {
143
+ this.each(function() {
144
+ var uploader, target, id, contents_bak;
145
+
146
+ target = $(this);
147
+ id = target.attr('id');
148
+
149
+ if (!id) {
150
+ id = plupload.guid();
151
+ target.attr('id', id);
152
+ }
153
+
154
+ contents_bak = target.html();
155
+ renderUI(id, target);
156
+
157
+ settings = $.extend({
158
+ dragdrop : true,
159
+ browse_button : id + '_browse',
160
+ container : id
161
+ }, settings);
162
+
163
+ // Enable drag/drop (see PostInit handler as well)
164
+ if (settings.dragdrop) {
165
+ settings.drop_element = id + '_filelist';
166
+ }
167
+
168
+ uploader = new plupload.Uploader(settings);
169
+
170
+ uploaders[id] = uploader;
171
+
172
+ function handleStatus(file) {
173
+ var actionClass;
174
+
175
+ if (file.status == plupload.DONE) {
176
+ actionClass = 'plupload_done';
177
+ }
178
+
179
+ if (file.status == plupload.FAILED) {
180
+ actionClass = 'plupload_failed';
181
+ }
182
+
183
+ if (file.status == plupload.QUEUED) {
184
+ actionClass = 'plupload_delete';
185
+ }
186
+
187
+ if (file.status == plupload.UPLOADING) {
188
+ actionClass = 'plupload_uploading';
189
+ }
190
+
191
+ var icon = $('#' + file.id).attr('class', actionClass).find('a').css('display', 'block');
192
+ if (file.hint) {
193
+ icon.attr('title', file.hint);
194
+ }
195
+ }
196
+
197
+ function updateTotalProgress() {
198
+ $('span.plupload_total_status', target).html(uploader.total.percent + '%');
199
+ $('div.plupload_progress_bar', target).css('width', uploader.total.percent + '%');
200
+ $('span.plupload_upload_status', target).html(
201
+ o.sprintf(_('Uploaded %d/%d files'), uploader.total.uploaded, uploader.files.length)
202
+ );
203
+ }
204
+
205
+ function updateList() {
206
+ var fileList = $('ul.plupload_filelist', target).html(''), inputCount = 0, inputHTML;
207
+
208
+ $.each(uploader.files, function(i, file) {
209
+ inputHTML = '';
210
+
211
+ if (file.status == plupload.DONE) {
212
+ if (file.target_name) {
213
+ inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_tmpname" value="' + plupload.xmlEncode(file.target_name) + '" />';
214
+ }
215
+
216
+ inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_name" value="' + plupload.xmlEncode(file.name) + '" />';
217
+ inputHTML += '<input type="hidden" name="' + id + '_' + inputCount + '_status" value="' + (file.status == plupload.DONE ? 'done' : 'failed') + '" />';
218
+
219
+ inputCount++;
220
+
221
+ $('#' + id + '_count').val(inputCount);
222
+ }
223
+
224
+ fileList.append(
225
+ '<li id="' + file.id + '">' +
226
+ '<div class="plupload_file_name"><span>' + file.name + '</span></div>' +
227
+ '<div class="plupload_file_action"><a href="#"></a></div>' +
228
+ '<div class="plupload_file_status">' + file.percent + '%</div>' +
229
+ '<div class="plupload_file_size">' + plupload.formatSize(file.size) + '</div>' +
230
+ '<div class="plupload_clearer">&nbsp;</div>' +
231
+ inputHTML +
232
+ '</li>'
233
+ );
234
+
235
+ handleStatus(file);
236
+
237
+ $('#' + file.id + '.plupload_delete a').click(function(e) {
238
+ $('#' + file.id).remove();
239
+ uploader.removeFile(file);
240
+
241
+ e.preventDefault();
242
+ });
243
+ });
244
+
245
+ $('span.plupload_total_file_size', target).html(plupload.formatSize(uploader.total.size));
246
+
247
+ if (uploader.total.queued === 0) {
248
+ $('span.plupload_add_text', target).html(_('Add Files'));
249
+ } else {
250
+ $('span.plupload_add_text', target).html(o.sprintf(_('%d files queued'), uploader.total.queued));
251
+ }
252
+
253
+ $('a.plupload_start', target).toggleClass('plupload_disabled', uploader.files.length == (uploader.total.uploaded + uploader.total.failed));
254
+
255
+ // Scroll to end of file list
256
+ fileList[0].scrollTop = fileList[0].scrollHeight;
257
+
258
+ updateTotalProgress();
259
+
260
+ // Re-add drag message if there is no files
261
+ if (!uploader.files.length && uploader.features.dragdrop && uploader.settings.dragdrop) {
262
+ $('#' + id + '_filelist').append('<li class="plupload_droptext">' + _("Drag files here.") + '</li>');
263
+ }
264
+ }
265
+
266
+ function destroy() {
267
+ delete uploaders[id];
268
+ uploader.destroy();
269
+ target.html(contents_bak);
270
+ uploader = target = contents_bak = null;
271
+ }
272
+
273
+ uploader.bind("UploadFile", function(up, file) {
274
+ $('#' + file.id).addClass('plupload_current_file');
275
+ });
276
+
277
+ uploader.bind('Init', function(up, res) {
278
+ // Enable rename support
279
+ if (!settings.unique_names && settings.rename) {
280
+ target.on('click', '#' + id + '_filelist div.plupload_file_name span', function(e) {
281
+ var targetSpan = $(e.target), file, parts, name, ext = "";
282
+
283
+ // Get file name and split out name and extension
284
+ file = up.getFile(targetSpan.parents('li')[0].id);
285
+ name = file.name;
286
+ parts = /^(.+)(\.[^.]+)$/.exec(name);
287
+ if (parts) {
288
+ name = parts[1];
289
+ ext = parts[2];
290
+ }
291
+
292
+ // Display input element
293
+ targetSpan.hide().after('<input type="text" />');
294
+ targetSpan.next().val(name).focus().blur(function() {
295
+ targetSpan.show().next().remove();
296
+ }).keydown(function(e) {
297
+ var targetInput = $(this);
298
+
299
+ if (e.keyCode == 13) {
300
+ e.preventDefault();
301
+
302
+ // Rename file and glue extension back on
303
+ file.name = targetInput.val() + ext;
304
+ targetSpan.html(file.name);
305
+ targetInput.blur();
306
+ }
307
+ });
308
+ });
309
+ }
310
+
311
+ $('#' + id + '_container').attr('title', 'Using runtime: ' + res.runtime);
312
+
313
+ $('a.plupload_start', target).click(function(e) {
314
+ if (!$(this).hasClass('plupload_disabled')) {
315
+ uploader.start();
316
+ }
317
+
318
+ e.preventDefault();
319
+ });
320
+
321
+ $('a.plupload_stop', target).click(function(e) {
322
+ e.preventDefault();
323
+ uploader.stop();
324
+ });
325
+
326
+ $('a.plupload_start', target).addClass('plupload_disabled');
327
+ });
328
+
329
+ uploader.bind("Error", function(up, err) {
330
+ var file = err.file, message;
331
+
332
+ if (file) {
333
+ message = err.message;
334
+
335
+ if (err.details) {
336
+ message += " (" + err.details + ")";
337
+ }
338
+
339
+ if (err.code == plupload.FILE_SIZE_ERROR) {
340
+ alert(_("Error: File too large:") + " " + file.name);
341
+ }
342
+
343
+ if (err.code == plupload.FILE_EXTENSION_ERROR) {
344
+ alert(_("Error: Invalid file extension:") + " " + file.name);
345
+ }
346
+
347
+ file.hint = message;
348
+ $('#' + file.id).attr('class', 'plupload_failed').find('a').css('display', 'block').attr('title', message);
349
+ }
350
+
351
+ if (err.code === plupload.INIT_ERROR) {
352
+ setTimeout(function() {
353
+ destroy();
354
+ }, 1);
355
+ }
356
+ });
357
+
358
+ uploader.bind("PostInit", function(up) {
359
+ // features are populated only after input components are fully instantiated
360
+ if (up.settings.dragdrop && up.features.dragdrop) {
361
+ $('#' + id + '_filelist').append('<li class="plupload_droptext">' + _("Drag files here.") + '</li>');
362
+ }
363
+ });
364
+
365
+ uploader.init();
366
+
367
+ uploader.bind('StateChanged', function() {
368
+ if (uploader.state === plupload.STARTED) {
369
+ $('li.plupload_delete a,div.plupload_buttons', target).hide();
370
+ $('span.plupload_upload_status,div.plupload_progress,a.plupload_stop', target).css('display', 'block');
371
+ $('span.plupload_upload_status', target).html('Uploaded ' + uploader.total.uploaded + '/' + uploader.files.length + ' files');
372
+
373
+ if (settings.multiple_queues) {
374
+ $('span.plupload_total_status,span.plupload_total_file_size', target).show();
375
+ }
376
+ } else {
377
+ updateList();
378
+ $('a.plupload_stop,div.plupload_progress', target).hide();
379
+ $('a.plupload_delete', target).css('display', 'block');
380
+
381
+ if (settings.multiple_queues && uploader.total.uploaded + uploader.total.failed == uploader.files.length) {
382
+ $(".plupload_buttons,.plupload_upload_status", target).css("display", "inline");
383
+ $(".plupload_start", target).addClass("plupload_disabled");
384
+ $('span.plupload_total_status,span.plupload_total_file_size', target).hide();
385
+ }
386
+ }
387
+ });
388
+
389
+ uploader.bind('FilesAdded', updateList);
390
+
391
+ uploader.bind('FilesRemoved', function() {
392
+ // since the whole file list is redrawn for every change in the queue
393
+ // we need to scroll back to the file removal point to avoid annoying
394
+ // scrolling to the bottom bug (see #926)
395
+ var scrollTop = $('#' + id + '_filelist').scrollTop();
396
+ updateList();
397
+ $('#' + id + '_filelist').scrollTop(scrollTop);
398
+ });
399
+
400
+ uploader.bind('FileUploaded', function(up, file) {
401
+ handleStatus(file);
402
+ });
403
+
404
+ uploader.bind("UploadProgress", function(up, file) {
405
+ // Set file specific progress
406
+ $('#' + file.id + ' div.plupload_file_status', target).html(file.percent + '%');
407
+
408
+ handleStatus(file);
409
+ updateTotalProgress();
410
+ });
411
+
412
+ // Call setup function
413
+ if (settings.setup) {
414
+ settings.setup(uploader);
415
+ }
416
+ });
417
+
418
+ return this;
419
+ } else {
420
+ // Get uploader instance for specified element
421
+ return uploaders[$(this[0]).attr('id')];
422
+ }
423
+ };
424
+ })(jQuery, mOxie);
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.plupload.queue/jquery.plupload.queue.min.js ADDED
@@ -0,0 +1 @@
 
1
+ ;(function(e,t){function r(e){return plupload.translate(e)||e}function i(t,n){n.contents().each(function(t,n){n=e(n),n.is(".plupload")||n.remove()}),n.prepend('<div class="plupload_wrapper plupload_scroll"><div id="'+t+'_container" class="plupload_container">'+'<div class="plupload">'+'<div class="plupload_header">'+'<div class="plupload_header_content">'+'<div class="plupload_header_title">'+r("Select files")+"</div>"+'<div class="plupload_header_text">'+r("Add files to the upload queue and click the start button.")+"</div>"+"</div>"+"</div>"+'<div class="plupload_content">'+'<div class="plupload_filelist_header">'+'<div class="plupload_file_name">'+r("Filename")+"</div>"+'<div class="plupload_file_action">&nbsp;</div>'+'<div class="plupload_file_status"><span>'+r("Status")+"</span></div>"+'<div class="plupload_file_size">'+r("Size")+"</div>"+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+'<ul id="'+t+'_filelist" class="plupload_filelist"></ul>'+'<div class="plupload_filelist_footer">'+'<div class="plupload_file_name">'+'<div class="plupload_buttons">'+'<a href="#" class="plupload_button plupload_add" id="'+t+'_browse">'+r("Add Files")+"</a>"+'<a href="#" class="plupload_button plupload_start">'+r("Start Upload")+"</a>"+"</div>"+'<span class="plupload_upload_status"></span>'+"</div>"+'<div class="plupload_file_action"></div>'+'<div class="plupload_file_status"><span class="plupload_total_status">0%</span></div>'+'<div class="plupload_file_size"><span class="plupload_total_file_size">0 b</span></div>'+'<div class="plupload_progress">'+'<div class="plupload_progress_container">'+'<div class="plupload_progress_bar"></div>'+"</div>"+"</div>"+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+"</div>"+"</div>"+"</div>"+'<input type="hidden" id="'+t+'_count" name="'+t+'_count" value="0" />'+"</div>")}var n={};e.fn.pluploadQueue=function(s){return s?(this.each(function(){function c(t){var n;t.status==plupload.DONE&&(n="plupload_done"),t.status==plupload.FAILED&&(n="plupload_failed"),t.status==plupload.QUEUED&&(n="plupload_delete"),t.status==plupload.UPLOADING&&(n="plupload_uploading");var r=e("#"+t.id).attr("class",n).find("a").css("display","block");t.hint&&r.attr("title",t.hint)}function h(){e("span.plupload_total_status",a).html(u.total.percent+"%"),e("div.plupload_progress_bar",a).css("width",u.total.percent+"%"),e("span.plupload_upload_status",a).html(t.sprintf(r("Uploaded %d/%d files"),u.total.uploaded,u.files.length))}function p(){var n=e("ul.plupload_filelist",a).html(""),i=0,s;e.each(u.files,function(t,r){s="",r.status==plupload.DONE&&(r.target_name&&(s+='<input type="hidden" name="'+f+"_"+i+'_tmpname" value="'+plupload.xmlEncode(r.target_name)+'" />'),s+='<input type="hidden" name="'+f+"_"+i+'_name" value="'+plupload.xmlEncode(r.name)+'" />',s+='<input type="hidden" name="'+f+"_"+i+'_status" value="'+(r.status==plupload.DONE?"done":"failed")+'" />',i++,e("#"+f+"_count").val(i)),n.append('<li id="'+r.id+'">'+'<div class="plupload_file_name"><span>'+r.name+"</span></div>"+'<div class="plupload_file_action"><a href="#"></a></div>'+'<div class="plupload_file_status">'+r.percent+"%</div>"+'<div class="plupload_file_size">'+plupload.formatSize(r.size)+"</div>"+'<div class="plupload_clearer">&nbsp;</div>'+s+"</li>"),c(r),e("#"+r.id+".plupload_delete a").click(function(t){e("#"+r.id).remove(),u.removeFile(r),t.preventDefault()})}),e("span.plupload_total_file_size",a).html(plupload.formatSize(u.total.size)),u.total.queued===0?e("span.plupload_add_text",a).html(r("Add Files")):e("span.plupload_add_text",a).html(t.sprintf(r("%d files queued"),u.total.queued)),e("a.plupload_start",a).toggleClass("plupload_disabled",u.files.length==u.total.uploaded+u.total.failed),n[0].scrollTop=n[0].scrollHeight,h(),!u.files.length&&u.features.dragdrop&&u.settings.dragdrop&&e("#"+f+"_filelist").append('<li class="plupload_droptext">'+r("Drag files here.")+"</li>")}function d(){delete n[f],u.destroy(),a.html(l),u=a=l=null}var u,a,f,l;a=e(this),f=a.attr("id"),f||(f=plupload.guid(),a.attr("id",f)),l=a.html(),i(f,a),s=e.extend({dragdrop:!0,browse_button:f+"_browse",container:f},s),s.dragdrop&&(s.drop_element=f+"_filelist"),u=new plupload.Uploader(s),n[f]=u,u.bind("UploadFile",function(t,n){e("#"+n.id).addClass("plupload_current_file")}),u.bind("Init",function(t,n){!s.unique_names&&s.rename&&a.on("click","#"+f+"_filelist div.plupload_file_name span",function(n){var r=e(n.target),i,s,o,u="";i=t.getFile(r.parents("li")[0].id),o=i.name,s=/^(.+)(\.[^.]+)$/.exec(o),s&&(o=s[1],u=s[2]),r.hide().after('<input type="text" />'),r.next().val(o).focus().blur(function(){r.show().next().remove()}).keydown(function(t){var n=e(this);t.keyCode==13&&(t.preventDefault(),i.name=n.val()+u,r.html(i.name),n.blur())})}),e("#"+f+"_container").attr("title","Using runtime: "+n.runtime),e("a.plupload_start",a).click(function(t){e(this).hasClass("plupload_disabled")||u.start(),t.preventDefault()}),e("a.plupload_stop",a).click(function(e){e.preventDefault(),u.stop()}),e("a.plupload_start",a).addClass("plupload_disabled")}),u.bind("Error",function(t,n){var i=n.file,s;i&&(s=n.message,n.details&&(s+=" ("+n.details+")"),n.code==plupload.FILE_SIZE_ERROR&&alert(r("Error: File too large:")+" "+i.name),n.code==plupload.FILE_EXTENSION_ERROR&&alert(r("Error: Invalid file extension:")+" "+i.name),i.hint=s,e("#"+i.id).attr("class","plupload_failed").find("a").css("display","block").attr("title",s)),n.code===plupload.INIT_ERROR&&setTimeout(function(){d()},1)}),u.bind("PostInit",function(t){t.settings.dragdrop&&t.features.dragdrop&&e("#"+f+"_filelist").append('<li class="plupload_droptext">'+r("Drag files here.")+"</li>")}),u.init(),u.bind("StateChanged",function(){u.state===plupload.STARTED?(e("li.plupload_delete a,div.plupload_buttons",a).hide(),e("span.plupload_upload_status,div.plupload_progress,a.plupload_stop",a).css("display","block"),e("span.plupload_upload_status",a).html("Uploaded "+u.total.uploaded+"/"+u.files.length+" files"),s.multiple_queues&&e("span.plupload_total_status,span.plupload_total_file_size",a).show()):(p(),e("a.plupload_stop,div.plupload_progress",a).hide(),e("a.plupload_delete",a).css("display","block"),s.multiple_queues&&u.total.uploaded+u.total.failed==u.files.length&&(e(".plupload_buttons,.plupload_upload_status",a).css("display","inline"),e(".plupload_start",a).addClass("plupload_disabled"),e("span.plupload_total_status,span.plupload_total_file_size",a).hide()))}),u.bind("FilesAdded",p),u.bind("FilesRemoved",function(){var t=e("#"+f+"_filelist").scrollTop();p(),e("#"+f+"_filelist").scrollTop(t)}),u.bind("FileUploaded",function(e,t){c(t)}),u.bind("UploadProgress",function(t,n){e("#"+n.id+" div.plupload_file_status",a).html(n.percent+"%"),c(n),h()}),s.setup&&s.setup(u)}),this):n[e(this[0]).attr("id")]}})(jQuery,mOxie);
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/css/jquery.ui.plupload.css ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Plupload
3
+ ------------------------------------------------------------------- */
4
+
5
+ .plupload_button {
6
+ cursor: pointer;
7
+ outline: none;
8
+ }
9
+
10
+ .plupload_wrapper {
11
+ font: normal 11px Verdana,sans-serif;
12
+ width: 100%;
13
+ min-width: 520px;
14
+ }
15
+
16
+ .plupload_container {
17
+ _height: 300px;
18
+ min-height: 300px;
19
+ position: relative;
20
+ }
21
+
22
+ .plupload_filelist_footer {border-width: 1px 0 0 0}
23
+ .plupload_file {border-width: 0 0 1px 0}
24
+ .plupload_container .plupload_header {border-width: 0 0 1px 0; position: relative;}
25
+
26
+ .plupload_delete .ui-icon,
27
+ .plupload_done .ui-icon,
28
+ .plupload_failed .ui-icon {
29
+ cursor:pointer;
30
+ }
31
+
32
+ .plupload_header_content {
33
+ height: 56px;
34
+ padding: 0 160px 0 60px;
35
+ position: relative;
36
+ }
37
+
38
+ .plupload_logo {
39
+ width: 40px;
40
+ height: 40px;
41
+ background: url('../img/plupload.png') no-repeat 0 0;
42
+ position: absolute;
43
+ top: 8px;
44
+ left: 8px;
45
+ }
46
+
47
+ .plupload_header_content_bw .plupload_logo {
48
+ background-position: -40px 0;
49
+ }
50
+
51
+ .plupload_header_title {
52
+ font: normal 18px sans-serif;
53
+ padding: 6px 0 3px;
54
+ }
55
+
56
+ .plupload_header_text {
57
+ font: normal 12px sans-serif;
58
+ }
59
+
60
+ .plupload_view_switch {
61
+ position: absolute;
62
+ right: 16px;
63
+ bottom: 8px;
64
+ margin: 0;
65
+ display: none;
66
+ }
67
+
68
+ .plupload_view_switch .ui-button {
69
+ margin-right: -0.31em;
70
+ }
71
+
72
+ .plupload_content {
73
+ position: absolute;
74
+ top: 87px;
75
+ bottom: 44px;
76
+ left: 0;
77
+ right: 0;
78
+ overflow-y: auto;
79
+ width: 100%;
80
+ }
81
+
82
+ .plupload_filelist {
83
+ border-collapse: collapse;
84
+ border-left: none;
85
+ border-right: none;
86
+ margin: 0;
87
+ padding: 0;
88
+ width: 100%;
89
+ -moz-user-select: none;
90
+ -webkit-user-select: none;
91
+ user-select: none;
92
+ }
93
+
94
+ .plupload_filelist_content {
95
+ padding: 0;
96
+ margin: 0;
97
+ }
98
+
99
+ .plupload_cell {padding: 8px 6px;}
100
+
101
+ .plupload_file {
102
+ list-style: none;
103
+ display: block;
104
+ position: relative;
105
+ overflow: hidden;
106
+ width: 100%;
107
+ }
108
+
109
+ .plupload_file_thumb {
110
+ position: absolute;
111
+ left: 6px;
112
+ top: 6px;
113
+ background: #eee url(../img/loading.gif) center no-repeat;
114
+ }
115
+
116
+ .plupload_file_thumb_loaded .plupload_file_thumb {
117
+ background-image: none;
118
+ }
119
+
120
+ .plupload_file_name {
121
+ overflow: hidden;
122
+ text-overflow: ellipsis;
123
+ white-space: nowrap;
124
+ }
125
+
126
+ .plupload_filelist_header {
127
+ border-top: none;
128
+ }
129
+
130
+ .plupload_filelist_footer {
131
+ position: absolute;
132
+ bottom: 0;
133
+ left: 0;
134
+ right: 0;
135
+ }
136
+
137
+ .plupload_buttons {
138
+ position: relative;
139
+ }
140
+
141
+ /* list view */
142
+ .plupload_view_list .plupload_file {
143
+ border-left: none;
144
+ border-right: none;
145
+ border-top: none;
146
+ height: 29px;
147
+ }
148
+
149
+ .plupload_view_list div.plupload_file_size,
150
+ .plupload_view_list div.plupload_file_status,
151
+ .plupload_view_list div.plupload_file_action {
152
+ padding: 8px 6px;
153
+ position: absolute;
154
+ top: 0;
155
+ right: 0;
156
+ }
157
+
158
+ .plupload_view_list div.plupload_file_name {
159
+ margin-right: 156px;
160
+ padding: 8px 6px;
161
+ _width: 75%;
162
+ }
163
+
164
+ .plupload_view_list div.plupload_file_size {
165
+ right: 28px;
166
+ }
167
+
168
+ .plupload_view_list div.plupload_file_status {
169
+ right: 82px;
170
+ }
171
+
172
+ .plupload_view_list .plupload_file_rename {
173
+ margin-left: -2px;
174
+ }
175
+
176
+ .plupload_view_list .plupload_file_size,
177
+ .plupload_view_list .plupload_file_status,
178
+ .plupload_filelist_footer .plupload_file_size,
179
+ .plupload_filelist_footer .plupload_file_status {
180
+ text-align: right;
181
+ width: 52px;
182
+ }
183
+
184
+ .plupload_view_list .plupload_file_thumb,
185
+ .plupload_view_list .plupload_file_dummy {
186
+ top: -999px;
187
+ }
188
+
189
+ .plupload_view_list .plupload_file_progress {
190
+ display: none;
191
+ }
192
+
193
+
194
+ /* thumbs view */
195
+ .plupload_view_thumbs .plupload_content {
196
+ top: 57px;
197
+ }
198
+
199
+ .plupload_view_thumbs .plupload_filelist_header {
200
+ display: none;
201
+ }
202
+
203
+ .plupload_view_thumbs .plupload_file {
204
+ width: 100px;
205
+ padding: 72px 6px 6px;
206
+ margin: 10px;
207
+ border: 1px solid #fff;
208
+ float: left;
209
+ }
210
+
211
+ .plupload_view_thumbs .plupload_file_thumb,
212
+ .plupload_view_thumbs .plupload_file_dummy {
213
+ width: 100px;
214
+ height: 60px;
215
+ text-align: center;
216
+ overflow: hidden;
217
+ }
218
+
219
+ .plupload_view_thumbs .plupload_file_dummy {
220
+ font-size: 21px;
221
+ font-weight: bold;
222
+ text-transform: lowercase;
223
+ overflow: hidden;
224
+ line-height: 60px;
225
+ border: none;
226
+ }
227
+
228
+ .plupload_view_thumbs div.plupload_file_action {
229
+ position: absolute;
230
+ top: 0;
231
+ right: 0;
232
+ }
233
+
234
+ .plupload_view_thumbs div.plupload_file_name {
235
+ padding: 0;
236
+ font-weight: bold;
237
+ }
238
+
239
+ .plupload_view_thumbs .plupload_file_rename {
240
+ padding: 1px 0;
241
+ width: 100% !important;
242
+ }
243
+
244
+ .plupload_view_thumbs div.plupload_file_size {
245
+ font-size: 0.8em;
246
+ font-weight: normal;
247
+ }
248
+
249
+ .plupload_view_thumbs div.plupload_file_status {
250
+ position: absolute;
251
+ top: 67px;
252
+ left: 6px;
253
+ width: 100px;
254
+ height: 3px;
255
+ overflow: hidden;
256
+ text-indent: -999px;
257
+ }
258
+
259
+ .plupload_view_thumbs div.plupload_file_progress {
260
+ border: none;
261
+ height: 100%;
262
+ }
263
+
264
+ .plupload .ui-sortable-helper,
265
+ .plupload .ui-sortable .plupload_file {
266
+ cursor:move;
267
+ }
268
+
269
+ .plupload_file_action {width: 16px;}
270
+ .plupload_file_name {
271
+ overflow: hidden;
272
+ padding-left: 10px;
273
+ }
274
+
275
+ .plupload_file_rename {
276
+ border: none;
277
+ font: normal 11px Verdana, sans-serif;
278
+ padding: 1px 2px;
279
+ line-height: 11px;
280
+ height: 11px;
281
+ }
282
+
283
+ .plupload_progress {width: 60px;}
284
+ .plupload_progress_container {padding: 1px;}
285
+
286
+
287
+ /* Floats */
288
+
289
+ .plupload_right {float: right;}
290
+ .plupload_left {float: left;}
291
+ .plupload_clear,.plupload_clearer {clear: both;}
292
+ .plupload_clearer, .plupload_progress_bar {
293
+ display: block;
294
+ font-size: 0;
295
+ line-height: 0;
296
+ }
297
+ .plupload_clearer {height: 0;}
298
+
299
+ /* Misc */
300
+ .plupload_hidden {display: none;}
301
+
302
+ .plupload_droptext {
303
+ position: absolute;
304
+ top: 0;
305
+ left: 0;
306
+ right: 0;
307
+ bottom: 0;
308
+ background: transparent;
309
+ text-align: center;
310
+ vertical-align: middle;
311
+ border: 0;
312
+ line-height: 160px;
313
+ display: none;
314
+ }
315
+
316
+ .plupload_dropbox .plupload_droptext {
317
+ display: block;
318
+ }
319
+
320
+ .plupload_buttons, .plupload_upload_status {float: left}
321
+
322
+ .plupload_message {
323
+ position: absolute;
324
+ top: -1px;
325
+ left: -1px;
326
+ height: 100%;
327
+ width: 100%;
328
+ }
329
+
330
+ .plupload_message p {
331
+ padding:0.7em;
332
+ margin:0;
333
+ }
334
+
335
+ .plupload_message strong {
336
+ font-weight: bold;
337
+ }
338
+
339
+ plupload_message i {
340
+ font-style: italic;
341
+ }
342
+
343
+ .plupload_message p span.ui-icon {
344
+ float: left;
345
+ margin-right: 0.3em;
346
+ }
347
+
348
+ .plupload_header_content .ui-state-error,
349
+ .plupload_header_content .ui-state-highlight {
350
+ border:none;
351
+ }
352
+
353
+ .plupload_message_close {
354
+ position:absolute;
355
+ top:5px;
356
+ right:5px;
357
+ cursor:pointer;
358
+ }
359
+
360
+ .plupload .ui-sortable-placeholder {
361
+ height:35px;
362
+ }
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/img/loading.gif ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/img/plupload.png ADDED
Binary file
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/jquery.ui.plupload.js ADDED
@@ -0,0 +1,1307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * jquery.ui.plupload.js
3
+ *
4
+ * Copyright 2013, Moxiecode Systems AB
5
+ * Released under GPL License.
6
+ *
7
+ * License: http://www.plupload.com/license
8
+ * Contributing: http://www.plupload.com/contributing
9
+ *
10
+ * Depends:
11
+ * jquery.ui.core.js
12
+ * jquery.ui.widget.js
13
+ * jquery.ui.button.js
14
+ * jquery.ui.progressbar.js
15
+ *
16
+ * Optionally:
17
+ * jquery.ui.sortable.js
18
+ */
19
+
20
+ /* global jQuery:true */
21
+
22
+ /**
23
+ jQuery UI based implementation of the Plupload API - multi-runtime file uploading API.
24
+
25
+ To use the widget you must include _jQuery_ and _jQuery UI_ bundle (including `ui.core`, `ui.widget`, `ui.button`,
26
+ `ui.progressbar` and `ui.sortable`).
27
+
28
+ In general the widget is designed the way that you do not usually need to do anything to it after you instantiate it.
29
+ But! You still can intervenue, to some extent, in case you need to. Although, due to the fact that widget is based on
30
+ _jQuery UI_ widget factory, there are some specifics. See examples below for more details.
31
+
32
+ @example
33
+ <!-- Instantiating: -->
34
+ <div id="uploader">
35
+ <p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
36
+ </div>
37
+
38
+ <script>
39
+ $('#uploader').plupload({
40
+ url : '../upload.php',
41
+ filters : [
42
+ {title : "Image files", extensions : "jpg,gif,png"}
43
+ ],
44
+ rename: true,
45
+ sortable: true,
46
+ flash_swf_url : '../../js/Moxie.swf',
47
+ silverlight_xap_url : '../../js/Moxie.xap',
48
+ });
49
+ </script>
50
+
51
+ @example
52
+ // Invoking methods:
53
+ $('#uploader').plupload(options);
54
+
55
+ // Display welcome message in the notification area
56
+ $('#uploader').plupload('notify', 'info', "This might be obvious, but you need to click 'Add Files' to add some files.");
57
+
58
+ @example
59
+ // Subscribing to the events...
60
+ // ... on initialization:
61
+ $('#uploader').plupload({
62
+ ...
63
+ viewchanged: function(event, args) {
64
+ // stuff ...
65
+ }
66
+ });
67
+ // ... or after initialization
68
+ $('#uploader').on("viewchanged", function(event, args) {
69
+ // stuff ...
70
+ });
71
+
72
+ @class UI.Plupload
73
+ @constructor
74
+ @param {Object} settings For detailed information about each option check documentation.
75
+ @param {String} settings.url URL of the server-side upload handler.
76
+ @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
77
+ @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
78
+ @param {Array} [settings.filters=[]] Set of file type filters, each one defined by hash of title and extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
79
+ @param {String} [settings.flash_swf_url] URL of the Flash swf.
80
+ @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
81
+ @param {Number|String} [settings.max_file_size] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
82
+ @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
83
+ @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
84
+ @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
85
+ @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
86
+ @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
87
+ @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
88
+ @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
89
+ @param {Number} [settings.resize.width] If image is bigger, it will be resized.
90
+ @param {Number} [settings.resize.height] If image is bigger, it will be resized.
91
+ @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
92
+ @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
93
+ @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
94
+ @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
95
+ @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
96
+
97
+ @param {Boolean} [settings.autostart=false] Whether to auto start uploading right after file selection.
98
+ @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
99
+ @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
100
+ @param {Boolean} [settings.sortable=false] Enable ability to sort files in the queue, changing their uploading priority.
101
+ @param {Object} [settings.buttons] Control the visibility of functional buttons.
102
+ @param {Boolean} [settings.buttons.browse=true] Display browse button.
103
+ @param {Boolean} [settings.buttons.start=true] Display start button.
104
+ @param {Boolean} [settings.buttons.stop=true] Display stop button.
105
+ @param {Object} [settings.views] Control various views of the file queue.
106
+ @param {Boolean} [settings.views.list=true] Enable list view.
107
+ @param {Boolean} [settings.views.thumbs=false] Enable thumbs view.
108
+ @param {String} [settings.views.default='list'] Default view.
109
+ @param {Boolean} [settings.views.remember=true] Whether to remember the current view (requires jQuery Cookie plugin).
110
+ @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
111
+ @param {Number} [settings.max_file_count=0] Limit the number of files user is able to upload in one go, autosets _multiple_queues_ to _false_ (default is 0 - no limit).
112
+ */
113
+ (function(window, document, plupload, o, $) {
114
+
115
+ /**
116
+ Dispatched when the widget is initialized and ready.
117
+
118
+ @event ready
119
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
120
+ */
121
+
122
+ /**
123
+ Dispatched when file dialog is closed.
124
+
125
+ @event selected
126
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
127
+ @param {Array} files Array of selected files represented by plupload.File objects
128
+ */
129
+
130
+ /**
131
+ Dispatched when file dialog is closed.
132
+
133
+ @event removed
134
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
135
+ @param {Array} files Array of removed files represented by plupload.File objects
136
+ */
137
+
138
+ /**
139
+ Dispatched when upload is started.
140
+
141
+ @event start
142
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
143
+ */
144
+
145
+ /**
146
+ Dispatched when upload is stopped.
147
+
148
+ @event stop
149
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
150
+ */
151
+
152
+ /**
153
+ Dispatched during the upload process.
154
+
155
+ @event progress
156
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
157
+ @param {plupload.File} file File that is being uploaded (includes loaded and percent properties among others).
158
+ @param {Number} size Total file size in bytes.
159
+ @param {Number} loaded Number of bytes uploaded of the files total size.
160
+ @param {Number} percent Number of percentage uploaded of the file.
161
+ */
162
+
163
+ /**
164
+ Dispatched when file is uploaded.
165
+
166
+ @event uploaded
167
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
168
+ @param {plupload.File} file File that was uploaded.
169
+ @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
170
+ */
171
+
172
+ /**
173
+ Dispatched when upload of the whole queue is complete.
174
+
175
+ @event complete
176
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
177
+ @param {Array} files Array of uploaded files represented by plupload.File objects
178
+ */
179
+
180
+ /**
181
+ Dispatched when the view is changed, e.g. from `list` to `thumbs` or vice versa.
182
+
183
+ @event viewchanged
184
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
185
+ @param {String} type Current view type.
186
+ */
187
+
188
+ /**
189
+ Dispatched when error of some kind is detected.
190
+
191
+ @event error
192
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
193
+ @param {String} error Error message.
194
+ @param {plupload.File} file File that was uploaded.
195
+ @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
196
+ */
197
+
198
+ var uploaders = {};
199
+
200
+ function _(str) {
201
+ return plupload.translate(str) || str;
202
+ }
203
+
204
+ function renderUI(obj) {
205
+ obj.id = obj.attr('id');
206
+
207
+ obj.html(
208
+ '<div class="plupload_wrapper">' +
209
+ '<div class="ui-widget-content plupload_container">' +
210
+ '<div class="ui-state-default ui-widget-header plupload_header">' +
211
+ '<div class="plupload_header_content">' +
212
+ '<div class="plupload_logo"> </div>' +
213
+ '<div class="plupload_header_title">' + _('Select files') + '</div>' +
214
+ '<div class="plupload_header_text">' + _('Add files to the upload queue and click the start button.') + '</div>' +
215
+ '<div class="plupload_view_switch">' +
216
+ '<input type="radio" id="'+obj.id+'_view_list" name="view_mode_'+obj.id+'" checked="checked" /><label class="plupload_button" for="'+obj.id+'_view_list" data-view="list">' + _('List') + '</label>' +
217
+ '<input type="radio" id="'+obj.id+'_view_thumbs" name="view_mode_'+obj.id+'" /><label class="plupload_button" for="'+obj.id+'_view_thumbs" data-view="thumbs">' + _('Thumbnails') + '</label>' +
218
+ '</div>' +
219
+ '</div>' +
220
+ '</div>' +
221
+
222
+ '<table class="plupload_filelist plupload_filelist_header ui-widget-header">' +
223
+ '<tr>' +
224
+ '<td class="plupload_cell plupload_file_name">' + _('Filename') + '</td>' +
225
+ '<td class="plupload_cell plupload_file_status">' + _('Status') + '</td>' +
226
+ '<td class="plupload_cell plupload_file_size">' + _('Size') + '</td>' +
227
+ '<td class="plupload_cell plupload_file_action">&nbsp;</td>' +
228
+ '</tr>' +
229
+ '</table>' +
230
+
231
+ '<div class="plupload_content">' +
232
+ '<div class="plupload_droptext">' + _("Drag files here.") + '</div>' +
233
+ '<ul class="plupload_filelist_content"> </ul>' +
234
+ '<div class="plupload_clearer">&nbsp;</div>' +
235
+ '</div>' +
236
+
237
+ '<table class="plupload_filelist plupload_filelist_footer ui-widget-header">' +
238
+ '<tr>' +
239
+ '<td class="plupload_cell plupload_file_name">' +
240
+ '<div class="plupload_buttons"><!-- Visible -->' +
241
+ '<a class="plupload_button plupload_add">' + _('Add Files') + '</a>&nbsp;' +
242
+ '<a class="plupload_button plupload_start">' + _('Start Upload') + '</a>&nbsp;' +
243
+ '<a class="plupload_button plupload_stop plupload_hidden">'+_('Stop Upload') + '</a>&nbsp;' +
244
+ '</div>' +
245
+
246
+ '<div class="plupload_started plupload_hidden"><!-- Hidden -->' +
247
+ '<div class="plupload_progress plupload_right">' +
248
+ '<div class="plupload_progress_container"></div>' +
249
+ '</div>' +
250
+
251
+ '<div class="plupload_cell plupload_upload_status"></div>' +
252
+
253
+ '<div class="plupload_clearer">&nbsp;</div>' +
254
+ '</div>' +
255
+ '</td>' +
256
+ '<td class="plupload_file_status"><span class="plupload_total_status">0%</span></td>' +
257
+ '<td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td>' +
258
+ '<td class="plupload_file_action"></td>' +
259
+ '</tr>' +
260
+ '</table>' +
261
+
262
+ '</div>' +
263
+ '<input class="plupload_count" value="0" type="hidden">' +
264
+ '</div>'
265
+ );
266
+ }
267
+
268
+
269
+ $.widget("ui.plupload", {
270
+
271
+ widgetEventPrefix: '',
272
+
273
+ contents_bak: '',
274
+
275
+ options: {
276
+ browse_button_hover: 'ui-state-hover',
277
+ browse_button_active: 'ui-state-active',
278
+
279
+ // widget specific
280
+ dragdrop : true,
281
+ multiple_queues: true, // re-use widget by default
282
+ buttons: {
283
+ browse: true,
284
+ start: true,
285
+ stop: true
286
+ },
287
+ views: {
288
+ list: true,
289
+ thumbs: false,
290
+ active: 'list',
291
+ remember: true // requires: https://github.com/carhartl/jquery-cookie, otherwise disabled even if set to true
292
+ },
293
+ autostart: false,
294
+ sortable: false,
295
+ rename: false,
296
+ max_file_count: 0 // unlimited
297
+ },
298
+
299
+ FILE_COUNT_ERROR: -9001,
300
+
301
+ _create: function() {
302
+ var id = this.element.attr('id');
303
+ if (!id) {
304
+ id = plupload.guid();
305
+ this.element.attr('id', id);
306
+ }
307
+ this.id = id;
308
+
309
+ // backup the elements initial state
310
+ this.contents_bak = this.element.html();
311
+ renderUI(this.element);
312
+
313
+ // container, just in case
314
+ this.container = $('.plupload_container', this.element).attr('id', id + '_container');
315
+
316
+ this.content = $('.plupload_content', this.element);
317
+
318
+ if ($.fn.resizable) {
319
+ this.container.resizable({
320
+ handles: 's',
321
+ minHeight: 300
322
+ });
323
+ }
324
+
325
+ // list of files, may become sortable
326
+ this.filelist = $('.plupload_filelist_content', this.container)
327
+ .attr({
328
+ id: id + '_filelist',
329
+ unselectable: 'on'
330
+ });
331
+
332
+
333
+ // buttons
334
+ this.browse_button = $('.plupload_add', this.container).attr('id', id + '_browse');
335
+ this.start_button = $('.plupload_start', this.container).attr('id', id + '_start');
336
+ this.stop_button = $('.plupload_stop', this.container).attr('id', id + '_stop');
337
+ this.thumbs_switcher = $('#' + id + '_view_thumbs');
338
+ this.list_switcher = $('#' + id + '_view_list');
339
+
340
+ if ($.ui.button) {
341
+ this.browse_button.button({
342
+ icons: { primary: 'ui-icon-circle-plus' },
343
+ disabled: true
344
+ });
345
+
346
+ this.start_button.button({
347
+ icons: { primary: 'ui-icon-circle-arrow-e' },
348
+ disabled: true
349
+ });
350
+
351
+ this.stop_button.button({
352
+ icons: { primary: 'ui-icon-circle-close' }
353
+ });
354
+
355
+ this.list_switcher.button({
356
+ text: false,
357
+ icons: { secondary: "ui-icon-grip-dotted-horizontal" }
358
+ });
359
+
360
+ this.thumbs_switcher.button({
361
+ text: false,
362
+ icons: { secondary: "ui-icon-image" }
363
+ });
364
+ }
365
+
366
+ // progressbar
367
+ this.progressbar = $('.plupload_progress_container', this.container);
368
+
369
+ if ($.ui.progressbar) {
370
+ this.progressbar.progressbar();
371
+ }
372
+
373
+ // counter
374
+ this.counter = $('.plupload_count', this.element)
375
+ .attr({
376
+ id: id + '_count',
377
+ name: id + '_count'
378
+ });
379
+
380
+ // initialize uploader instance
381
+ this._initUploader();
382
+ },
383
+
384
+ _initUploader: function() {
385
+ var self = this
386
+ , id = this.id
387
+ , uploader
388
+ , options = {
389
+ container: id + '_buttons',
390
+ browse_button: id + '_browse'
391
+ }
392
+ ;
393
+
394
+ $('.plupload_buttons', this.element).attr('id', id + '_buttons');
395
+
396
+ if (self.options.dragdrop) {
397
+ this.filelist.parent().attr('id', this.id + '_dropbox');
398
+ options.drop_element = this.id + '_dropbox';
399
+ }
400
+
401
+ uploader = this.uploader = uploaders[id] = new plupload.Uploader($.extend(this.options, options));
402
+
403
+ if (self.options.views.thumbs) {
404
+ uploader.settings.required_features.display_media = true;
405
+ }
406
+
407
+
408
+ uploader.bind('Error', function(up, err) {
409
+ var message, details = "";
410
+
411
+ message = '<strong>' + err.message + '</strong>';
412
+
413
+ switch (err.code) {
414
+ case plupload.FILE_EXTENSION_ERROR:
415
+ details = o.sprintf(_("File: %s"), err.file.name);
416
+ break;
417
+
418
+ case plupload.FILE_SIZE_ERROR:
419
+ details = o.sprintf(_("File: %s, size: %d, max file size: %d"), err.file.name, err.file.size, plupload.parseSize(self.options.max_file_size));
420
+ break;
421
+
422
+ case plupload.FILE_DUPLICATE_ERROR:
423
+ details = o.sprintf(_("%s already present in the queue."), err.file.name);
424
+ break;
425
+
426
+ case self.FILE_COUNT_ERROR:
427
+ details = o.sprintf(_("Upload element accepts only %d file(s) at a time. Extra files were stripped."), self.options.max_file_count);
428
+ break;
429
+
430
+ case plupload.IMAGE_FORMAT_ERROR :
431
+ details = _("Image format either wrong or not supported.");
432
+ break;
433
+
434
+ case plupload.IMAGE_MEMORY_ERROR :
435
+ details = _("Runtime ran out of available memory.");
436
+ break;
437
+
438
+ /* // This needs a review
439
+ case plupload.IMAGE_DIMENSIONS_ERROR :
440
+ details = o.sprintf(_('Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.'), up.runtime, up.features.maxWidth, up.features.maxHeight);
441
+ break; */
442
+
443
+ case plupload.HTTP_ERROR:
444
+ details = _("Upload URL might be wrong or doesn't exist.");
445
+ break;
446
+ }
447
+
448
+ message += " <br /><i>" + details + "</i>";
449
+
450
+ self._trigger('error', null, { up: up, error: err } );
451
+
452
+ // do not show UI if no runtime can be initialized
453
+ if (err.code === plupload.INIT_ERROR) {
454
+ setTimeout(function() {
455
+ self.destroy();
456
+ }, 1);
457
+ } else {
458
+ self.notify('error', message);
459
+ }
460
+ });
461
+
462
+
463
+ uploader.bind('PostInit', function(up) {
464
+ // all buttons are optional, so they can be disabled and hidden
465
+ if (!self.options.buttons.browse) {
466
+ self.browse_button.button('disable').hide();
467
+ up.disableBrowse(true);
468
+ } else {
469
+ self.browse_button.button('enable');
470
+ }
471
+
472
+ if (!self.options.buttons.start) {
473
+ self.start_button.button('disable').hide();
474
+ }
475
+
476
+ if (!self.options.buttons.stop) {
477
+ self.stop_button.button('disable').hide();
478
+ }
479
+
480
+ if (!self.options.unique_names && self.options.rename) {
481
+ self._enableRenaming();
482
+ }
483
+
484
+ if (self.options.dragdrop && up.features.dragdrop) {
485
+ self.filelist.parent().addClass('plupload_dropbox');
486
+ }
487
+
488
+ self._enableViewSwitcher();
489
+
490
+ self.start_button.click(function(e) {
491
+ if (!$(this).button('option', 'disabled')) {
492
+ self.start();
493
+ }
494
+ e.preventDefault();
495
+ });
496
+
497
+ self.stop_button.click(function(e) {
498
+ self.stop();
499
+ e.preventDefault();
500
+ });
501
+
502
+ self._trigger('ready', null, { up: up });
503
+ });
504
+
505
+
506
+ // check if file count doesn't exceed the limit
507
+ if (self.options.max_file_count) {
508
+ self.options.multiple_queues = false; // one go only
509
+
510
+ uploader.bind('FilesAdded', function(up, selectedFiles) {
511
+ var selectedCount = selectedFiles.length
512
+ , extraCount = up.files.length + selectedCount - self.options.max_file_count
513
+ ;
514
+
515
+ if (extraCount > 0) {
516
+ selectedFiles.splice(selectedCount - extraCount, extraCount);
517
+
518
+ up.trigger('Error', {
519
+ code : self.FILE_COUNT_ERROR,
520
+ message : _('File count error.')
521
+ });
522
+ }
523
+ });
524
+ }
525
+
526
+ // uploader internal events must run first
527
+ uploader.init();
528
+
529
+ uploader.bind('FileFiltered', function(up, file) {
530
+ self._addFiles(file);
531
+ });
532
+
533
+ uploader.bind('FilesAdded', function(up, files) {
534
+ self._trigger('selected', null, { up: up, files: files } );
535
+
536
+ // re-enable sortable
537
+ if (self.options.sortable && $.ui.sortable) {
538
+ self._enableSortingList();
539
+ }
540
+
541
+ self._trigger('updatelist', null, { filelist: self.filelist });
542
+
543
+ if (self.options.autostart) {
544
+ // set a little delay to make sure that QueueChanged triggered by the core has time to complete
545
+ setTimeout(function() {
546
+ self.start();
547
+ }, 10);
548
+ }
549
+ });
550
+
551
+ uploader.bind('FilesRemoved', function(up, files) {
552
+ self._trigger('removed', null, { up: up, files: files } );
553
+ });
554
+
555
+ uploader.bind('QueueChanged StateChanged', function() {
556
+ self._handleState();
557
+ });
558
+
559
+ uploader.bind('UploadFile', function(up, file) {
560
+ self._handleFileStatus(file);
561
+ });
562
+
563
+ uploader.bind('FileUploaded', function(up, file) {
564
+ self._handleFileStatus(file);
565
+ self._trigger('uploaded', null, { up: up, file: file } );
566
+ });
567
+
568
+ uploader.bind('UploadProgress', function(up, file) {
569
+ self._handleFileStatus(file);
570
+ self._updateTotalProgress();
571
+ self._trigger('progress', null, { up: up, file: file } );
572
+ });
573
+
574
+ uploader.bind('UploadComplete', function(up, files) {
575
+ self._addFormFields();
576
+ self._trigger('complete', null, { up: up, files: files } );
577
+ });
578
+ },
579
+
580
+
581
+ _setOption: function(key, value) {
582
+ var self = this;
583
+
584
+ if (key == 'buttons' && typeof(value) == 'object') {
585
+ value = $.extend(self.options.buttons, value);
586
+
587
+ if (!value.browse) {
588
+ self.browse_button.button('disable').hide();
589
+ self.uploader.disableBrowse(true);
590
+ } else {
591
+ self.browse_button.button('enable').show();
592
+ self.uploader.disableBrowse(false);
593
+ }
594
+
595
+ if (!value.start) {
596
+ self.start_button.button('disable').hide();
597
+ } else {
598
+ self.start_button.button('enable').show();
599
+ }
600
+
601
+ if (!value.stop) {
602
+ self.stop_button.button('disable').hide();
603
+ } else {
604
+ self.start_button.button('enable').show();
605
+ }
606
+ }
607
+
608
+ self.uploader.settings[key] = value;
609
+ },
610
+
611
+
612
+ /**
613
+ Start upload. Triggers `start` event.
614
+
615
+ @method start
616
+ */
617
+ start: function() {
618
+ this.uploader.start();
619
+ this._trigger('start', null, { up: this.uploader });
620
+ },
621
+
622
+
623
+ /**
624
+ Stop upload. Triggers `stop` event.
625
+
626
+ @method stop
627
+ */
628
+ stop: function() {
629
+ this.uploader.stop();
630
+ this._trigger('stop', null, { up: this.uploader });
631
+ },
632
+
633
+
634
+ /**
635
+ Enable browse button.
636
+
637
+ @method enable
638
+ */
639
+ enable: function() {
640
+ this.browse_button.button('enable');
641
+ this.uploader.disableBrowse(false);
642
+ },
643
+
644
+
645
+ /**
646
+ Disable browse button.
647
+
648
+ @method disable
649
+ */
650
+ disable: function() {
651
+ this.browse_button.button('disable');
652
+ this.uploader.disableBrowse(true);
653
+ },
654
+
655
+
656
+ /**
657
+ Retrieve file by it's unique id.
658
+
659
+ @method getFile
660
+ @param {String} id Unique id of the file
661
+ @return {plupload.File}
662
+ */
663
+ getFile: function(id) {
664
+ var file;
665
+
666
+ if (typeof id === 'number') {
667
+ file = this.uploader.files[id];
668
+ } else {
669
+ file = this.uploader.getFile(id);
670
+ }
671
+ return file;
672
+ },
673
+
674
+ /**
675
+ Return array of files currently in the queue.
676
+
677
+ @method getFiles
678
+ @return {Array} Array of files in the queue represented by plupload.File objects
679
+ */
680
+ getFiles: function() {
681
+ return this.uploader.files;
682
+ },
683
+
684
+
685
+ /**
686
+ Remove the file from the queue.
687
+
688
+ @method removeFile
689
+ @param {plupload.File|String} file File to remove, might be specified directly or by it's unique id
690
+ */
691
+ removeFile: function(file) {
692
+ if (plupload.typeOf(file) === 'string') {
693
+ file = this.getFile(file);
694
+ }
695
+ this._removeFiles(file);
696
+ },
697
+
698
+
699
+ /**
700
+ Clear the file queue.
701
+
702
+ @method clearQueue
703
+ */
704
+ clearQueue: function() {
705
+ this.uploader.splice();
706
+ },
707
+
708
+
709
+ /**
710
+ Retrieve internal plupload.Uploader object (usually not required).
711
+
712
+ @method getUploader
713
+ @return {plupload.Uploader}
714
+ */
715
+ getUploader: function() {
716
+ return this.uploader;
717
+ },
718
+
719
+
720
+ /**
721
+ Trigger refresh procedure, specifically browse_button re-measure and re-position operations.
722
+ Might get handy, when UI Widget is placed within the popup, that is constantly hidden and shown
723
+ again - without calling this method after each show operation, dialog trigger might get displaced
724
+ and disfunctional.
725
+
726
+ @method refresh
727
+ */
728
+ refresh: function() {
729
+ this.uploader.refresh();
730
+ },
731
+
732
+
733
+ /**
734
+ Display a message in notification area.
735
+
736
+ @method notify
737
+ @param {Enum} type Type of the message, either `error` or `info`
738
+ @param {String} message The text message to display.
739
+ */
740
+ notify: function(type, message) {
741
+ var popup = $(
742
+ '<div class="plupload_message">' +
743
+ '<span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+_('Close')+'"></span>' +
744
+ '<p><span class="ui-icon"></span>' + message + '</p>' +
745
+ '</div>'
746
+ );
747
+
748
+ popup
749
+ .addClass('ui-state-' + (type === 'error' ? 'error' : 'highlight'))
750
+ .find('p .ui-icon')
751
+ .addClass('ui-icon-' + (type === 'error' ? 'alert' : 'info'))
752
+ .end()
753
+ .find('.plupload_message_close')
754
+ .click(function() {
755
+ popup.remove();
756
+ })
757
+ .end();
758
+
759
+ $('.plupload_header', this.container).append(popup);
760
+ },
761
+
762
+
763
+ /**
764
+ Destroy the widget, the uploader, free associated resources and bring back original html.
765
+
766
+ @method destroy
767
+ */
768
+ destroy: function() {
769
+ this._removeFiles([].slice.call(this.uploader.files));
770
+
771
+ // destroy uploader instance
772
+ this.uploader.destroy();
773
+
774
+ // unbind all button events
775
+ $('.plupload_button', this.element).unbind();
776
+
777
+ // destroy buttons
778
+ if ($.ui.button) {
779
+ $('.plupload_add, .plupload_start, .plupload_stop', this.container)
780
+ .button('destroy');
781
+ }
782
+
783
+ // destroy progressbar
784
+ if ($.ui.progressbar) {
785
+ this.progressbar.progressbar('destroy');
786
+ }
787
+
788
+ // destroy sortable behavior
789
+ if ($.ui.sortable && this.options.sortable) {
790
+ $('tbody', this.filelist).sortable('destroy');
791
+ }
792
+
793
+ // restore the elements initial state
794
+ this.element
795
+ .empty()
796
+ .html(this.contents_bak);
797
+ this.contents_bak = '';
798
+
799
+ $.Widget.prototype.destroy.apply(this);
800
+ },
801
+
802
+
803
+ _handleState: function() {
804
+ var up = this.uploader;
805
+
806
+ if (up.state === plupload.STARTED) {
807
+ $(this.start_button).button('disable');
808
+
809
+ $([])
810
+ .add(this.stop_button)
811
+ .add('.plupload_started')
812
+ .removeClass('plupload_hidden');
813
+
814
+ $('.plupload_upload_status', this.element).html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
815
+ $('.plupload_header_content', this.element).addClass('plupload_header_content_bw');
816
+ } else if (up.state === plupload.STOPPED) {
817
+ $([])
818
+ .add(this.stop_button)
819
+ .add('.plupload_started')
820
+ .addClass('plupload_hidden');
821
+
822
+ if (this.options.multiple_queues) {
823
+ $('.plupload_header_content', this.element).removeClass('plupload_header_content_bw');
824
+ } else {
825
+ $([])
826
+ .add(this.browse_button)
827
+ .add(this.start_button)
828
+ .button('disable');
829
+
830
+ up.disableBrowse();
831
+ }
832
+
833
+ if (up.files.length === (up.total.uploaded + up.total.failed)) {
834
+ this.start_button.button('disable');
835
+ } else {
836
+ this.start_button.button('enable');
837
+ }
838
+
839
+ this._updateTotalProgress();
840
+ }
841
+
842
+ if (up.total.queued === 0) {
843
+ $('.ui-button-text', this.browse_button).html(_('Add Files'));
844
+ } else {
845
+ $('.ui-button-text', this.browse_button).html(o.sprintf(_('%d files queued'), up.total.queued));
846
+ }
847
+
848
+ up.refresh();
849
+ },
850
+
851
+
852
+ _handleFileStatus: function(file) {
853
+ var self = this, actionClass, iconClass;
854
+
855
+ // since this method might be called asynchronously, file row might not yet be rendered
856
+ if (!$('#' + file.id).length) {
857
+ return;
858
+ }
859
+
860
+ switch (file.status) {
861
+ case plupload.DONE:
862
+ actionClass = 'plupload_done';
863
+ iconClass = 'ui-icon ui-icon-circle-check';
864
+ break;
865
+
866
+ case plupload.FAILED:
867
+ actionClass = 'ui-state-error plupload_failed';
868
+ iconClass = 'ui-icon ui-icon-alert';
869
+ break;
870
+
871
+ case plupload.QUEUED:
872
+ actionClass = 'plupload_delete';
873
+ iconClass = 'ui-icon ui-icon-circle-minus';
874
+ break;
875
+
876
+ case plupload.UPLOADING:
877
+ actionClass = 'ui-state-highlight plupload_uploading';
878
+ iconClass = 'ui-icon ui-icon-circle-arrow-w';
879
+
880
+ // scroll uploading file into the view if its bottom boundary is out of it
881
+ var scroller = $('.plupload_scroll', this.container)
882
+ , scrollTop = scroller.scrollTop()
883
+ , scrollerHeight = scroller.height()
884
+ , rowOffset = $('#' + file.id).position().top + $('#' + file.id).height()
885
+ ;
886
+
887
+ if (scrollerHeight < rowOffset) {
888
+ scroller.scrollTop(scrollTop + rowOffset - scrollerHeight);
889
+ }
890
+
891
+ // Set file specific progress
892
+ $('#' + file.id)
893
+ .find('.plupload_file_percent')
894
+ .html(file.percent + '%')
895
+ .end()
896
+ .find('.plupload_file_progress')
897
+ .css('width', file.percent + '%')
898
+ .end()
899
+ .find('.plupload_file_size')
900
+ .html(plupload.formatSize(file.size));
901
+ break;
902
+ }
903
+ actionClass += ' ui-state-default plupload_file';
904
+
905
+ $('#' + file.id)
906
+ .attr('class', actionClass)
907
+ .find('.ui-icon')
908
+ .attr('class', iconClass)
909
+ .end()
910
+ .filter('.plupload_delete, .plupload_done, .plupload_failed')
911
+ .find('.ui-icon')
912
+ .click(function(e) {
913
+ self._removeFiles(file);
914
+ e.preventDefault();
915
+ });
916
+ },
917
+
918
+
919
+ _updateTotalProgress: function() {
920
+ var up = this.uploader;
921
+
922
+ // Scroll to end of file list
923
+ this.filelist[0].scrollTop = this.filelist[0].scrollHeight;
924
+
925
+ this.progressbar.progressbar('value', up.total.percent);
926
+
927
+ this.element
928
+ .find('.plupload_total_status')
929
+ .html(up.total.percent + '%')
930
+ .end()
931
+ .find('.plupload_total_file_size')
932
+ .html(plupload.formatSize(up.total.size))
933
+ .end()
934
+ .find('.plupload_upload_status')
935
+ .html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
936
+ },
937
+
938
+
939
+ _displayThumbs: function() {
940
+ var self = this
941
+ , tw, th // thumb width/height
942
+ , cols
943
+ , num = 0 // number of simultaneously visible thumbs
944
+ , thumbs = [] // array of thumbs to preload at any given moment
945
+ , loading = false
946
+ ;
947
+
948
+ if (!this.options.views.thumbs) {
949
+ return;
950
+ }
951
+
952
+
953
+ function onLast(el, eventName, cb) {
954
+ var timer;
955
+
956
+ el.on(eventName, function() {
957
+ clearTimeout(timer);
958
+ timer = setTimeout(function() {
959
+ clearTimeout(timer);
960
+ cb();
961
+ }, 300);
962
+ });
963
+ }
964
+
965
+
966
+ // calculate number of simultaneously visible thumbs
967
+ function measure() {
968
+ if (!tw || !th) {
969
+ var wrapper = $('.plupload_file:eq(0)', self.filelist);
970
+ tw = wrapper.outerWidth(true);
971
+ th = wrapper.outerHeight(true);
972
+ }
973
+
974
+ var aw = self.content.width(), ah = self.content.height();
975
+ cols = Math.floor(aw / tw);
976
+ num = cols * (Math.ceil(ah / th) + 1);
977
+ }
978
+
979
+
980
+ function pickThumbsToLoad() {
981
+ // calculate index of virst visible thumb
982
+ var startIdx = Math.floor(self.content.scrollTop() / th) * cols;
983
+ // get potentially visible thumbs that are not yet visible
984
+ thumbs = $('.plupload_file', self.filelist)
985
+ .slice(startIdx, startIdx + num)
986
+ .filter(':not(.plupload_file_thumb_loaded)')
987
+ .get();
988
+ }
989
+
990
+
991
+ function init() {
992
+ function mpl() {
993
+ if (self.view_mode !== 'thumbs') {
994
+ return;
995
+ }
996
+ measure();
997
+ pickThumbsToLoad();
998
+ lazyLoad();
999
+ }
1000
+
1001
+ if ($.fn.resizable) {
1002
+ onLast(self.container, 'resize', mpl);
1003
+ }
1004
+
1005
+ onLast(self.window, 'resize', mpl);
1006
+ onLast(self.content, 'scroll', mpl);
1007
+
1008
+ self.element.on('viewchanged selected', mpl);
1009
+
1010
+ mpl();
1011
+ }
1012
+
1013
+
1014
+ function preloadThumb(file, cb) {
1015
+ var img = new o.Image();
1016
+
1017
+ img.onload = function() {
1018
+ var thumb = $('#' + file.id + ' .plupload_file_thumb', self.filelist).html('');
1019
+ this.embed(thumb[0], {
1020
+ width: 100,
1021
+ height: 60,
1022
+ crop: true,
1023
+ swf_url: o.resolveUrl(self.options.flash_swf_url),
1024
+ xap_url: o.resolveUrl(self.options.silverlight_xap_url)
1025
+ });
1026
+ };
1027
+
1028
+ img.bind("embedded error", function() {
1029
+ $('#' + file.id, self.filelist).addClass('plupload_file_thumb_loaded');
1030
+ this.destroy();
1031
+ setTimeout(cb, 1); // detach, otherwise ui might hang (in SilverLight for example)
1032
+ });
1033
+
1034
+ img.load(file.getSource());
1035
+ }
1036
+
1037
+
1038
+ function lazyLoad() {
1039
+ if (self.view_mode !== 'thumbs' || loading) {
1040
+ return;
1041
+ }
1042
+
1043
+ pickThumbsToLoad();
1044
+ if (!thumbs.length) {
1045
+ return;
1046
+ }
1047
+
1048
+ loading = true;
1049
+
1050
+ preloadThumb(self.getFile($(thumbs.shift()).attr('id')), function() {
1051
+ loading = false;
1052
+ lazyLoad();
1053
+ });
1054
+ }
1055
+
1056
+ // this has to run only once to measure structures and bind listeners
1057
+ this.element.on('selected', function onselected() {
1058
+ self.element.off('selected', onselected);
1059
+ init();
1060
+ });
1061
+ },
1062
+
1063
+
1064
+ _addFiles: function(files) {
1065
+ var self = this, file_html;
1066
+
1067
+ file_html = '<li class="plupload_file ui-state-default" id="%id%">' +
1068
+ '<div class="plupload_file_thumb">' +
1069
+ '<div class="plupload_file_dummy ui-widget-content"><span class="ui-state-disabled">%ext%</span></div>' +
1070
+ '</div>' +
1071
+ '<div class="plupload_file_name" title="%name%"><span class="plupload_file_namespan">%name%</span></div>' +
1072
+ '<div class="plupload_file_action"><div class="ui-icon"> </div></div>' +
1073
+ '<div class="plupload_file_size">%size% </div>' +
1074
+ '<div class="plupload_file_status">' +
1075
+ '<div class="plupload_file_progress ui-widget-header" style="width: 0%"> </div>' +
1076
+ '<span class="plupload_file_percent">%percent% </span>' +
1077
+ '</div>' +
1078
+ '<div class="plupload_file_fields"> </div>' +
1079
+ '</li>';
1080
+
1081
+ if (plupload.typeOf(files) !== 'array') {
1082
+ files = [files];
1083
+ }
1084
+
1085
+ $.each(files, function(i, file) {
1086
+ var ext = o.Mime.getFileExtension(file.name) || 'none';
1087
+
1088
+ self.filelist.append(file_html.replace(/%(\w+)%/g, function($0, $1) {
1089
+ if ('size' === $1) {
1090
+ return plupload.formatSize(file.size);
1091
+ } else if ('ext' === $1) {
1092
+ return ext;
1093
+ } else {
1094
+ return file[$1] || '';
1095
+ }
1096
+ }));
1097
+
1098
+ self._handleFileStatus(file);
1099
+ });
1100
+ },
1101
+
1102
+
1103
+ _removeFiles: function(files) {
1104
+ var self = this, up = this.uploader;
1105
+
1106
+ if (plupload.typeOf(files) !== 'array') {
1107
+ files = [files];
1108
+ }
1109
+
1110
+ // destroy sortable if enabled
1111
+ if ($.ui.sortable && this.options.sortable) {
1112
+ $('tbody', self.filelist).sortable('destroy');
1113
+ }
1114
+
1115
+ $.each(files, function(i, file) {
1116
+ $('#' + file.id).toggle("highlight", function() {
1117
+ this.remove();
1118
+ });
1119
+ up.removeFile(file);
1120
+ });
1121
+
1122
+
1123
+ if (up.files.length) {
1124
+ // re-initialize sortable
1125
+ if (this.options.sortable && $.ui.sortable) {
1126
+ this._enableSortingList();
1127
+ }
1128
+ }
1129
+
1130
+ this._trigger('updatelist', null, { filelist: this.filelist });
1131
+ },
1132
+
1133
+
1134
+ _addFormFields: function() {
1135
+ var self = this;
1136
+
1137
+ // re-add from fresh
1138
+ $('.plupload_file_fields', this.filelist).html('');
1139
+
1140
+ plupload.each(this.uploader.files, function(file, count) {
1141
+ var fields = ''
1142
+ , id = self.id + '_' + count
1143
+ ;
1144
+
1145
+ if (file.target_name) {
1146
+ fields += '<input type="hidden" name="' + id + '_tmpname" value="'+plupload.xmlEncode(file.target_name)+'" />';
1147
+ }
1148
+ fields += '<input type="hidden" name="' + id + '_name" value="'+plupload.xmlEncode(file.name)+'" />';
1149
+ fields += '<input type="hidden" name="' + id + '_status" value="' + (file.status === plupload.DONE ? 'done' : 'failed') + '" />';
1150
+
1151
+ $('#' + file.id).find('.plupload_file_fields').html(fields);
1152
+ });
1153
+
1154
+ this.counter.val(this.uploader.files.length);
1155
+ },
1156
+
1157
+
1158
+ _viewChanged: function(view) {
1159
+ // update or write a new cookie
1160
+ if (this.options.views.remember && $.cookie) {
1161
+ $.cookie('plupload_ui_view', view, { expires: 7, path: '/' });
1162
+ }
1163
+
1164
+ // ugly fix for IE6 - make content area stretchable
1165
+ if (o.Env.browser === 'IE' && o.Env.version < 7) {
1166
+ this.content.attr('style', 'height:expression(document.getElementById("' + this.id + '_container' + '").clientHeight - ' + (view === 'list' ? 133 : 103) + ');');
1167
+ }
1168
+
1169
+ this.container.removeClass('plupload_view_list plupload_view_thumbs').addClass('plupload_view_' + view);
1170
+ this.view_mode = view;
1171
+ this._trigger('viewchanged', null, { view: view });
1172
+ },
1173
+
1174
+
1175
+ _enableViewSwitcher: function() {
1176
+ var self = this
1177
+ , view
1178
+ , switcher = $('.plupload_view_switch', this.container)
1179
+ , buttons
1180
+ , button
1181
+ ;
1182
+
1183
+ plupload.each(['list', 'thumbs'], function(view) {
1184
+ if (!self.options.views[view]) {
1185
+ switcher.find('[for="' + self.id + '_view_' + view + '"], #'+ self.id +'_view_' + view).remove();
1186
+ }
1187
+ });
1188
+
1189
+ // check if any visible left
1190
+ buttons = switcher.find('.plupload_button');
1191
+
1192
+ if (buttons.length === 1) {
1193
+ switcher.hide();
1194
+ view = buttons.eq(0).data('view');
1195
+ this._viewChanged(view);
1196
+ } else if ($.ui.button && buttons.length > 1) {
1197
+ if (this.options.views.remember && $.cookie) {
1198
+ view = $.cookie('plupload_ui_view');
1199
+ }
1200
+
1201
+ // if wierd case, bail out to default
1202
+ if (!~plupload.inArray(view, ['list', 'thumbs'])) {
1203
+ view = this.options.views.active;
1204
+ }
1205
+
1206
+ switcher
1207
+ .show()
1208
+ .buttonset()
1209
+ .find('.ui-button')
1210
+ .click(function(e) {
1211
+ view = $(this).data('view');
1212
+ self._viewChanged(view);
1213
+ e.preventDefault(); // avoid auto scrolling to widget in IE and FF (see #850)
1214
+ });
1215
+
1216
+ // if view not active - happens when switcher wasn't clicked manually
1217
+ button = switcher.find('[for="' + self.id + '_view_'+view+'"]');
1218
+ if (button.length) {
1219
+ button.trigger('click');
1220
+ }
1221
+ } else {
1222
+ switcher.show();
1223
+ this._viewChanged(this.options.views.active);
1224
+ }
1225
+
1226
+ // initialize thumb viewer if requested
1227
+ if (this.options.views.thumbs) {
1228
+ this._displayThumbs();
1229
+ }
1230
+ },
1231
+
1232
+
1233
+ _enableRenaming: function() {
1234
+ var self = this;
1235
+
1236
+ this.filelist.dblclick(function(e) {
1237
+ var nameSpan = $(e.target), nameInput, file, parts, name, ext = "";
1238
+
1239
+ if (!nameSpan.hasClass('plupload_file_namespan')) {
1240
+ return;
1241
+ }
1242
+
1243
+ // Get file name and split out name and extension
1244
+ file = self.uploader.getFile(nameSpan.closest('.plupload_file')[0].id);
1245
+ name = file.name;
1246
+ parts = /^(.+)(\.[^.]+)$/.exec(name);
1247
+ if (parts) {
1248
+ name = parts[1];
1249
+ ext = parts[2];
1250
+ }
1251
+
1252
+ // Display input element
1253
+ nameInput = $('<input class="plupload_file_rename" type="text" />').width(nameSpan.width()).insertAfter(nameSpan.hide());
1254
+ nameInput.val(name).blur(function() {
1255
+ nameSpan.show().parent().scrollLeft(0).end().next().remove();
1256
+ }).keydown(function(e) {
1257
+ var nameInput = $(this);
1258
+
1259
+ if ($.inArray(e.keyCode, [13, 27]) !== -1) {
1260
+ e.preventDefault();
1261
+
1262
+ // Rename file and glue extension back on
1263
+ if (e.keyCode === 13) {
1264
+ file.name = nameInput.val() + ext;
1265
+ nameSpan.html(file.name);
1266
+ }
1267
+ nameInput.blur();
1268
+ }
1269
+ })[0].focus();
1270
+ });
1271
+ },
1272
+
1273
+
1274
+ _enableSortingList: function() {
1275
+ var self = this;
1276
+
1277
+ if ($('.plupload_file', this.filelist).length < 2) {
1278
+ return;
1279
+ }
1280
+
1281
+ // destroy sortable if enabled
1282
+ $('tbody', this.filelist).sortable('destroy');
1283
+
1284
+ // enable
1285
+ this.filelist.sortable({
1286
+ items: '.plupload_delete',
1287
+
1288
+ cancel: 'object, .plupload_clearer',
1289
+
1290
+ stop: function() {
1291
+ var files = [];
1292
+
1293
+ $.each($(this).sortable('toArray'), function(i, id) {
1294
+ files[files.length] = self.uploader.getFile(id);
1295
+ });
1296
+
1297
+ files.unshift(files.length);
1298
+ files.unshift(0);
1299
+
1300
+ // re-populate files array
1301
+ Array.prototype.splice.apply(self.uploader.files, files);
1302
+ }
1303
+ });
1304
+ }
1305
+ });
1306
+
1307
+ } (window, document, plupload, mOxie, jQuery));
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/jquery.ui.plupload/jquery.ui.plupload.min.js ADDED
@@ -0,0 +1 @@
 
1
+ ;(function(e,t,n,r,i){function o(e){return n.translate(e)||e}function u(e){e.id=e.attr("id"),e.html('<div class="plupload_wrapper"><div class="ui-widget-content plupload_container"><div class="ui-state-default ui-widget-header plupload_header"><div class="plupload_header_content"><div class="plupload_logo"> </div><div class="plupload_header_title">'+o("Select files")+"</div>"+'<div class="plupload_header_text">'+o("Add files to the upload queue and click the start button.")+"</div>"+'<div class="plupload_view_switch">'+'<input type="radio" id="'+e.id+'_view_list" name="view_mode_'+e.id+'" checked="checked" /><label class="plupload_button" for="'+e.id+'_view_list" data-view="list">'+o("List")+"</label>"+'<input type="radio" id="'+e.id+'_view_thumbs" name="view_mode_'+e.id+'" /><label class="plupload_button" for="'+e.id+'_view_thumbs" data-view="thumbs">'+o("Thumbnails")+"</label>"+"</div>"+"</div>"+"</div>"+'<table class="plupload_filelist plupload_filelist_header ui-widget-header">'+"<tr>"+'<td class="plupload_cell plupload_file_name">'+o("Filename")+"</td>"+'<td class="plupload_cell plupload_file_status">'+o("Status")+"</td>"+'<td class="plupload_cell plupload_file_size">'+o("Size")+"</td>"+'<td class="plupload_cell plupload_file_action">&nbsp;</td>'+"</tr>"+"</table>"+'<div class="plupload_content">'+'<div class="plupload_droptext">'+o("Drag files here.")+"</div>"+'<ul class="plupload_filelist_content"> </ul>'+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+'<table class="plupload_filelist plupload_filelist_footer ui-widget-header">'+"<tr>"+'<td class="plupload_cell plupload_file_name">'+'<div class="plupload_buttons"><!-- Visible -->'+'<a class="plupload_button plupload_add">'+o("Add Files")+"</a>&nbsp;"+'<a class="plupload_button plupload_start">'+o("Start Upload")+"</a>&nbsp;"+'<a class="plupload_button plupload_stop plupload_hidden">'+o("Stop Upload")+"</a>&nbsp;"+"</div>"+'<div class="plupload_started plupload_hidden"><!-- Hidden -->'+'<div class="plupload_progress plupload_right">'+'<div class="plupload_progress_container"></div>'+"</div>"+'<div class="plupload_cell plupload_upload_status"></div>'+'<div class="plupload_clearer">&nbsp;</div>'+"</div>"+"</td>"+'<td class="plupload_file_status"><span class="plupload_total_status">0%</span></td>'+'<td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td>'+'<td class="plupload_file_action"></td>'+"</tr>"+"</table>"+"</div>"+'<input class="plupload_count" value="0" type="hidden">'+"</div>")}var s={};i.widget("ui.plupload",{widgetEventPrefix:"",contents_bak:"",options:{browse_button_hover:"ui-state-hover",browse_button_active:"ui-state-active",dragdrop:!0,multiple_queues:!0,buttons:{browse:!0,start:!0,stop:!0},views:{list:!0,thumbs:!1,active:"list",remember:!0},autostart:!1,sortable:!1,rename:!1,max_file_count:0},FILE_COUNT_ERROR:-9001,_create:function(){var e=this.element.attr("id");e||(e=n.guid(),this.element.attr("id",e)),this.id=e,this.contents_bak=this.element.html(),u(this.element),this.container=i(".plupload_container",this.element).attr("id",e+"_container"),this.content=i(".plupload_content",this.element),i.fn.resizable&&this.container.resizable({handles:"s",minHeight:300}),this.filelist=i(".plupload_filelist_content",this.container).attr({id:e+"_filelist",unselectable:"on"}),this.browse_button=i(".plupload_add",this.container).attr("id",e+"_browse"),this.start_button=i(".plupload_start",this.container).attr("id",e+"_start"),this.stop_button=i(".plupload_stop",this.container).attr("id",e+"_stop"),this.thumbs_switcher=i("#"+e+"_view_thumbs"),this.list_switcher=i("#"+e+"_view_list"),i.ui.button&&(this.browse_button.button({icons:{primary:"ui-icon-circle-plus"},disabled:!0}),this.start_button.button({icons:{primary:"ui-icon-circle-arrow-e"},disabled:!0}),this.stop_button.button({icons:{primary:"ui-icon-circle-close"}}),this.list_switcher.button({text:!1,icons:{secondary:"ui-icon-grip-dotted-horizontal"}}),this.thumbs_switcher.button({text:!1,icons:{secondary:"ui-icon-image"}})),this.progressbar=i(".plupload_progress_container",this.container),i.ui.progressbar&&this.progressbar.progressbar(),this.counter=i(".plupload_count",this.element).attr({id:e+"_count",name:e+"_count"}),this._initUploader()},_initUploader:function(){var e=this,t=this.id,u,a={container:t+"_buttons",browse_button:t+"_browse"};i(".plupload_buttons",this.element).attr("id",t+"_buttons"),e.options.dragdrop&&(this.filelist.parent().attr("id",this.id+"_dropbox"),a.drop_element=this.id+"_dropbox"),u=this.uploader=s[t]=new n.Uploader(i.extend(this.options,a)),e.options.views.thumbs&&(u.settings.required_features.display_media=!0),u.bind("Error",function(t,i){var s,u="";s="<strong>"+i.message+"</strong>";switch(i.code){case n.FILE_EXTENSION_ERROR:u=r.sprintf(o("File: %s"),i.file.name);break;case n.FILE_SIZE_ERROR:u=r.sprintf(o("File: %s, size: %d, max file size: %d"),i.file.name,i.file.size,n.parseSize(e.options.max_file_size));break;case n.FILE_DUPLICATE_ERROR:u=r.sprintf(o("%s already present in the queue."),i.file.name);break;case e.FILE_COUNT_ERROR:u=r.sprintf(o("Upload element accepts only %d file(s) at a time. Extra files were stripped."),e.options.max_file_count);break;case n.IMAGE_FORMAT_ERROR:u=o("Image format either wrong or not supported.");break;case n.IMAGE_MEMORY_ERROR:u=o("Runtime ran out of available memory.");break;case n.HTTP_ERROR:u=o("Upload URL might be wrong or doesn't exist.")}s+=" <br /><i>"+u+"</i>",e._trigger("error",null,{up:t,error:i}),i.code===n.INIT_ERROR?setTimeout(function(){e.destroy()},1):e.notify("error",s)}),u.bind("PostInit",function(t){e.options.buttons.browse?e.browse_button.button("enable"):(e.browse_button.button("disable").hide(),t.disableBrowse(!0)),e.options.buttons.start||e.start_button.button("disable").hide(),e.options.buttons.stop||e.stop_button.button("disable").hide(),!e.options.unique_names&&e.options.rename&&e._enableRenaming(),e.options.dragdrop&&t.features.dragdrop&&e.filelist.parent().addClass("plupload_dropbox"),e._enableViewSwitcher(),e.start_button.click(function(t){i(this).button("option","disabled")||e.start(),t.preventDefault()}),e.stop_button.click(function(t){e.stop(),t.preventDefault()}),e._trigger("ready",null,{up:t})}),e.options.max_file_count&&(e.options.multiple_queues=!1,u.bind("FilesAdded",function(t,n){var r=n.length,i=t.files.length+r-e.options.max_file_count;i>0&&(n.splice(r-i,i),t.trigger("Error",{code:e.FILE_COUNT_ERROR,message:o("File count error.")}))})),u.init(),u.bind("FileFiltered",function(t,n){e._addFiles(n)}),u.bind("FilesAdded",function(t,n){e._trigger("selected",null,{up:t,files:n}),e.options.sortable&&i.ui.sortable&&e._enableSortingList(),e._trigger("updatelist",null,{filelist:e.filelist}),e.options.autostart&&setTimeout(function(){e.start()},10)}),u.bind("FilesRemoved",function(t,n){e._trigger("removed",null,{up:t,files:n})}),u.bind("QueueChanged StateChanged",function(){e._handleState()}),u.bind("UploadFile",function(t,n){e._handleFileStatus(n)}),u.bind("FileUploaded",function(t,n){e._handleFileStatus(n),e._trigger("uploaded",null,{up:t,file:n})}),u.bind("UploadProgress",function(t,n){e._handleFileStatus(n),e._updateTotalProgress(),e._trigger("progress",null,{up:t,file:n})}),u.bind("UploadComplete",function(t,n){e._addFormFields(),e._trigger("complete",null,{up:t,files:n})})},_setOption:function(e,t){var n=this;e=="buttons"&&typeof t=="object"&&(t=i.extend(n.options.buttons,t),t.browse?(n.browse_button.button("enable").show(),n.uploader.disableBrowse(!1)):(n.browse_button.button("disable").hide(),n.uploader.disableBrowse(!0)),t.start?n.start_button.button("enable").show():n.start_button.button("disable").hide(),t.stop?n.start_button.button("enable").show():n.stop_button.button("disable").hide()),n.uploader.settings[e]=t},start:function(){this.uploader.start(),this._trigger("start",null,{up:this.uploader})},stop:function(){this.uploader.stop(),this._trigger("stop",null,{up:this.uploader})},enable:function(){this.browse_button.button("enable"),this.uploader.disableBrowse(!1)},disable:function(){this.browse_button.button("disable"),this.uploader.disableBrowse(!0)},getFile:function(e){var t;return typeof e=="number"?t=this.uploader.files[e]:t=this.uploader.getFile(e),t},getFiles:function(){return this.uploader.files},removeFile:function(e){n.typeOf(e)==="string"&&(e=this.getFile(e)),this._removeFiles(e)},clearQueue:function(){this.uploader.splice()},getUploader:function(){return this.uploader},refresh:function(){this.uploader.refresh()},notify:function(e,t){var n=i('<div class="plupload_message"><span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+o("Close")+'"></span>'+'<p><span class="ui-icon"></span>'+t+"</p>"+"</div>");n.addClass("ui-state-"+(e==="error"?"error":"highlight")).find("p .ui-icon").addClass("ui-icon-"+(e==="error"?"alert":"info")).end().find(".plupload_message_close").click(function(){n.remove()}).end(),i(".plupload_header",this.container).append(n)},destroy:function(){this._removeFiles([].slice.call(this.uploader.files)),this.uploader.destroy(),i(".plupload_button",this.element).unbind(),i.ui.button&&i(".plupload_add, .plupload_start, .plupload_stop",this.container).button("destroy"),i.ui.progressbar&&this.progressbar.progressbar("destroy"),i.ui.sortable&&this.options.sortable&&i("tbody",this.filelist).sortable("destroy"),this.element.empty().html(this.contents_bak),this.contents_bak="",i.Widget.prototype.destroy.apply(this)},_handleState:function(){var e=this.uploader;e.state===n.STARTED?(i(this.start_button).button("disable"),i([]).add(this.stop_button).add(".plupload_started").removeClass("plupload_hidden"),i(".plupload_upload_status",this.element).html(r.sprintf(o("Uploaded %d/%d files"),e.total.uploaded,e.files.length)),i(".plupload_header_content",this.element).addClass("plupload_header_content_bw")):e.state===n.STOPPED&&(i([]).add(this.stop_button).add(".plupload_started").addClass("plupload_hidden"),this.options.multiple_queues?i(".plupload_header_content",this.element).removeClass("plupload_header_content_bw"):(i([]).add(this.browse_button).add(this.start_button).button("disable"),e.disableBrowse()),e.files.length===e.total.uploaded+e.total.failed?this.start_button.button("disable"):this.start_button.button("enable"),this._updateTotalProgress()),e.total.queued===0?i(".ui-button-text",this.browse_button).html(o("Add Files")):i(".ui-button-text",this.browse_button).html(r.sprintf(o("%d files queued"),e.total.queued)),e.refresh()},_handleFileStatus:function(e){var t=this,r,s;if(!i("#"+e.id).length)return;switch(e.status){case n.DONE:r="plupload_done",s="ui-icon ui-icon-circle-check";break;case n.FAILED:r="ui-state-error plupload_failed",s="ui-icon ui-icon-alert";break;case n.QUEUED:r="plupload_delete",s="ui-icon ui-icon-circle-minus";break;case n.UPLOADING:r="ui-state-highlight plupload_uploading",s="ui-icon ui-icon-circle-arrow-w";var o=i(".plupload_scroll",this.container),u=o.scrollTop(),a=o.height(),f=i("#"+e.id).position().top+i("#"+e.id).height();a<f&&o.scrollTop(u+f-a),i("#"+e.id).find(".plupload_file_percent").html(e.percent+"%").end().find(".plupload_file_progress").css("width",e.percent+"%").end().find(".plupload_file_size").html(n.formatSize(e.size))}r+=" ui-state-default plupload_file",i("#"+e.id).attr("class",r).find(".ui-icon").attr("class",s).end().filter(".plupload_delete, .plupload_done, .plupload_failed").find(".ui-icon").click(function(n){t._removeFiles(e),n.preventDefault()})},_updateTotalProgress:function(){var e=this.uploader;this.filelist[0].scrollTop=this.filelist[0].scrollHeight,this.progressbar.progressbar("value",e.total.percent),this.element.find(".plupload_total_status").html(e.total.percent+"%").end().find(".plupload_total_file_size").html(n.formatSize(e.total.size)).end().find(".plupload_upload_status").html(r.sprintf(o("Uploaded %d/%d files"),e.total.uploaded,e.files.length))},_displayThumbs:function(){function f(e,t,n){var r;e.on(t,function(){clearTimeout(r),r=setTimeout(function(){clearTimeout(r),n()},300)})}function l(){if(!t||!n){var r=i(".plupload_file:eq(0)",e.filelist);t=r.outerWidth(!0),n=r.outerHeight(!0)}var u=e.content.width(),a=e.content.height();s=Math.floor(u/t),o=s*(Math.ceil(a/n)+1)}function c(){var t=Math.floor(e.content.scrollTop()/n)*s;u=i(".plupload_file",e.filelist).slice(t,t+o).filter(":not(.plupload_file_thumb_loaded)").get()}function h(){function t(){if(e.view_mode!=="thumbs")return;l(),c(),d()}i.fn.resizable&&f(e.container,"resize",t),f(e.window,"resize",t),f(e.content,"scroll",t),e.element.on("viewchanged selected",t),t()}function p(t,n){var s=new r.Image;s.onload=function(){var n=i("#"+t.id+" .plupload_file_thumb",e.filelist).html("");this.embed(n[0],{width:100,height:60,crop:!0,swf_url:r.resolveUrl(e.options.flash_swf_url),xap_url:r.resolveUrl(e.options.silverlight_xap_url)})},s.bind("embedded error",function(){i("#"+t.id,e.filelist).addClass("plupload_file_thumb_loaded"),this.destroy(),setTimeout(n,1)}),s.load(t.getSource())}function d(){if(e.view_mode!=="thumbs"||a)return;c();if(!u.length)return;a=!0,p(e.getFile(i(u.shift()).attr("id")),function(){a=!1,d()})}var e=this,t,n,s,o=0,u=[],a=!1;if(!this.options.views.thumbs)return;this.element.on("selected",function v(){e.element.off("selected",v),h()})},_addFiles:function(e){var t=this,s;s='<li class="plupload_file ui-state-default" id="%id%"><div class="plupload_file_thumb"><div class="plupload_file_dummy ui-widget-content"><span class="ui-state-disabled">%ext%</span></div></div><div class="plupload_file_name" title="%name%"><span class="plupload_file_namespan">%name%</span></div><div class="plupload_file_action"><div class="ui-icon"> </div></div><div class="plupload_file_size">%size% </div><div class="plupload_file_status"><div class="plupload_file_progress ui-widget-header" style="width: 0%"> </div><span class="plupload_file_percent">%percent% </span></div><div class="plupload_file_fields"> </div></li>',n.typeOf(e)!=="array"&&(e=[e]),i.each(e,function(e,i){var o=r.Mime.getFileExtension(i.name)||"none";t.filelist.append(s.replace(/%(\w+)%/g,function(e,t){return"size"===t?n.formatSize(i.size):"ext"===t?o:i[t]||""})),t._handleFileStatus(i)})},_removeFiles:function(e){var t=this,r=this.uploader;n.typeOf(e)!=="array"&&(e=[e]),i.ui.sortable&&this.options.sortable&&i("tbody",t.filelist).sortable("destroy"),i.each(e,function(e,t){i("#"+t.id).toggle("highlight",function(){this.remove()}),r.removeFile(t)}),r.files.length&&this.options.sortable&&i.ui.sortable&&this._enableSortingList(),this._trigger("updatelist",null,{filelist:this.filelist})},_addFormFields:function(){var e=this;i(".plupload_file_fields",this.filelist).html(""),n.each(this.uploader.files,function(t,r){var s="",o=e.id+"_"+r;t.target_name&&(s+='<input type="hidden" name="'+o+'_tmpname" value="'+n.xmlEncode(t.target_name)+'" />'),s+='<input type="hidden" name="'+o+'_name" value="'+n.xmlEncode(t.name)+'" />',s+='<input type="hidden" name="'+o+'_status" value="'+(t.status===n.DONE?"done":"failed")+'" />',i("#"+t.id).find(".plupload_file_fields").html(s)}),this.counter.val(this.uploader.files.length)},_viewChanged:function(e){this.options.views.remember&&i.cookie&&i.cookie("plupload_ui_view",e,{expires:7,path:"/"}),r.Env.browser==="IE"&&r.Env.version<7&&this.content.attr("style",'height:expression(document.getElementById("'+this.id+"_container"+'").clientHeight - '+(e==="list"?133:103)+");"),this.container.removeClass("plupload_view_list plupload_view_thumbs").addClass("plupload_view_"+e),this.view_mode=e,this._trigger("viewchanged",null,{view:e})},_enableViewSwitcher:function(){var e=this,t,r=i(".plupload_view_switch",this.container),s,o;n.each(["list","thumbs"],function(t){e.options.views[t]||r.find('[for="'+e.id+"_view_"+t+'"], #'+e.id+"_view_"+t).remove()}),s=r.find(".plupload_button"),s.length===1?(r.hide(),t=s.eq(0).data("view"),this._viewChanged(t)):i.ui.button&&s.length>1?(this.options.views.remember&&i.cookie&&(t=i.cookie("plupload_ui_view")),~n.inArray(t,["list","thumbs"])||(t=this.options.views.active),r.show().buttonset().find(".ui-button").click(function(n){t=i(this).data("view"),e._viewChanged(t),n.preventDefault()}),o=r.find('[for="'+e.id+"_view_"+t+'"]'),o.length&&o.trigger("click")):(r.show(),this._viewChanged(this.options.views.active)),this.options.views.thumbs&&this._displayThumbs()},_enableRenaming:function(){var e=this;this.filelist.dblclick(function(t){var n=i(t.target),r,s,o,u,a="";if(!n.hasClass("plupload_file_namespan"))return;s=e.uploader.getFile(n.closest(".plupload_file")[0].id),u=s.name,o=/^(.+)(\.[^.]+)$/.exec(u),o&&(u=o[1],a=o[2]),r=i('<input class="plupload_file_rename" type="text" />').width(n.width()).insertAfter(n.hide()),r.val(u).blur(function(){n.show().parent().scrollLeft(0).end().next().remove()}).keydown(function(e){var t=i(this);i.inArray(e.keyCode,[13,27])!==-1&&(e.preventDefault(),e.keyCode===13&&(s.name=t.val()+a,n.html(s.name)),t.blur())})[0].focus()})},_enableSortingList:function(){var e=this;if(i(".plupload_file",this.filelist).length<2)return;i("tbody",this.filelist).sortable("destroy"),this.filelist.sortable({items:".plupload_delete",cancel:"object, .plupload_clearer",stop:function(){var t=[];i.each(i(this).sortable("toArray"),function(n,r){t[t.length]=e.uploader.getFile(r)}),t.unshift(t.length),t.unshift(0),Array.prototype.splice.apply(e.uploader.files,t)}})}})})(window,document,plupload,mOxie,jQuery);
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/moxie.js ADDED
@@ -0,0 +1,10684 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
3
+ * v1.2.0
4
+ *
5
+ * Copyright 2013, Moxiecode Systems AB
6
+ * Released under GPL License.
7
+ *
8
+ * License: http://www.plupload.com/license
9
+ * Contributing: http://www.plupload.com/contributing
10
+ *
11
+ * Date: 2014-01-16
12
+ */
13
+ /**
14
+ * Compiled inline version. (Library mode)
15
+ */
16
+
17
+ /*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
18
+ /*globals $code */
19
+
20
+ (function(exports, undefined) {
21
+ "use strict";
22
+
23
+ var modules = {};
24
+
25
+ function require(ids, callback) {
26
+ var module, defs = [];
27
+
28
+ for (var i = 0; i < ids.length; ++i) {
29
+ module = modules[ids[i]] || resolve(ids[i]);
30
+ if (!module) {
31
+ throw 'module definition dependecy not found: ' + ids[i];
32
+ }
33
+
34
+ defs.push(module);
35
+ }
36
+
37
+ callback.apply(null, defs);
38
+ }
39
+
40
+ function define(id, dependencies, definition) {
41
+ if (typeof id !== 'string') {
42
+ throw 'invalid module definition, module id must be defined and be a string';
43
+ }
44
+
45
+ if (dependencies === undefined) {
46
+ throw 'invalid module definition, dependencies must be specified';
47
+ }
48
+
49
+ if (definition === undefined) {
50
+ throw 'invalid module definition, definition function must be specified';
51
+ }
52
+
53
+ require(dependencies, function() {
54
+ modules[id] = definition.apply(null, arguments);
55
+ });
56
+ }
57
+
58
+ function defined(id) {
59
+ return !!modules[id];
60
+ }
61
+
62
+ function resolve(id) {
63
+ var target = exports;
64
+ var fragments = id.split(/[.\/]/);
65
+
66
+ for (var fi = 0; fi < fragments.length; ++fi) {
67
+ if (!target[fragments[fi]]) {
68
+ return;
69
+ }
70
+
71
+ target = target[fragments[fi]];
72
+ }
73
+
74
+ return target;
75
+ }
76
+
77
+ function expose(ids) {
78
+ for (var i = 0; i < ids.length; i++) {
79
+ var target = exports;
80
+ var id = ids[i];
81
+ var fragments = id.split(/[.\/]/);
82
+
83
+ for (var fi = 0; fi < fragments.length - 1; ++fi) {
84
+ if (target[fragments[fi]] === undefined) {
85
+ target[fragments[fi]] = {};
86
+ }
87
+
88
+ target = target[fragments[fi]];
89
+ }
90
+
91
+ target[fragments[fragments.length - 1]] = modules[id];
92
+ }
93
+ }
94
+
95
+ // Included from: src/javascript/core/utils/Basic.js
96
+
97
+ /**
98
+ * Basic.js
99
+ *
100
+ * Copyright 2013, Moxiecode Systems AB
101
+ * Released under GPL License.
102
+ *
103
+ * License: http://www.plupload.com/license
104
+ * Contributing: http://www.plupload.com/contributing
105
+ */
106
+
107
+ define('moxie/core/utils/Basic', [], function() {
108
+ /**
109
+ Gets the true type of the built-in object (better version of typeof).
110
+ @author Angus Croll (http://javascriptweblog.wordpress.com/)
111
+
112
+ @method typeOf
113
+ @for Utils
114
+ @static
115
+ @param {Object} o Object to check.
116
+ @return {String} Object [[Class]]
117
+ */
118
+ var typeOf = function(o) {
119
+ var undef;
120
+
121
+ if (o === undef) {
122
+ return 'undefined';
123
+ } else if (o === null) {
124
+ return 'null';
125
+ } else if (o.nodeType) {
126
+ return 'node';
127
+ }
128
+
129
+ // the snippet below is awesome, however it fails to detect null, undefined and arguments types in IE lte 8
130
+ return ({}).toString.call(o).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
131
+ };
132
+
133
+ /**
134
+ Extends the specified object with another object.
135
+
136
+ @method extend
137
+ @static
138
+ @param {Object} target Object to extend.
139
+ @param {Object} [obj]* Multiple objects to extend with.
140
+ @return {Object} Same as target, the extended object.
141
+ */
142
+ var extend = function(target) {
143
+ var undef;
144
+
145
+ each(arguments, function(arg, i) {
146
+ if (i > 0) {
147
+ each(arg, function(value, key) {
148
+ if (value !== undef) {
149
+ if (typeOf(target[key]) === typeOf(value) && !!~inArray(typeOf(value), ['array', 'object'])) {
150
+ extend(target[key], value);
151
+ } else {
152
+ target[key] = value;
153
+ }
154
+ }
155
+ });
156
+ }
157
+ });
158
+ return target;
159
+ };
160
+
161
+ /**
162
+ Executes the callback function for each item in array/object. If you return false in the
163
+ callback it will break the loop.
164
+
165
+ @method each
166
+ @static
167
+ @param {Object} obj Object to iterate.
168
+ @param {function} callback Callback function to execute for each item.
169
+ */
170
+ var each = function(obj, callback) {
171
+ var length, key, i, undef;
172
+
173
+ if (obj) {
174
+ try {
175
+ length = obj.length;
176
+ } catch(ex) {
177
+ length = undef;
178
+ }
179
+
180
+ if (length === undef) {
181
+ // Loop object items
182
+ for (key in obj) {
183
+ if (obj.hasOwnProperty(key)) {
184
+ if (callback(obj[key], key) === false) {
185
+ return;
186
+ }
187
+ }
188
+ }
189
+ } else {
190
+ // Loop array items
191
+ for (i = 0; i < length; i++) {
192
+ if (callback(obj[i], i) === false) {
193
+ return;
194
+ }
195
+ }
196
+ }
197
+ }
198
+ };
199
+
200
+ /**
201
+ Checks if object is empty.
202
+
203
+ @method isEmptyObj
204
+ @static
205
+ @param {Object} o Object to check.
206
+ @return {Boolean}
207
+ */
208
+ var isEmptyObj = function(obj) {
209
+ var prop;
210
+
211
+ if (!obj || typeOf(obj) !== 'object') {
212
+ return true;
213
+ }
214
+
215
+ for (prop in obj) {
216
+ return false;
217
+ }
218
+
219
+ return true;
220
+ };
221
+
222
+ /**
223
+ Recieve an array of functions (usually async) to call in sequence, each function
224
+ receives a callback as first argument that it should call, when it completes. Finally,
225
+ after everything is complete, main callback is called. Passing truthy value to the
226
+ callback as a first argument will interrupt the sequence and invoke main callback
227
+ immediately.
228
+
229
+ @method inSeries
230
+ @static
231
+ @param {Array} queue Array of functions to call in sequence
232
+ @param {Function} cb Main callback that is called in the end, or in case of erro
233
+ */
234
+ var inSeries = function(queue, cb) {
235
+ var i = 0, length = queue.length;
236
+
237
+ if (typeOf(cb) !== 'function') {
238
+ cb = function() {};
239
+ }
240
+
241
+ if (!queue || !queue.length) {
242
+ cb();
243
+ }
244
+
245
+ function callNext(i) {
246
+ if (typeOf(queue[i]) === 'function') {
247
+ queue[i](function(error) {
248
+ /*jshint expr:true */
249
+ ++i < length && !error ? callNext(i) : cb(error);
250
+ });
251
+ }
252
+ }
253
+ callNext(i);
254
+ };
255
+
256
+
257
+ /**
258
+ Recieve an array of functions (usually async) to call in parallel, each function
259
+ receives a callback as first argument that it should call, when it completes. After
260
+ everything is complete, main callback is called. Passing truthy value to the
261
+ callback as a first argument will interrupt the process and invoke main callback
262
+ immediately.
263
+
264
+ @method inParallel
265
+ @static
266
+ @param {Array} queue Array of functions to call in sequence
267
+ @param {Function} cb Main callback that is called in the end, or in case of erro
268
+ */
269
+ var inParallel = function(queue, cb) {
270
+ var count = 0, num = queue.length, cbArgs = new Array(num);
271
+
272
+ each(queue, function(fn, i) {
273
+ fn(function(error) {
274
+ if (error) {
275
+ return cb(error);
276
+ }
277
+
278
+ var args = [].slice.call(arguments);
279
+ args.shift(); // strip error - undefined or not
280
+
281
+ cbArgs[i] = args;
282
+ count++;
283
+
284
+ if (count === num) {
285
+ cbArgs.unshift(null);
286
+ cb.apply(this, cbArgs);
287
+ }
288
+ });
289
+ });
290
+ };
291
+
292
+
293
+ /**
294
+ Find an element in array and return it's index if present, otherwise return -1.
295
+
296
+ @method inArray
297
+ @static
298
+ @param {Mixed} needle Element to find
299
+ @param {Array} array
300
+ @return {Int} Index of the element, or -1 if not found
301
+ */
302
+ var inArray = function(needle, array) {
303
+ if (array) {
304
+ if (Array.prototype.indexOf) {
305
+ return Array.prototype.indexOf.call(array, needle);
306
+ }
307
+
308
+ for (var i = 0, length = array.length; i < length; i++) {
309
+ if (array[i] === needle) {
310
+ return i;
311
+ }
312
+ }
313
+ }
314
+ return -1;
315
+ };
316
+
317
+
318
+ /**
319
+ Returns elements of first array if they are not present in second. And false - otherwise.
320
+
321
+ @private
322
+ @method arrayDiff
323
+ @param {Array} needles
324
+ @param {Array} array
325
+ @return {Array|Boolean}
326
+ */
327
+ var arrayDiff = function(needles, array) {
328
+ var diff = [];
329
+
330
+ if (typeOf(needles) !== 'array') {
331
+ needles = [needles];
332
+ }
333
+
334
+ if (typeOf(array) !== 'array') {
335
+ array = [array];
336
+ }
337
+
338
+ for (var i in needles) {
339
+ if (inArray(needles[i], array) === -1) {
340
+ diff.push(needles[i]);
341
+ }
342
+ }
343
+ return diff.length ? diff : false;
344
+ };
345
+
346
+
347
+ /**
348
+ Find intersection of two arrays.
349
+
350
+ @private
351
+ @method arrayIntersect
352
+ @param {Array} array1
353
+ @param {Array} array2
354
+ @return {Array} Intersection of two arrays or null if there is none
355
+ */
356
+ var arrayIntersect = function(array1, array2) {
357
+ var result = [];
358
+ each(array1, function(item) {
359
+ if (inArray(item, array2) !== -1) {
360
+ result.push(item);
361
+ }
362
+ });
363
+ return result.length ? result : null;
364
+ };
365
+
366
+
367
+ /**
368
+ Forces anything into an array.
369
+
370
+ @method toArray
371
+ @static
372
+ @param {Object} obj Object with length field.
373
+ @return {Array} Array object containing all items.
374
+ */
375
+ var toArray = function(obj) {
376
+ var i, arr = [];
377
+
378
+ for (i = 0; i < obj.length; i++) {
379
+ arr[i] = obj[i];
380
+ }
381
+
382
+ return arr;
383
+ };
384
+
385
+
386
+ /**
387
+ Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers.
388
+ The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages
389
+ to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique.
390
+ It's more probable for the earth to be hit with an ansteriod. Y
391
+
392
+ @method guid
393
+ @static
394
+ @param {String} prefix to prepend (by default 'o' will be prepended).
395
+ @method guid
396
+ @return {String} Virtually unique id.
397
+ */
398
+ var guid = (function() {
399
+ var counter = 0;
400
+
401
+ return function(prefix) {
402
+ var guid = new Date().getTime().toString(32), i;
403
+
404
+ for (i = 0; i < 5; i++) {
405
+ guid += Math.floor(Math.random() * 65535).toString(32);
406
+ }
407
+
408
+ return (prefix || 'o_') + guid + (counter++).toString(32);
409
+ };
410
+ }());
411
+
412
+
413
+ /**
414
+ Trims white spaces around the string
415
+
416
+ @method trim
417
+ @static
418
+ @param {String} str
419
+ @return {String}
420
+ */
421
+ var trim = function(str) {
422
+ if (!str) {
423
+ return str;
424
+ }
425
+ return String.prototype.trim ? String.prototype.trim.call(str) : str.toString().replace(/^\s*/, '').replace(/\s*$/, '');
426
+ };
427
+
428
+
429
+ /**
430
+ Parses the specified size string into a byte value. For example 10kb becomes 10240.
431
+
432
+ @method parseSizeStr
433
+ @static
434
+ @param {String/Number} size String to parse or number to just pass through.
435
+ @return {Number} Size in bytes.
436
+ */
437
+ var parseSizeStr = function(size) {
438
+ if (typeof(size) !== 'string') {
439
+ return size;
440
+ }
441
+
442
+ var muls = {
443
+ t: 1099511627776,
444
+ g: 1073741824,
445
+ m: 1048576,
446
+ k: 1024
447
+ },
448
+ mul;
449
+
450
+ size = /^([0-9]+)([mgk]?)$/.exec(size.toLowerCase().replace(/[^0-9mkg]/g, ''));
451
+ mul = size[2];
452
+ size = +size[1];
453
+
454
+ if (muls.hasOwnProperty(mul)) {
455
+ size *= muls[mul];
456
+ }
457
+ return size;
458
+ };
459
+
460
+
461
+ return {
462
+ guid: guid,
463
+ typeOf: typeOf,
464
+ extend: extend,
465
+ each: each,
466
+ isEmptyObj: isEmptyObj,
467
+ inSeries: inSeries,
468
+ inParallel: inParallel,
469
+ inArray: inArray,
470
+ arrayDiff: arrayDiff,
471
+ arrayIntersect: arrayIntersect,
472
+ toArray: toArray,
473
+ trim: trim,
474
+ parseSizeStr: parseSizeStr
475
+ };
476
+ });
477
+
478
+ // Included from: src/javascript/core/I18n.js
479
+
480
+ /**
481
+ * I18n.js
482
+ *
483
+ * Copyright 2013, Moxiecode Systems AB
484
+ * Released under GPL License.
485
+ *
486
+ * License: http://www.plupload.com/license
487
+ * Contributing: http://www.plupload.com/contributing
488
+ */
489
+
490
+ define("moxie/core/I18n", [
491
+ "moxie/core/utils/Basic"
492
+ ], function(Basic) {
493
+ var i18n = {};
494
+
495
+ return {
496
+ /**
497
+ * Extends the language pack object with new items.
498
+ *
499
+ * @param {Object} pack Language pack items to add.
500
+ * @return {Object} Extended language pack object.
501
+ */
502
+ addI18n: function(pack) {
503
+ return Basic.extend(i18n, pack);
504
+ },
505
+
506
+ /**
507
+ * Translates the specified string by checking for the english string in the language pack lookup.
508
+ *
509
+ * @param {String} str String to look for.
510
+ * @return {String} Translated string or the input string if it wasn't found.
511
+ */
512
+ translate: function(str) {
513
+ return i18n[str] || str;
514
+ },
515
+
516
+ /**
517
+ * Shortcut for translate function
518
+ *
519
+ * @param {String} str String to look for.
520
+ * @return {String} Translated string or the input string if it wasn't found.
521
+ */
522
+ _: function(str) {
523
+ return this.translate(str);
524
+ },
525
+
526
+ /**
527
+ * Pseudo sprintf implementation - simple way to replace tokens with specified values.
528
+ *
529
+ * @param {String} str String with tokens
530
+ * @return {String} String with replaced tokens
531
+ */
532
+ sprintf: function(str) {
533
+ var args = [].slice.call(arguments, 1);
534
+
535
+ return str.replace(/%[a-z]/g, function() {
536
+ var value = args.shift();
537
+ return Basic.typeOf(value) !== 'undefined' ? value : '';
538
+ });
539
+ }
540
+ };
541
+ });
542
+
543
+ // Included from: src/javascript/core/utils/Mime.js
544
+
545
+ /**
546
+ * Mime.js
547
+ *
548
+ * Copyright 2013, Moxiecode Systems AB
549
+ * Released under GPL License.
550
+ *
551
+ * License: http://www.plupload.com/license
552
+ * Contributing: http://www.plupload.com/contributing
553
+ */
554
+
555
+ define("moxie/core/utils/Mime", [
556
+ "moxie/core/utils/Basic",
557
+ "moxie/core/I18n"
558
+ ], function(Basic, I18n) {
559
+
560
+ var mimeData = "" +
561
+ "application/msword,doc dot," +
562
+ "application/pdf,pdf," +
563
+ "application/pgp-signature,pgp," +
564
+ "application/postscript,ps ai eps," +
565
+ "application/rtf,rtf," +
566
+ "application/vnd.ms-excel,xls xlb," +
567
+ "application/vnd.ms-powerpoint,ppt pps pot," +
568
+ "application/zip,zip," +
569
+ "application/x-shockwave-flash,swf swfl," +
570
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx," +
571
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx," +
572
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx," +
573
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx," +
574
+ "application/vnd.openxmlformats-officedocument.presentationml.template,potx," +
575
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx," +
576
+ "application/x-javascript,js," +
577
+ "application/json,json," +
578
+ "audio/mpeg,mp3 mpga mpega mp2," +
579
+ "audio/x-wav,wav," +
580
+ "audio/x-m4a,m4a," +
581
+ "audio/ogg,oga ogg," +
582
+ "audio/aiff,aiff aif," +
583
+ "audio/flac,flac," +
584
+ "audio/aac,aac," +
585
+ "audio/ac3,ac3," +
586
+ "audio/x-ms-wma,wma," +
587
+ "image/bmp,bmp," +
588
+ "image/gif,gif," +
589
+ "image/jpeg,jpg jpeg jpe," +
590
+ "image/photoshop,psd," +
591
+ "image/png,png," +
592
+ "image/svg+xml,svg svgz," +
593
+ "image/tiff,tiff tif," +
594
+ "text/plain,asc txt text diff log," +
595
+ "text/html,htm html xhtml," +
596
+ "text/css,css," +
597
+ "text/csv,csv," +
598
+ "text/rtf,rtf," +
599
+ "video/mpeg,mpeg mpg mpe m2v," +
600
+ "video/quicktime,qt mov," +
601
+ "video/mp4,mp4," +
602
+ "video/x-m4v,m4v," +
603
+ "video/x-flv,flv," +
604
+ "video/x-ms-wmv,wmv," +
605
+ "video/avi,avi," +
606
+ "video/webm,webm," +
607
+ "video/3gpp,3gpp 3gp," +
608
+ "video/3gpp2,3g2," +
609
+ "video/vnd.rn-realvideo,rv," +
610
+ "video/ogg,ogv," +
611
+ "video/x-matroska,mkv," +
612
+ "application/vnd.oasis.opendocument.formula-template,otf," +
613
+ "application/octet-stream,exe";
614
+
615
+
616
+ var Mime = {
617
+
618
+ mimes: {},
619
+
620
+ extensions: {},
621
+
622
+ // Parses the default mime types string into a mimes and extensions lookup maps
623
+ addMimeType: function (mimeData) {
624
+ var items = mimeData.split(/,/), i, ii, ext;
625
+
626
+ for (i = 0; i < items.length; i += 2) {
627
+ ext = items[i + 1].split(/ /);
628
+
629
+ // extension to mime lookup
630
+ for (ii = 0; ii < ext.length; ii++) {
631
+ this.mimes[ext[ii]] = items[i];
632
+ }
633
+ // mime to extension lookup
634
+ this.extensions[items[i]] = ext;
635
+ }
636
+ },
637
+
638
+
639
+ extList2mimes: function (filters, addMissingExtensions) {
640
+ var self = this, ext, i, ii, type, mimes = [];
641
+
642
+ // convert extensions to mime types list
643
+ for (i = 0; i < filters.length; i++) {
644
+ ext = filters[i].extensions.split(/\s*,\s*/);
645
+
646
+ for (ii = 0; ii < ext.length; ii++) {
647
+
648
+ // if there's an asterisk in the list, then accept attribute is not required
649
+ if (ext[ii] === '*') {
650
+ return [];
651
+ }
652
+
653
+ type = self.mimes[ext[ii]];
654
+ if (!type) {
655
+ if (addMissingExtensions && /^\w+$/.test(ext[ii])) {
656
+ mimes.push('.' + ext[ii]);
657
+ } else {
658
+ return []; // accept all
659
+ }
660
+ } else if (Basic.inArray(type, mimes) === -1) {
661
+ mimes.push(type);
662
+ }
663
+ }
664
+ }
665
+ return mimes;
666
+ },
667
+
668
+
669
+ mimes2exts: function(mimes) {
670
+ var self = this, exts = [];
671
+
672
+ Basic.each(mimes, function(mime) {
673
+ if (mime === '*') {
674
+ exts = [];
675
+ return false;
676
+ }
677
+
678
+ // check if this thing looks like mime type
679
+ var m = mime.match(/^(\w+)\/(\*|\w+)$/);
680
+ if (m) {
681
+ if (m[2] === '*') {
682
+ // wildcard mime type detected
683
+ Basic.each(self.extensions, function(arr, mime) {
684
+ if ((new RegExp('^' + m[1] + '/')).test(mime)) {
685
+ [].push.apply(exts, self.extensions[mime]);
686
+ }
687
+ });
688
+ } else if (self.extensions[mime]) {
689
+ [].push.apply(exts, self.extensions[mime]);
690
+ }
691
+ }
692
+ });
693
+ return exts;
694
+ },
695
+
696
+
697
+ mimes2extList: function(mimes) {
698
+ var accept = [], exts = [];
699
+
700
+ if (Basic.typeOf(mimes) === 'string') {
701
+ mimes = Basic.trim(mimes).split(/\s*,\s*/);
702
+ }
703
+
704
+ exts = this.mimes2exts(mimes);
705
+
706
+ accept.push({
707
+ title: I18n.translate('Files'),
708
+ extensions: exts.length ? exts.join(',') : '*'
709
+ });
710
+
711
+ // save original mimes string
712
+ accept.mimes = mimes;
713
+
714
+ return accept;
715
+ },
716
+
717
+
718
+ getFileExtension: function(fileName) {
719
+ var matches = fileName && fileName.match(/\.([^.]+)$/);
720
+ if (matches) {
721
+ return matches[1].toLowerCase();
722
+ }
723
+ return '';
724
+ },
725
+
726
+ getFileMime: function(fileName) {
727
+ return this.mimes[this.getFileExtension(fileName)] || '';
728
+ }
729
+ };
730
+
731
+ Mime.addMimeType(mimeData);
732
+
733
+ return Mime;
734
+ });
735
+
736
+ // Included from: src/javascript/core/utils/Env.js
737
+
738
+ /**
739
+ * Env.js
740
+ *
741
+ * Copyright 2013, Moxiecode Systems AB
742
+ * Released under GPL License.
743
+ *
744
+ * License: http://www.plupload.com/license
745
+ * Contributing: http://www.plupload.com/contributing
746
+ */
747
+
748
+ define("moxie/core/utils/Env", [
749
+ "moxie/core/utils/Basic"
750
+ ], function(Basic) {
751
+
752
+ // UAParser.js v0.6.2
753
+ // Lightweight JavaScript-based User-Agent string parser
754
+ // https://github.com/faisalman/ua-parser-js
755
+ //
756
+ // Copyright © 2012-2013 Faisalman <fyzlman@gmail.com>
757
+ // Dual licensed under GPLv2 & MIT
758
+
759
+ var UAParser = (function (undefined) {
760
+
761
+ //////////////
762
+ // Constants
763
+ /////////////
764
+
765
+
766
+ var EMPTY = '',
767
+ UNKNOWN = '?',
768
+ FUNC_TYPE = 'function',
769
+ UNDEF_TYPE = 'undefined',
770
+ OBJ_TYPE = 'object',
771
+ MAJOR = 'major',
772
+ MODEL = 'model',
773
+ NAME = 'name',
774
+ TYPE = 'type',
775
+ VENDOR = 'vendor',
776
+ VERSION = 'version',
777
+ ARCHITECTURE= 'architecture',
778
+ CONSOLE = 'console',
779
+ MOBILE = 'mobile',
780
+ TABLET = 'tablet';
781
+
782
+
783
+ ///////////
784
+ // Helper
785
+ //////////
786
+
787
+
788
+ var util = {
789
+ has : function (str1, str2) {
790
+ return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1;
791
+ },
792
+ lowerize : function (str) {
793
+ return str.toLowerCase();
794
+ }
795
+ };
796
+
797
+
798
+ ///////////////
799
+ // Map helper
800
+ //////////////
801
+
802
+
803
+ var mapper = {
804
+
805
+ rgx : function () {
806
+
807
+ // loop through all regexes maps
808
+ for (var result, i = 0, j, k, p, q, matches, match, args = arguments; i < args.length; i += 2) {
809
+
810
+ var regex = args[i], // even sequence (0,2,4,..)
811
+ props = args[i + 1]; // odd sequence (1,3,5,..)
812
+
813
+ // construct object barebones
814
+ if (typeof(result) === UNDEF_TYPE) {
815
+ result = {};
816
+ for (p in props) {
817
+ q = props[p];
818
+ if (typeof(q) === OBJ_TYPE) {
819
+ result[q[0]] = undefined;
820
+ } else {
821
+ result[q] = undefined;
822
+ }
823
+ }
824
+ }
825
+
826
+ // try matching uastring with regexes
827
+ for (j = k = 0; j < regex.length; j++) {
828
+ matches = regex[j].exec(this.getUA());
829
+ if (!!matches) {
830
+ for (p = 0; p < props.length; p++) {
831
+ match = matches[++k];
832
+ q = props[p];
833
+ // check if given property is actually array
834
+ if (typeof(q) === OBJ_TYPE && q.length > 0) {
835
+ if (q.length == 2) {
836
+ if (typeof(q[1]) == FUNC_TYPE) {
837
+ // assign modified match
838
+ result[q[0]] = q[1].call(this, match);
839
+ } else {
840
+ // assign given value, ignore regex match
841
+ result[q[0]] = q[1];
842
+ }
843
+ } else if (q.length == 3) {
844
+ // check whether function or regex
845
+ if (typeof(q[1]) === FUNC_TYPE && !(q[1].exec && q[1].test)) {
846
+ // call function (usually string mapper)
847
+ result[q[0]] = match ? q[1].call(this, match, q[2]) : undefined;
848
+ } else {
849
+ // sanitize match using given regex
850
+ result[q[0]] = match ? match.replace(q[1], q[2]) : undefined;
851
+ }
852
+ } else if (q.length == 4) {
853
+ result[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined;
854
+ }
855
+ } else {
856
+ result[q] = match ? match : undefined;
857
+ }
858
+ }
859
+ break;
860
+ }
861
+ }
862
+
863
+ if(!!matches) break; // break the loop immediately if match found
864
+ }
865
+ return result;
866
+ },
867
+
868
+ str : function (str, map) {
869
+
870
+ for (var i in map) {
871
+ // check if array
872
+ if (typeof(map[i]) === OBJ_TYPE && map[i].length > 0) {
873
+ for (var j = 0; j < map[i].length; j++) {
874
+ if (util.has(map[i][j], str)) {
875
+ return (i === UNKNOWN) ? undefined : i;
876
+ }
877
+ }
878
+ } else if (util.has(map[i], str)) {
879
+ return (i === UNKNOWN) ? undefined : i;
880
+ }
881
+ }
882
+ return str;
883
+ }
884
+ };
885
+
886
+
887
+ ///////////////
888
+ // String map
889
+ //////////////
890
+
891
+
892
+ var maps = {
893
+
894
+ browser : {
895
+ oldsafari : {
896
+ major : {
897
+ '1' : ['/8', '/1', '/3'],
898
+ '2' : '/4',
899
+ '?' : '/'
900
+ },
901
+ version : {
902
+ '1.0' : '/8',
903
+ '1.2' : '/1',
904
+ '1.3' : '/3',
905
+ '2.0' : '/412',
906
+ '2.0.2' : '/416',
907
+ '2.0.3' : '/417',
908
+ '2.0.4' : '/419',
909
+ '?' : '/'
910
+ }
911
+ }
912
+ },
913
+
914
+ device : {
915
+ sprint : {
916
+ model : {
917
+ 'Evo Shift 4G' : '7373KT'
918
+ },
919
+ vendor : {
920
+ 'HTC' : 'APA',
921
+ 'Sprint' : 'Sprint'
922
+ }
923
+ }
924
+ },
925
+
926
+ os : {
927
+ windows : {
928
+ version : {
929
+ 'ME' : '4.90',
930
+ 'NT 3.11' : 'NT3.51',
931
+ 'NT 4.0' : 'NT4.0',
932
+ '2000' : 'NT 5.0',
933
+ 'XP' : ['NT 5.1', 'NT 5.2'],
934
+ 'Vista' : 'NT 6.0',
935
+ '7' : 'NT 6.1',
936
+ '8' : 'NT 6.2',
937
+ '8.1' : 'NT 6.3',
938
+ 'RT' : 'ARM'
939
+ }
940
+ }
941
+ }
942
+ };
943
+
944
+
945
+ //////////////
946
+ // Regex map
947
+ /////////////
948
+
949
+
950
+ var regexes = {
951
+
952
+ browser : [[
953
+
954
+ // Presto based
955
+ /(opera\smini)\/((\d+)?[\w\.-]+)/i, // Opera Mini
956
+ /(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i, // Opera Mobi/Tablet
957
+ /(opera).+version\/((\d+)?[\w\.]+)/i, // Opera > 9.80
958
+ /(opera)[\/\s]+((\d+)?[\w\.]+)/i // Opera < 9.80
959
+
960
+ ], [NAME, VERSION, MAJOR], [
961
+
962
+ /\s(opr)\/((\d+)?[\w\.]+)/i // Opera Webkit
963
+ ], [[NAME, 'Opera'], VERSION, MAJOR], [
964
+
965
+ // Mixed
966
+ /(kindle)\/((\d+)?[\w\.]+)/i, // Kindle
967
+ /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i,
968
+ // Lunascape/Maxthon/Netfront/Jasmine/Blazer
969
+
970
+ // Trident based
971
+ /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i,
972
+ // Avant/IEMobile/SlimBrowser/Baidu
973
+ /(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i, // Internet Explorer
974
+
975
+ // Webkit/KHTML based
976
+ /(rekonq)((?:\/)[\w\.]+)*/i, // Rekonq
977
+ /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i
978
+ // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron
979
+ ], [NAME, VERSION, MAJOR], [
980
+
981
+ /(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i // IE11
982
+ ], [[NAME, 'IE'], VERSION, MAJOR], [
983
+
984
+ /(yabrowser)\/((\d+)?[\w\.]+)/i // Yandex
985
+ ], [[NAME, 'Yandex'], VERSION, MAJOR], [
986
+
987
+ /(comodo_dragon)\/((\d+)?[\w\.]+)/i // Comodo Dragon
988
+ ], [[NAME, /_/g, ' '], VERSION, MAJOR], [
989
+
990
+ /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i
991
+ // Chrome/OmniWeb/Arora/Tizen/Nokia
992
+ ], [NAME, VERSION, MAJOR], [
993
+
994
+ /(dolfin)\/((\d+)?[\w\.]+)/i // Dolphin
995
+ ], [[NAME, 'Dolphin'], VERSION, MAJOR], [
996
+
997
+ /((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i // Chrome for Android/iOS
998
+ ], [[NAME, 'Chrome'], VERSION, MAJOR], [
999
+
1000
+ /((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i // Android Browser
1001
+ ], [[NAME, 'Android Browser'], VERSION, MAJOR], [
1002
+
1003
+ /version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari
1004
+ ], [VERSION, MAJOR, [NAME, 'Mobile Safari']], [
1005
+
1006
+ /version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile
1007
+ ], [VERSION, MAJOR, NAME], [
1008
+
1009
+ /webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i // Safari < 3.0
1010
+ ], [NAME, [MAJOR, mapper.str, maps.browser.oldsafari.major], [VERSION, mapper.str, maps.browser.oldsafari.version]], [
1011
+
1012
+ /(konqueror)\/((\d+)?[\w\.]+)/i, // Konqueror
1013
+ /(webkit|khtml)\/((\d+)?[\w\.]+)/i
1014
+ ], [NAME, VERSION, MAJOR], [
1015
+
1016
+ // Gecko based
1017
+ /(navigator|netscape)\/((\d+)?[\w\.-]+)/i // Netscape
1018
+ ], [[NAME, 'Netscape'], VERSION, MAJOR], [
1019
+ /(swiftfox)/i, // Swiftfox
1020
+ /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i,
1021
+ // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror
1022
+ /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i,
1023
+ // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix
1024
+ /(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla
1025
+
1026
+ // Other
1027
+ /(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i,
1028
+ // UCBrowser/Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/QQBrowser
1029
+ /(links)\s\(((\d+)?[\w\.]+)/i, // Links
1030
+ /(gobrowser)\/?((\d+)?[\w\.]+)*/i, // GoBrowser
1031
+ /(ice\s?browser)\/v?((\d+)?[\w\._]+)/i, // ICE Browser
1032
+ /(mosaic)[\/\s]((\d+)?[\w\.]+)/i // Mosaic
1033
+ ], [NAME, VERSION, MAJOR]
1034
+ ],
1035
+
1036
+ engine : [[
1037
+
1038
+ /(presto)\/([\w\.]+)/i, // Presto
1039
+ /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m
1040
+ /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links
1041
+ /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab
1042
+ ], [NAME, VERSION], [
1043
+
1044
+ /rv\:([\w\.]+).*(gecko)/i // Gecko
1045
+ ], [VERSION, NAME]
1046
+ ],
1047
+
1048
+ os : [[
1049
+
1050
+ // Windows based
1051
+ /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT
1052
+ /(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i
1053
+ ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [
1054
+ /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i
1055
+ ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [
1056
+
1057
+ // Mobile/Embedded OS
1058
+ /\((bb)(10);/i // BlackBerry 10
1059
+ ], [[NAME, 'BlackBerry'], VERSION], [
1060
+ /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry
1061
+ /(tizen)\/([\w\.]+)/i, // Tizen
1062
+ /(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i
1063
+ // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo
1064
+ ], [NAME, VERSION], [
1065
+ /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian
1066
+ ], [[NAME, 'Symbian'], VERSION],[
1067
+ /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS
1068
+ ], [[NAME, 'Firefox OS'], VERSION], [
1069
+
1070
+ // Console
1071
+ /(nintendo|playstation)\s([wids3portablevu]+)/i, // Nintendo/Playstation
1072
+
1073
+ // GNU/Linux based
1074
+ /(mint)[\/\s\(]?(\w+)*/i, // Mint
1075
+ /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i,
1076
+ // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware
1077
+ // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk
1078
+ /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux
1079
+ /(gnu)\s?([\w\.]+)*/i // GNU
1080
+ ], [NAME, VERSION], [
1081
+
1082
+ /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS
1083
+ ], [[NAME, 'Chromium OS'], VERSION],[
1084
+
1085
+ // Solaris
1086
+ /(sunos)\s?([\w\.]+\d)*/i // Solaris
1087
+ ], [[NAME, 'Solaris'], VERSION], [
1088
+
1089
+ // BSD based
1090
+ /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly
1091
+ ], [NAME, VERSION],[
1092
+
1093
+ /(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i // iOS
1094
+ ], [[NAME, 'iOS'], [VERSION, /_/g, '.']], [
1095
+
1096
+ /(mac\sos\sx)\s?([\w\s\.]+\w)*/i // Mac OS
1097
+ ], [NAME, [VERSION, /_/g, '.']], [
1098
+
1099
+ // Other
1100
+ /(haiku)\s(\w+)/i, // Haiku
1101
+ /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX
1102
+ /(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i,
1103
+ // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS
1104
+ /(unix)\s?([\w\.]+)*/i // UNIX
1105
+ ], [NAME, VERSION]
1106
+ ]
1107
+ };
1108
+
1109
+
1110
+ /////////////////
1111
+ // Constructor
1112
+ ////////////////
1113
+
1114
+
1115
+ var UAParser = function (uastring) {
1116
+
1117
+ var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY);
1118
+
1119
+ this.getBrowser = function () {
1120
+ return mapper.rgx.apply(this, regexes.browser);
1121
+ };
1122
+ this.getEngine = function () {
1123
+ return mapper.rgx.apply(this, regexes.engine);
1124
+ };
1125
+ this.getOS = function () {
1126
+ return mapper.rgx.apply(this, regexes.os);
1127
+ };
1128
+ this.getResult = function() {
1129
+ return {
1130
+ ua : this.getUA(),
1131
+ browser : this.getBrowser(),
1132
+ engine : this.getEngine(),
1133
+ os : this.getOS()
1134
+ };
1135
+ };
1136
+ this.getUA = function () {
1137
+ return ua;
1138
+ };
1139
+ this.setUA = function (uastring) {
1140
+ ua = uastring;
1141
+ return this;
1142
+ };
1143
+ this.setUA(ua);
1144
+ };
1145
+
1146
+ return new UAParser().getResult();
1147
+ })();
1148
+
1149
+
1150
+ function version_compare(v1, v2, operator) {
1151
+ // From: http://phpjs.org/functions
1152
+ // + original by: Philippe Jausions (http://pear.php.net/user/jausions)
1153
+ // + original by: Aidan Lister (http://aidanlister.com/)
1154
+ // + reimplemented by: Kankrelune (http://www.webfaktory.info/)
1155
+ // + improved by: Brett Zamir (http://brett-zamir.me)
1156
+ // + improved by: Scott Baker
1157
+ // + improved by: Theriault
1158
+ // * example 1: version_compare('8.2.5rc', '8.2.5a');
1159
+ // * returns 1: 1
1160
+ // * example 2: version_compare('8.2.50', '8.2.52', '<');
1161
+ // * returns 2: true
1162
+ // * example 3: version_compare('5.3.0-dev', '5.3.0');
1163
+ // * returns 3: -1
1164
+ // * example 4: version_compare('4.1.0.52','4.01.0.51');
1165
+ // * returns 4: 1
1166
+
1167
+ // Important: compare must be initialized at 0.
1168
+ var i = 0,
1169
+ x = 0,
1170
+ compare = 0,
1171
+ // vm maps textual PHP versions to negatives so they're less than 0.
1172
+ // PHP currently defines these as CASE-SENSITIVE. It is important to
1173
+ // leave these as negatives so that they can come before numerical versions
1174
+ // and as if no letters were there to begin with.
1175
+ // (1alpha is < 1 and < 1.1 but > 1dev1)
1176
+ // If a non-numerical value can't be mapped to this table, it receives
1177
+ // -7 as its value.
1178
+ vm = {
1179
+ 'dev': -6,
1180
+ 'alpha': -5,
1181
+ 'a': -5,
1182
+ 'beta': -4,
1183
+ 'b': -4,
1184
+ 'RC': -3,
1185
+ 'rc': -3,
1186
+ '#': -2,
1187
+ 'p': 1,
1188
+ 'pl': 1
1189
+ },
1190
+ // This function will be called to prepare each version argument.
1191
+ // It replaces every _, -, and + with a dot.
1192
+ // It surrounds any nonsequence of numbers/dots with dots.
1193
+ // It replaces sequences of dots with a single dot.
1194
+ // version_compare('4..0', '4.0') == 0
1195
+ // Important: A string of 0 length needs to be converted into a value
1196
+ // even less than an unexisting value in vm (-7), hence [-8].
1197
+ // It's also important to not strip spaces because of this.
1198
+ // version_compare('', ' ') == 1
1199
+ prepVersion = function (v) {
1200
+ v = ('' + v).replace(/[_\-+]/g, '.');
1201
+ v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
1202
+ return (!v.length ? [-8] : v.split('.'));
1203
+ },
1204
+ // This converts a version component to a number.
1205
+ // Empty component becomes 0.
1206
+ // Non-numerical component becomes a negative number.
1207
+ // Numerical component becomes itself as an integer.
1208
+ numVersion = function (v) {
1209
+ return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
1210
+ };
1211
+
1212
+ v1 = prepVersion(v1);
1213
+ v2 = prepVersion(v2);
1214
+ x = Math.max(v1.length, v2.length);
1215
+ for (i = 0; i < x; i++) {
1216
+ if (v1[i] == v2[i]) {
1217
+ continue;
1218
+ }
1219
+ v1[i] = numVersion(v1[i]);
1220
+ v2[i] = numVersion(v2[i]);
1221
+ if (v1[i] < v2[i]) {
1222
+ compare = -1;
1223
+ break;
1224
+ } else if (v1[i] > v2[i]) {
1225
+ compare = 1;
1226
+ break;
1227
+ }
1228
+ }
1229
+ if (!operator) {
1230
+ return compare;
1231
+ }
1232
+
1233
+ // Important: operator is CASE-SENSITIVE.
1234
+ // "No operator" seems to be treated as "<."
1235
+ // Any other values seem to make the function return null.
1236
+ switch (operator) {
1237
+ case '>':
1238
+ case 'gt':
1239
+ return (compare > 0);
1240
+ case '>=':
1241
+ case 'ge':
1242
+ return (compare >= 0);
1243
+ case '<=':
1244
+ case 'le':
1245
+ return (compare <= 0);
1246
+ case '==':
1247
+ case '=':
1248
+ case 'eq':
1249
+ return (compare === 0);
1250
+ case '<>':
1251
+ case '!=':
1252
+ case 'ne':
1253
+ return (compare !== 0);
1254
+ case '':
1255
+ case '<':
1256
+ case 'lt':
1257
+ return (compare < 0);
1258
+ default:
1259
+ return null;
1260
+ }
1261
+ }
1262
+
1263
+
1264
+ var can = (function() {
1265
+ var caps = {
1266
+ define_property: (function() {
1267
+ /* // currently too much extra code required, not exactly worth it
1268
+ try { // as of IE8, getters/setters are supported only on DOM elements
1269
+ var obj = {};
1270
+ if (Object.defineProperty) {
1271
+ Object.defineProperty(obj, 'prop', {
1272
+ enumerable: true,
1273
+ configurable: true
1274
+ });
1275
+ return true;
1276
+ }
1277
+ } catch(ex) {}
1278
+
1279
+ if (Object.prototype.__defineGetter__ && Object.prototype.__defineSetter__) {
1280
+ return true;
1281
+ }*/
1282
+ return false;
1283
+ }()),
1284
+
1285
+ create_canvas: (function() {
1286
+ // On the S60 and BB Storm, getContext exists, but always returns undefined
1287
+ // so we actually have to call getContext() to verify
1288
+ // github.com/Modernizr/Modernizr/issues/issue/97/
1289
+ var el = document.createElement('canvas');
1290
+ return !!(el.getContext && el.getContext('2d'));
1291
+ }()),
1292
+
1293
+ return_response_type: function(responseType) {
1294
+ try {
1295
+ if (Basic.inArray(responseType, ['', 'text', 'document']) !== -1) {
1296
+ return true;
1297
+ } else if (window.XMLHttpRequest) {
1298
+ var xhr = new XMLHttpRequest();
1299
+ xhr.open('get', '/'); // otherwise Gecko throws an exception
1300
+ if ('responseType' in xhr) {
1301
+ xhr.responseType = responseType;
1302
+ // as of 23.0.1271.64, Chrome switched from throwing exception to merely logging it to the console (why? o why?)
1303
+ if (xhr.responseType !== responseType) {
1304
+ return false;
1305
+ }
1306
+ return true;
1307
+ }
1308
+ }
1309
+ } catch (ex) {}
1310
+ return false;
1311
+ },
1312
+
1313
+ // ideas for this heavily come from Modernizr (http://modernizr.com/)
1314
+ use_data_uri: (function() {
1315
+ var du = new Image();
1316
+
1317
+ du.onload = function() {
1318
+ caps.use_data_uri = (du.width === 1 && du.height === 1);
1319
+ };
1320
+
1321
+ setTimeout(function() {
1322
+ du.src = "data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==";
1323
+ }, 1);
1324
+ return false;
1325
+ }()),
1326
+
1327
+ use_data_uri_over32kb: function() { // IE8
1328
+ return caps.use_data_uri && (Env.browser !== 'IE' || Env.version >= 9);
1329
+ },
1330
+
1331
+ use_data_uri_of: function(bytes) {
1332
+ return (caps.use_data_uri && bytes < 33000 || caps.use_data_uri_over32kb());
1333
+ },
1334
+
1335
+ use_fileinput: function() {
1336
+ var el = document.createElement('input');
1337
+ el.setAttribute('type', 'file');
1338
+ return !el.disabled;
1339
+ }
1340
+ };
1341
+
1342
+ return function(cap) {
1343
+ var args = [].slice.call(arguments);
1344
+ args.shift(); // shift of cap
1345
+ return Basic.typeOf(caps[cap]) === 'function' ? caps[cap].apply(this, args) : !!caps[cap];
1346
+ };
1347
+ }());
1348
+
1349
+
1350
+ var Env = {
1351
+ can: can,
1352
+
1353
+ browser: UAParser.browser.name,
1354
+ version: parseFloat(UAParser.browser.major),
1355
+ os: UAParser.os.name, // everybody intuitively types it in a lowercase for some reason
1356
+ osVersion: UAParser.os.version,
1357
+
1358
+ verComp: version_compare,
1359
+
1360
+ swf_url: "../flash/Moxie.swf",
1361
+ xap_url: "../silverlight/Moxie.xap",
1362
+ global_event_dispatcher: "moxie.core.EventTarget.instance.dispatchEvent"
1363
+ };
1364
+
1365
+ // for backward compatibility
1366
+ // @deprecated Use `Env.os` instead
1367
+ Env.OS = Env.os;
1368
+
1369
+ return Env;
1370
+ });
1371
+
1372
+ // Included from: src/javascript/core/utils/Dom.js
1373
+
1374
+ /**
1375
+ * Dom.js
1376
+ *
1377
+ * Copyright 2013, Moxiecode Systems AB
1378
+ * Released under GPL License.
1379
+ *
1380
+ * License: http://www.plupload.com/license
1381
+ * Contributing: http://www.plupload.com/contributing
1382
+ */
1383
+
1384
+ define('moxie/core/utils/Dom', ['moxie/core/utils/Env'], function(Env) {
1385
+
1386
+ /**
1387
+ Get DOM Element by it's id.
1388
+
1389
+ @method get
1390
+ @for Utils
1391
+ @param {String} id Identifier of the DOM Element
1392
+ @return {DOMElement}
1393
+ */
1394
+ var get = function(id) {
1395
+ if (typeof id !== 'string') {
1396
+ return id;
1397
+ }
1398
+ return document.getElementById(id);
1399
+ };
1400
+
1401
+ /**
1402
+ Checks if specified DOM element has specified class.
1403
+
1404
+ @method hasClass
1405
+ @static
1406
+ @param {Object} obj DOM element like object to add handler to.
1407
+ @param {String} name Class name
1408
+ */
1409
+ var hasClass = function(obj, name) {
1410
+ if (!obj.className) {
1411
+ return false;
1412
+ }
1413
+
1414
+ var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
1415
+ return regExp.test(obj.className);
1416
+ };
1417
+
1418
+ /**
1419
+ Adds specified className to specified DOM element.
1420
+
1421
+ @method addClass
1422
+ @static
1423
+ @param {Object} obj DOM element like object to add handler to.
1424
+ @param {String} name Class name
1425
+ */
1426
+ var addClass = function(obj, name) {
1427
+ if (!hasClass(obj, name)) {
1428
+ obj.className = !obj.className ? name : obj.className.replace(/\s+$/, '') + ' ' + name;
1429
+ }
1430
+ };
1431
+
1432
+ /**
1433
+ Removes specified className from specified DOM element.
1434
+
1435
+ @method removeClass
1436
+ @static
1437
+ @param {Object} obj DOM element like object to add handler to.
1438
+ @param {String} name Class name
1439
+ */
1440
+ var removeClass = function(obj, name) {
1441
+ if (obj.className) {
1442
+ var regExp = new RegExp("(^|\\s+)"+name+"(\\s+|$)");
1443
+ obj.className = obj.className.replace(regExp, function($0, $1, $2) {
1444
+ return $1 === ' ' && $2 === ' ' ? ' ' : '';
1445
+ });
1446
+ }
1447
+ };
1448
+
1449
+ /**
1450
+ Returns a given computed style of a DOM element.
1451
+
1452
+ @method getStyle
1453
+ @static
1454
+ @param {Object} obj DOM element like object.
1455
+ @param {String} name Style you want to get from the DOM element
1456
+ */
1457
+ var getStyle = function(obj, name) {
1458
+ if (obj.currentStyle) {
1459
+ return obj.currentStyle[name];
1460
+ } else if (window.getComputedStyle) {
1461
+ return window.getComputedStyle(obj, null)[name];
1462
+ }
1463
+ };
1464
+
1465
+
1466
+ /**
1467
+ Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields.
1468
+
1469
+ @method getPos
1470
+ @static
1471
+ @param {Element} node HTML element or element id to get x, y position from.
1472
+ @param {Element} root Optional root element to stop calculations at.
1473
+ @return {object} Absolute position of the specified element object with x, y fields.
1474
+ */
1475
+ var getPos = function(node, root) {
1476
+ var x = 0, y = 0, parent, doc = document, nodeRect, rootRect;
1477
+
1478
+ node = node;
1479
+ root = root || doc.body;
1480
+
1481
+ // Returns the x, y cordinate for an element on IE 6 and IE 7
1482
+ function getIEPos(node) {
1483
+ var bodyElm, rect, x = 0, y = 0;
1484
+
1485
+ if (node) {
1486
+ rect = node.getBoundingClientRect();
1487
+ bodyElm = doc.compatMode === "CSS1Compat" ? doc.documentElement : doc.body;
1488
+ x = rect.left + bodyElm.scrollLeft;
1489
+ y = rect.top + bodyElm.scrollTop;
1490
+ }
1491
+
1492
+ return {
1493
+ x : x,
1494
+ y : y
1495
+ };
1496
+ }
1497
+
1498
+ // Use getBoundingClientRect on IE 6 and IE 7 but not on IE 8 in standards mode
1499
+ if (node && node.getBoundingClientRect && Env.browser === 'IE' && (!doc.documentMode || doc.documentMode < 8)) {
1500
+ nodeRect = getIEPos(node);
1501
+ rootRect = getIEPos(root);
1502
+
1503
+ return {
1504
+ x : nodeRect.x - rootRect.x,
1505
+ y : nodeRect.y - rootRect.y
1506
+ };
1507
+ }
1508
+
1509
+ parent = node;
1510
+ while (parent && parent != root && parent.nodeType) {
1511
+ x += parent.offsetLeft || 0;
1512
+ y += parent.offsetTop || 0;
1513
+ parent = parent.offsetParent;
1514
+ }
1515
+
1516
+ parent = node.parentNode;
1517
+ while (parent && parent != root && parent.nodeType) {
1518
+ x -= parent.scrollLeft || 0;
1519
+ y -= parent.scrollTop || 0;
1520
+ parent = parent.parentNode;
1521
+ }
1522
+
1523
+ return {
1524
+ x : x,
1525
+ y : y
1526
+ };
1527
+ };
1528
+
1529
+ /**
1530
+ Returns the size of the specified node in pixels.
1531
+
1532
+ @method getSize
1533
+ @static
1534
+ @param {Node} node Node to get the size of.
1535
+ @return {Object} Object with a w and h property.
1536
+ */
1537
+ var getSize = function(node) {
1538
+ return {
1539
+ w : node.offsetWidth || node.clientWidth,
1540
+ h : node.offsetHeight || node.clientHeight
1541
+ };
1542
+ };
1543
+
1544
+ return {
1545
+ get: get,
1546
+ hasClass: hasClass,
1547
+ addClass: addClass,
1548
+ removeClass: removeClass,
1549
+ getStyle: getStyle,
1550
+ getPos: getPos,
1551
+ getSize: getSize
1552
+ };
1553
+ });
1554
+
1555
+ // Included from: src/javascript/core/Exceptions.js
1556
+
1557
+ /**
1558
+ * Exceptions.js
1559
+ *
1560
+ * Copyright 2013, Moxiecode Systems AB
1561
+ * Released under GPL License.
1562
+ *
1563
+ * License: http://www.plupload.com/license
1564
+ * Contributing: http://www.plupload.com/contributing
1565
+ */
1566
+
1567
+ define('moxie/core/Exceptions', [
1568
+ 'moxie/core/utils/Basic'
1569
+ ], function(Basic) {
1570
+ function _findKey(obj, value) {
1571
+ var key;
1572
+ for (key in obj) {
1573
+ if (obj[key] === value) {
1574
+ return key;
1575
+ }
1576
+ }
1577
+ return null;
1578
+ }
1579
+
1580
+ return {
1581
+ RuntimeError: (function() {
1582
+ var namecodes = {
1583
+ NOT_INIT_ERR: 1,
1584
+ NOT_SUPPORTED_ERR: 9,
1585
+ JS_ERR: 4
1586
+ };
1587
+
1588
+ function RuntimeError(code) {
1589
+ this.code = code;
1590
+ this.name = _findKey(namecodes, code);
1591
+ this.message = this.name + ": RuntimeError " + this.code;
1592
+ }
1593
+
1594
+ Basic.extend(RuntimeError, namecodes);
1595
+ RuntimeError.prototype = Error.prototype;
1596
+ return RuntimeError;
1597
+ }()),
1598
+
1599
+ OperationNotAllowedException: (function() {
1600
+
1601
+ function OperationNotAllowedException(code) {
1602
+ this.code = code;
1603
+ this.name = 'OperationNotAllowedException';
1604
+ }
1605
+
1606
+ Basic.extend(OperationNotAllowedException, {
1607
+ NOT_ALLOWED_ERR: 1
1608
+ });
1609
+
1610
+ OperationNotAllowedException.prototype = Error.prototype;
1611
+
1612
+ return OperationNotAllowedException;
1613
+ }()),
1614
+
1615
+ ImageError: (function() {
1616
+ var namecodes = {
1617
+ WRONG_FORMAT: 1,
1618
+ MAX_RESOLUTION_ERR: 2
1619
+ };
1620
+
1621
+ function ImageError(code) {
1622
+ this.code = code;
1623
+ this.name = _findKey(namecodes, code);
1624
+ this.message = this.name + ": ImageError " + this.code;
1625
+ }
1626
+
1627
+ Basic.extend(ImageError, namecodes);
1628
+ ImageError.prototype = Error.prototype;
1629
+
1630
+ return ImageError;
1631
+ }()),
1632
+
1633
+ FileException: (function() {
1634
+ var namecodes = {
1635
+ NOT_FOUND_ERR: 1,
1636
+ SECURITY_ERR: 2,
1637
+ ABORT_ERR: 3,
1638
+ NOT_READABLE_ERR: 4,
1639
+ ENCODING_ERR: 5,
1640
+ NO_MODIFICATION_ALLOWED_ERR: 6,
1641
+ INVALID_STATE_ERR: 7,
1642
+ SYNTAX_ERR: 8
1643
+ };
1644
+
1645
+ function FileException(code) {
1646
+ this.code = code;
1647
+ this.name = _findKey(namecodes, code);
1648
+ this.message = this.name + ": FileException " + this.code;
1649
+ }
1650
+
1651
+ Basic.extend(FileException, namecodes);
1652
+ FileException.prototype = Error.prototype;
1653
+ return FileException;
1654
+ }()),
1655
+
1656
+ DOMException: (function() {
1657
+ var namecodes = {
1658
+ INDEX_SIZE_ERR: 1,
1659
+ DOMSTRING_SIZE_ERR: 2,
1660
+ HIERARCHY_REQUEST_ERR: 3,
1661
+ WRONG_DOCUMENT_ERR: 4,
1662
+ INVALID_CHARACTER_ERR: 5,
1663
+ NO_DATA_ALLOWED_ERR: 6,
1664
+ NO_MODIFICATION_ALLOWED_ERR: 7,
1665
+ NOT_FOUND_ERR: 8,
1666
+ NOT_SUPPORTED_ERR: 9,
1667
+ INUSE_ATTRIBUTE_ERR: 10,
1668
+ INVALID_STATE_ERR: 11,
1669
+ SYNTAX_ERR: 12,
1670
+ INVALID_MODIFICATION_ERR: 13,
1671
+ NAMESPACE_ERR: 14,
1672
+ INVALID_ACCESS_ERR: 15,
1673
+ VALIDATION_ERR: 16,
1674
+ TYPE_MISMATCH_ERR: 17,
1675
+ SECURITY_ERR: 18,
1676
+ NETWORK_ERR: 19,
1677
+ ABORT_ERR: 20,
1678
+ URL_MISMATCH_ERR: 21,
1679
+ QUOTA_EXCEEDED_ERR: 22,
1680
+ TIMEOUT_ERR: 23,
1681
+ INVALID_NODE_TYPE_ERR: 24,
1682
+ DATA_CLONE_ERR: 25
1683
+ };
1684
+
1685
+ function DOMException(code) {
1686
+ this.code = code;
1687
+ this.name = _findKey(namecodes, code);
1688
+ this.message = this.name + ": DOMException " + this.code;
1689
+ }
1690
+
1691
+ Basic.extend(DOMException, namecodes);
1692
+ DOMException.prototype = Error.prototype;
1693
+ return DOMException;
1694
+ }()),
1695
+
1696
+ EventException: (function() {
1697
+ function EventException(code) {
1698
+ this.code = code;
1699
+ this.name = 'EventException';
1700
+ }
1701
+
1702
+ Basic.extend(EventException, {
1703
+ UNSPECIFIED_EVENT_TYPE_ERR: 0
1704
+ });
1705
+
1706
+ EventException.prototype = Error.prototype;
1707
+
1708
+ return EventException;
1709
+ }())
1710
+ };
1711
+ });
1712
+
1713
+ // Included from: src/javascript/core/EventTarget.js
1714
+
1715
+ /**
1716
+ * EventTarget.js
1717
+ *
1718
+ * Copyright 2013, Moxiecode Systems AB
1719
+ * Released under GPL License.
1720
+ *
1721
+ * License: http://www.plupload.com/license
1722
+ * Contributing: http://www.plupload.com/contributing
1723
+ */
1724
+
1725
+ define('moxie/core/EventTarget', [
1726
+ 'moxie/core/Exceptions',
1727
+ 'moxie/core/utils/Basic'
1728
+ ], function(x, Basic) {
1729
+ /**
1730
+ Parent object for all event dispatching components and objects
1731
+
1732
+ @class EventTarget
1733
+ @constructor EventTarget
1734
+ */
1735
+ function EventTarget() {
1736
+ // hash of event listeners by object uid
1737
+ var eventpool = {};
1738
+
1739
+ Basic.extend(this, {
1740
+
1741
+ /**
1742
+ Unique id of the event dispatcher, usually overriden by children
1743
+
1744
+ @property uid
1745
+ @type String
1746
+ */
1747
+ uid: null,
1748
+
1749
+ /**
1750
+ Can be called from within a child in order to acquire uniqie id in automated manner
1751
+
1752
+ @method init
1753
+ */
1754
+ init: function() {
1755
+ if (!this.uid) {
1756
+ this.uid = Basic.guid('uid_');
1757
+ }
1758
+ },
1759
+
1760
+ /**
1761
+ Register a handler to a specific event dispatched by the object
1762
+
1763
+ @method addEventListener
1764
+ @param {String} type Type or basically a name of the event to subscribe to
1765
+ @param {Function} fn Callback function that will be called when event happens
1766
+ @param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first
1767
+ @param {Object} [scope=this] A scope to invoke event handler in
1768
+ */
1769
+ addEventListener: function(type, fn, priority, scope) {
1770
+ var self = this, list;
1771
+
1772
+ type = Basic.trim(type);
1773
+
1774
+ if (/\s/.test(type)) {
1775
+ // multiple event types were passed for one handler
1776
+ Basic.each(type.split(/\s+/), function(type) {
1777
+ self.addEventListener(type, fn, priority, scope);
1778
+ });
1779
+ return;
1780
+ }
1781
+
1782
+ type = type.toLowerCase();
1783
+ priority = parseInt(priority, 10) || 0;
1784
+
1785
+ list = eventpool[this.uid] && eventpool[this.uid][type] || [];
1786
+ list.push({fn : fn, priority : priority, scope : scope || this});
1787
+
1788
+ if (!eventpool[this.uid]) {
1789
+ eventpool[this.uid] = {};
1790
+ }
1791
+ eventpool[this.uid][type] = list;
1792
+ },
1793
+
1794
+ /**
1795
+ Check if any handlers were registered to the specified event
1796
+
1797
+ @method hasEventListener
1798
+ @param {String} type Type or basically a name of the event to check
1799
+ @return {Mixed} Returns a handler if it was found and false, if - not
1800
+ */
1801
+ hasEventListener: function(type) {
1802
+ return type ? !!(eventpool[this.uid] && eventpool[this.uid][type]) : !!eventpool[this.uid];
1803
+ },
1804
+
1805
+ /**
1806
+ Unregister the handler from the event, or if former was not specified - unregister all handlers
1807
+
1808
+ @method removeEventListener
1809
+ @param {String} type Type or basically a name of the event
1810
+ @param {Function} [fn] Handler to unregister
1811
+ */
1812
+ removeEventListener: function(type, fn) {
1813
+ type = type.toLowerCase();
1814
+
1815
+ var list = eventpool[this.uid] && eventpool[this.uid][type], i;
1816
+
1817
+ if (list) {
1818
+ if (fn) {
1819
+ for (i = list.length - 1; i >= 0; i--) {
1820
+ if (list[i].fn === fn) {
1821
+ list.splice(i, 1);
1822
+ break;
1823
+ }
1824
+ }
1825
+ } else {
1826
+ list = [];
1827
+ }
1828
+
1829
+ // delete event list if it has become empty
1830
+ if (!list.length) {
1831
+ delete eventpool[this.uid][type];
1832
+
1833
+ // and object specific entry in a hash if it has no more listeners attached
1834
+ if (Basic.isEmptyObj(eventpool[this.uid])) {
1835
+ delete eventpool[this.uid];
1836
+ }
1837
+ }
1838
+ }
1839
+ },
1840
+
1841
+ /**
1842
+ Remove all event handlers from the object
1843
+
1844
+ @method removeAllEventListeners
1845
+ */
1846
+ removeAllEventListeners: function() {
1847
+ if (eventpool[this.uid]) {
1848
+ delete eventpool[this.uid];
1849
+ }
1850
+ },
1851
+
1852
+ /**
1853
+ Dispatch the event
1854
+
1855
+ @method dispatchEvent
1856
+ @param {String/Object} Type of event or event object to dispatch
1857
+ @param {Mixed} [...] Variable number of arguments to be passed to a handlers
1858
+ @return {Boolean} true by default and false if any handler returned false
1859
+ */
1860
+ dispatchEvent: function(type) {
1861
+ var uid, list, args, tmpEvt, evt = {}, result = true, undef;
1862
+
1863
+ if (Basic.typeOf(type) !== 'string') {
1864
+ // we can't use original object directly (because of Silverlight)
1865
+ tmpEvt = type;
1866
+
1867
+ if (Basic.typeOf(tmpEvt.type) === 'string') {
1868
+ type = tmpEvt.type;
1869
+
1870
+ if (tmpEvt.total !== undef && tmpEvt.loaded !== undef) { // progress event
1871
+ evt.total = tmpEvt.total;
1872
+ evt.loaded = tmpEvt.loaded;
1873
+ }
1874
+ evt.async = tmpEvt.async || false;
1875
+ } else {
1876
+ throw new x.EventException(x.EventException.UNSPECIFIED_EVENT_TYPE_ERR);
1877
+ }
1878
+ }
1879
+
1880
+ // check if event is meant to be dispatched on an object having specific uid
1881
+ if (type.indexOf('::') !== -1) {
1882
+ (function(arr) {
1883
+ uid = arr[0];
1884
+ type = arr[1];
1885
+ }(type.split('::')));
1886
+ } else {
1887
+ uid = this.uid;
1888
+ }
1889
+
1890
+ type = type.toLowerCase();
1891
+
1892
+ list = eventpool[uid] && eventpool[uid][type];
1893
+
1894
+ if (list) {
1895
+ // sort event list by prority
1896
+ list.sort(function(a, b) { return b.priority - a.priority; });
1897
+
1898
+ args = [].slice.call(arguments);
1899
+
1900
+ // first argument will be pseudo-event object
1901
+ args.shift();
1902
+ evt.type = type;
1903
+ args.unshift(evt);
1904
+
1905
+ // Dispatch event to all listeners
1906
+ var queue = [];
1907
+ Basic.each(list, function(handler) {
1908
+ // explicitly set the target, otherwise events fired from shims do not get it
1909
+ args[0].target = handler.scope;
1910
+ // if event is marked as async, detach the handler
1911
+ if (evt.async) {
1912
+ queue.push(function(cb) {
1913
+ setTimeout(function() {
1914
+ cb(handler.fn.apply(handler.scope, args) === false);
1915
+ }, 1);
1916
+ });
1917
+ } else {
1918
+ queue.push(function(cb) {
1919
+ cb(handler.fn.apply(handler.scope, args) === false); // if handler returns false stop propagation
1920
+ });
1921
+ }
1922
+ });
1923
+ if (queue.length) {
1924
+ Basic.inSeries(queue, function(err) {
1925
+ result = !err;
1926
+ });
1927
+ }
1928
+ }
1929
+ return result;
1930
+ },
1931
+
1932
+ /**
1933
+ Alias for addEventListener
1934
+
1935
+ @method bind
1936
+ @protected
1937
+ */
1938
+ bind: function() {
1939
+ this.addEventListener.apply(this, arguments);
1940
+ },
1941
+
1942
+ /**
1943
+ Alias for removeEventListener
1944
+
1945
+ @method unbind
1946
+ @protected
1947
+ */
1948
+ unbind: function() {
1949
+ this.removeEventListener.apply(this, arguments);
1950
+ },
1951
+
1952
+ /**
1953
+ Alias for removeAllEventListeners
1954
+
1955
+ @method unbindAll
1956
+ @protected
1957
+ */
1958
+ unbindAll: function() {
1959
+ this.removeAllEventListeners.apply(this, arguments);
1960
+ },
1961
+
1962
+ /**
1963
+ Alias for dispatchEvent
1964
+
1965
+ @method trigger
1966
+ @protected
1967
+ */
1968
+ trigger: function() {
1969
+ return this.dispatchEvent.apply(this, arguments);
1970
+ },
1971
+
1972
+
1973
+ /**
1974
+ Converts properties of on[event] type to corresponding event handlers,
1975
+ is used to avoid extra hassle around the process of calling them back
1976
+
1977
+ @method convertEventPropsToHandlers
1978
+ @private
1979
+ */
1980
+ convertEventPropsToHandlers: function(handlers) {
1981
+ var h;
1982
+
1983
+ if (Basic.typeOf(handlers) !== 'array') {
1984
+ handlers = [handlers];
1985
+ }
1986
+
1987
+ for (var i = 0; i < handlers.length; i++) {
1988
+ h = 'on' + handlers[i];
1989
+
1990
+ if (Basic.typeOf(this[h]) === 'function') {
1991
+ this.addEventListener(handlers[i], this[h]);
1992
+ } else if (Basic.typeOf(this[h]) === 'undefined') {
1993
+ this[h] = null; // object must have defined event properties, even if it doesn't make use of them
1994
+ }
1995
+ }
1996
+ }
1997
+
1998
+ });
1999
+ }
2000
+
2001
+ EventTarget.instance = new EventTarget();
2002
+
2003
+ return EventTarget;
2004
+ });
2005
+
2006
+ // Included from: src/javascript/core/utils/Encode.js
2007
+
2008
+ /**
2009
+ * Encode.js
2010
+ *
2011
+ * Copyright 2013, Moxiecode Systems AB
2012
+ * Released under GPL License.
2013
+ *
2014
+ * License: http://www.plupload.com/license
2015
+ * Contributing: http://www.plupload.com/contributing
2016
+ */
2017
+
2018
+ define('moxie/core/utils/Encode', [], function() {
2019
+
2020
+ /**
2021
+ Encode string with UTF-8
2022
+
2023
+ @method utf8_encode
2024
+ @for Utils
2025
+ @static
2026
+ @param {String} str String to encode
2027
+ @return {String} UTF-8 encoded string
2028
+ */
2029
+ var utf8_encode = function(str) {
2030
+ return unescape(encodeURIComponent(str));
2031
+ };
2032
+
2033
+ /**
2034
+ Decode UTF-8 encoded string
2035
+
2036
+ @method utf8_decode
2037
+ @static
2038
+ @param {String} str String to decode
2039
+ @return {String} Decoded string
2040
+ */
2041
+ var utf8_decode = function(str_data) {
2042
+ return decodeURIComponent(escape(str_data));
2043
+ };
2044
+
2045
+ /**
2046
+ Decode Base64 encoded string (uses browser's default method if available),
2047
+ from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_decode.js
2048
+
2049
+ @method atob
2050
+ @static
2051
+ @param {String} data String to decode
2052
+ @return {String} Decoded string
2053
+ */
2054
+ var atob = function(data, utf8) {
2055
+ if (typeof(window.atob) === 'function') {
2056
+ return utf8 ? utf8_decode(window.atob(data)) : window.atob(data);
2057
+ }
2058
+
2059
+ // http://kevin.vanzonneveld.net
2060
+ // + original by: Tyler Akins (http://rumkin.com)
2061
+ // + improved by: Thunder.m
2062
+ // + input by: Aman Gupta
2063
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2064
+ // + bugfixed by: Onno Marsman
2065
+ // + bugfixed by: Pellentesque Malesuada
2066
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2067
+ // + input by: Brett Zamir (http://brett-zamir.me)
2068
+ // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2069
+ // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
2070
+ // * returns 1: 'Kevin van Zonneveld'
2071
+ // mozilla has this native
2072
+ // - but breaks in 2.0.0.12!
2073
+ //if (typeof this.window.atob == 'function') {
2074
+ // return atob(data);
2075
+ //}
2076
+ var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
2077
+ var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
2078
+ ac = 0,
2079
+ dec = "",
2080
+ tmp_arr = [];
2081
+
2082
+ if (!data) {
2083
+ return data;
2084
+ }
2085
+
2086
+ data += '';
2087
+
2088
+ do { // unpack four hexets into three octets using index points in b64
2089
+ h1 = b64.indexOf(data.charAt(i++));
2090
+ h2 = b64.indexOf(data.charAt(i++));
2091
+ h3 = b64.indexOf(data.charAt(i++));
2092
+ h4 = b64.indexOf(data.charAt(i++));
2093
+
2094
+ bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
2095
+
2096
+ o1 = bits >> 16 & 0xff;
2097
+ o2 = bits >> 8 & 0xff;
2098
+ o3 = bits & 0xff;
2099
+
2100
+ if (h3 == 64) {
2101
+ tmp_arr[ac++] = String.fromCharCode(o1);
2102
+ } else if (h4 == 64) {
2103
+ tmp_arr[ac++] = String.fromCharCode(o1, o2);
2104
+ } else {
2105
+ tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
2106
+ }
2107
+ } while (i < data.length);
2108
+
2109
+ dec = tmp_arr.join('');
2110
+
2111
+ return utf8 ? utf8_decode(dec) : dec;
2112
+ };
2113
+
2114
+ /**
2115
+ Base64 encode string (uses browser's default method if available),
2116
+ from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_encode.js
2117
+
2118
+ @method btoa
2119
+ @static
2120
+ @param {String} data String to encode
2121
+ @return {String} Base64 encoded string
2122
+ */
2123
+ var btoa = function(data, utf8) {
2124
+ if (utf8) {
2125
+ utf8_encode(data);
2126
+ }
2127
+
2128
+ if (typeof(window.btoa) === 'function') {
2129
+ return window.btoa(data);
2130
+ }
2131
+
2132
+ // http://kevin.vanzonneveld.net
2133
+ // + original by: Tyler Akins (http://rumkin.com)
2134
+ // + improved by: Bayron Guevara
2135
+ // + improved by: Thunder.m
2136
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2137
+ // + bugfixed by: Pellentesque Malesuada
2138
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
2139
+ // + improved by: Rafał Kukawski (http://kukawski.pl)
2140
+ // * example 1: base64_encode('Kevin van Zonneveld');
2141
+ // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
2142
+ // mozilla has this native
2143
+ // - but breaks in 2.0.0.12!
2144
+ var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
2145
+ var o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
2146
+ ac = 0,
2147
+ enc = "",
2148
+ tmp_arr = [];
2149
+
2150
+ if (!data) {
2151
+ return data;
2152
+ }
2153
+
2154
+ do { // pack three octets into four hexets
2155
+ o1 = data.charCodeAt(i++);
2156
+ o2 = data.charCodeAt(i++);
2157
+ o3 = data.charCodeAt(i++);
2158
+
2159
+ bits = o1 << 16 | o2 << 8 | o3;
2160
+
2161
+ h1 = bits >> 18 & 0x3f;
2162
+ h2 = bits >> 12 & 0x3f;
2163
+ h3 = bits >> 6 & 0x3f;
2164
+ h4 = bits & 0x3f;
2165
+
2166
+ // use hexets to index into b64, and append result to encoded string
2167
+ tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
2168
+ } while (i < data.length);
2169
+
2170
+ enc = tmp_arr.join('');
2171
+
2172
+ var r = data.length % 3;
2173
+
2174
+ return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
2175
+ };
2176
+
2177
+
2178
+ return {
2179
+ utf8_encode: utf8_encode,
2180
+ utf8_decode: utf8_decode,
2181
+ atob: atob,
2182
+ btoa: btoa
2183
+ };
2184
+ });
2185
+
2186
+ // Included from: src/javascript/runtime/Runtime.js
2187
+
2188
+ /**
2189
+ * Runtime.js
2190
+ *
2191
+ * Copyright 2013, Moxiecode Systems AB
2192
+ * Released under GPL License.
2193
+ *
2194
+ * License: http://www.plupload.com/license
2195
+ * Contributing: http://www.plupload.com/contributing
2196
+ */
2197
+
2198
+ define('moxie/runtime/Runtime', [
2199
+ "moxie/core/utils/Basic",
2200
+ "moxie/core/utils/Dom",
2201
+ "moxie/core/EventTarget"
2202
+ ], function(Basic, Dom, EventTarget) {
2203
+ var runtimeConstructors = {}, runtimes = {};
2204
+
2205
+ /**
2206
+ Common set of methods and properties for every runtime instance
2207
+
2208
+ @class Runtime
2209
+
2210
+ @param {Object} options
2211
+ @param {String} type Sanitized name of the runtime
2212
+ @param {Object} [caps] Set of capabilities that differentiate specified runtime
2213
+ @param {Object} [modeCaps] Set of capabilities that do require specific operational mode
2214
+ @param {String} [preferredMode='browser'] Preferred operational mode to choose if no required capabilities were requested
2215
+ */
2216
+ function Runtime(options, type, caps, modeCaps, preferredMode) {
2217
+ /**
2218
+ Dispatched when runtime is initialized and ready.
2219
+ Results in RuntimeInit on a connected component.
2220
+
2221
+ @event Init
2222
+ */
2223
+
2224
+ /**
2225
+ Dispatched when runtime fails to initialize.
2226
+ Results in RuntimeError on a connected component.
2227
+
2228
+ @event Error
2229
+ */
2230
+
2231
+ var self = this
2232
+ , _shim
2233
+ , _uid = Basic.guid(type + '_')
2234
+ , defaultMode = preferredMode || 'browser'
2235
+ ;
2236
+
2237
+ options = options || {};
2238
+
2239
+ // register runtime in private hash
2240
+ runtimes[_uid] = this;
2241
+
2242
+ /**
2243
+ Default set of capabilities, which can be redifined later by specific runtime
2244
+
2245
+ @private
2246
+ @property caps
2247
+ @type Object
2248
+ */
2249
+ caps = Basic.extend({
2250
+ // Runtime can:
2251
+ // provide access to raw binary data of the file
2252
+ access_binary: false,
2253
+ // provide access to raw binary data of the image (image extension is optional)
2254
+ access_image_binary: false,
2255
+ // display binary data as thumbs for example
2256
+ display_media: false,
2257
+ // make cross-domain requests
2258
+ do_cors: false,
2259
+ // accept files dragged and dropped from the desktop
2260
+ drag_and_drop: false,
2261
+ // filter files in selection dialog by their extensions
2262
+ filter_by_extension: true,
2263
+ // resize image (and manipulate it raw data of any file in general)
2264
+ resize_image: false,
2265
+ // periodically report how many bytes of total in the file were uploaded (loaded)
2266
+ report_upload_progress: false,
2267
+ // provide access to the headers of http response
2268
+ return_response_headers: false,
2269
+ // support response of specific type, which should be passed as an argument
2270
+ // e.g. runtime.can('return_response_type', 'blob')
2271
+ return_response_type: false,
2272
+ // return http status code of the response
2273
+ return_status_code: true,
2274
+ // send custom http header with the request
2275
+ send_custom_headers: false,
2276
+ // pick up the files from a dialog
2277
+ select_file: false,
2278
+ // select whole folder in file browse dialog
2279
+ select_folder: false,
2280
+ // select multiple files at once in file browse dialog
2281
+ select_multiple: true,
2282
+ // send raw binary data, that is generated after image resizing or manipulation of other kind
2283
+ send_binary_string: false,
2284
+ // send cookies with http request and therefore retain session
2285
+ send_browser_cookies: true,
2286
+ // send data formatted as multipart/form-data
2287
+ send_multipart: true,
2288
+ // slice the file or blob to smaller parts
2289
+ slice_blob: false,
2290
+ // upload file without preloading it to memory, stream it out directly from disk
2291
+ stream_upload: false,
2292
+ // programmatically trigger file browse dialog
2293
+ summon_file_dialog: false,
2294
+ // upload file of specific size, size should be passed as argument
2295
+ // e.g. runtime.can('upload_filesize', '500mb')
2296
+ upload_filesize: true,
2297
+ // initiate http request with specific http method, method should be passed as argument
2298
+ // e.g. runtime.can('use_http_method', 'put')
2299
+ use_http_method: true
2300
+ }, caps);
2301
+
2302
+
2303
+ // default to the mode that is compatible with preferred caps
2304
+ if (options.preferred_caps) {
2305
+ defaultMode = Runtime.getMode(modeCaps, options.preferred_caps, defaultMode);
2306
+ }
2307
+
2308
+ // small extension factory here (is meant to be extended with actual extensions constructors)
2309
+ _shim = (function() {
2310
+ var objpool = {};
2311
+ return {
2312
+ exec: function(uid, comp, fn, args) {
2313
+ if (_shim[comp]) {
2314
+ if (!objpool[uid]) {
2315
+ objpool[uid] = {
2316
+ context: this,
2317
+ instance: new _shim[comp]()
2318
+ };
2319
+ }
2320
+ if (objpool[uid].instance[fn]) {
2321
+ return objpool[uid].instance[fn].apply(this, args);
2322
+ }
2323
+ }
2324
+ },
2325
+
2326
+ removeInstance: function(uid) {
2327
+ delete objpool[uid];
2328
+ },
2329
+
2330
+ removeAllInstances: function() {
2331
+ var self = this;
2332
+ Basic.each(objpool, function(obj, uid) {
2333
+ if (Basic.typeOf(obj.instance.destroy) === 'function') {
2334
+ obj.instance.destroy.call(obj.context);
2335
+ }
2336
+ self.removeInstance(uid);
2337
+ });
2338
+ }
2339
+ };
2340
+ }());
2341
+
2342
+
2343
+ // public methods
2344
+ Basic.extend(this, {
2345
+ /**
2346
+ Specifies whether runtime instance was initialized or not
2347
+
2348
+ @property initialized
2349
+ @type {Boolean}
2350
+ @default false
2351
+ */
2352
+ initialized: false, // shims require this flag to stop initialization retries
2353
+
2354
+ /**
2355
+ Unique ID of the runtime
2356
+
2357
+ @property uid
2358
+ @type {String}
2359
+ */
2360
+ uid: _uid,
2361
+
2362
+ /**
2363
+ Runtime type (e.g. flash, html5, etc)
2364
+
2365
+ @property type
2366
+ @type {String}
2367
+ */
2368
+ type: type,
2369
+
2370
+ /**
2371
+ Runtime (not native one) may operate in browser or client mode.
2372
+
2373
+ @property mode
2374
+ @private
2375
+ @type {String|Boolean} current mode or false, if none possible
2376
+ */
2377
+ mode: Runtime.getMode(modeCaps, (options.required_caps), defaultMode),
2378
+
2379
+ /**
2380
+ id of the DOM container for the runtime (if available)
2381
+
2382
+ @property shimid
2383
+ @type {String}
2384
+ */
2385
+ shimid: _uid + '_container',
2386
+
2387
+ /**
2388
+ Number of connected clients. If equal to zero, runtime can be destroyed
2389
+
2390
+ @property clients
2391
+ @type {Number}
2392
+ */
2393
+ clients: 0,
2394
+
2395
+ /**
2396
+ Runtime initialization options
2397
+
2398
+ @property options
2399
+ @type {Object}
2400
+ */
2401
+ options: options,
2402
+
2403
+ /**
2404
+ Checks if the runtime has specific capability
2405
+
2406
+ @method can
2407
+ @param {String} cap Name of capability to check
2408
+ @param {Mixed} [value] If passed, capability should somehow correlate to the value
2409
+ @param {Object} [refCaps] Set of capabilities to check the specified cap against (defaults to internal set)
2410
+ @return {Boolean} true if runtime has such capability and false, if - not
2411
+ */
2412
+ can: function(cap, value) {
2413
+ var refCaps = arguments[2] || caps;
2414
+
2415
+ // if cap var is a comma-separated list of caps, convert it to object (key/value)
2416
+ if (Basic.typeOf(cap) === 'string' && Basic.typeOf(value) === 'undefined') {
2417
+ cap = Runtime.parseCaps(cap);
2418
+ }
2419
+
2420
+ if (Basic.typeOf(cap) === 'object') {
2421
+ for (var key in cap) {
2422
+ if (!this.can(key, cap[key], refCaps)) {
2423
+ return false;
2424
+ }
2425
+ }
2426
+ return true;
2427
+ }
2428
+
2429
+ // check the individual cap
2430
+ if (Basic.typeOf(refCaps[cap]) === 'function') {
2431
+ return refCaps[cap].call(this, value);
2432
+ } else {
2433
+ return (value === refCaps[cap]);
2434
+ }
2435
+ },
2436
+
2437
+ /**
2438
+ Returns container for the runtime as DOM element
2439
+
2440
+ @method getShimContainer
2441
+ @return {DOMElement}
2442
+ */
2443
+ getShimContainer: function() {
2444
+ var container, shimContainer = Dom.get(this.shimid);
2445
+
2446
+ // if no container for shim, create one
2447
+ if (!shimContainer) {
2448
+ container = this.options.container ? Dom.get(this.options.container) : document.body;
2449
+
2450
+ // create shim container and insert it at an absolute position into the outer container
2451
+ shimContainer = document.createElement('div');
2452
+ shimContainer.id = this.shimid;
2453
+ shimContainer.className = 'moxie-shim moxie-shim-' + this.type;
2454
+
2455
+ Basic.extend(shimContainer.style, {
2456
+ position: 'absolute',
2457
+ top: '0px',
2458
+ left: '0px',
2459
+ width: '1px',
2460
+ height: '1px',
2461
+ overflow: 'hidden'
2462
+ });
2463
+
2464
+ container.appendChild(shimContainer);
2465
+ container = null;
2466
+ }
2467
+
2468
+ return shimContainer;
2469
+ },
2470
+
2471
+ /**
2472
+ Returns runtime as DOM element (if appropriate)
2473
+
2474
+ @method getShim
2475
+ @return {DOMElement}
2476
+ */
2477
+ getShim: function() {
2478
+ return _shim;
2479
+ },
2480
+
2481
+ /**
2482
+ Invokes a method within the runtime itself (might differ across the runtimes)
2483
+
2484
+ @method shimExec
2485
+ @param {Mixed} []
2486
+ @protected
2487
+ @return {Mixed} Depends on the action and component
2488
+ */
2489
+ shimExec: function(component, action) {
2490
+ var args = [].slice.call(arguments, 2);
2491
+ return self.getShim().exec.call(this, this.uid, component, action, args);
2492
+ },
2493
+
2494
+ /**
2495
+ Operaional interface that is used by components to invoke specific actions on the runtime
2496
+ (is invoked in the scope of component)
2497
+
2498
+ @method exec
2499
+ @param {Mixed} []*
2500
+ @protected
2501
+ @return {Mixed} Depends on the action and component
2502
+ */
2503
+ exec: function(component, action) { // this is called in the context of component, not runtime
2504
+ var args = [].slice.call(arguments, 2);
2505
+
2506
+ if (self[component] && self[component][action]) {
2507
+ return self[component][action].apply(this, args);
2508
+ }
2509
+ return self.shimExec.apply(this, arguments);
2510
+ },
2511
+
2512
+ /**
2513
+ Destroys the runtime (removes all events and deletes DOM structures)
2514
+
2515
+ @method destroy
2516
+ */
2517
+ destroy: function() {
2518
+ if (!self) {
2519
+ return; // obviously already destroyed
2520
+ }
2521
+
2522
+ var shimContainer = Dom.get(this.shimid);
2523
+ if (shimContainer) {
2524
+ shimContainer.parentNode.removeChild(shimContainer);
2525
+ }
2526
+
2527
+ if (_shim) {
2528
+ _shim.removeAllInstances();
2529
+ }
2530
+
2531
+ this.unbindAll();
2532
+ delete runtimes[this.uid];
2533
+ this.uid = null; // mark this runtime as destroyed
2534
+ _uid = self = _shim = shimContainer = null;
2535
+ }
2536
+ });
2537
+
2538
+ // once we got the mode, test against all caps
2539
+ if (this.mode && options.required_caps && !this.can(options.required_caps)) {
2540
+ this.mode = false;
2541
+ }
2542
+ }
2543
+
2544
+
2545
+ /**
2546
+ Default order to try different runtime types
2547
+
2548
+ @property order
2549
+ @type String
2550
+ @static
2551
+ */
2552
+ Runtime.order = 'html5,flash,silverlight,html4';
2553
+
2554
+
2555
+ /**
2556
+ Retrieves runtime from private hash by it's uid
2557
+
2558
+ @method getRuntime
2559
+ @private
2560
+ @static
2561
+ @param {String} uid Unique identifier of the runtime
2562
+ @return {Runtime|Boolean} Returns runtime, if it exists and false, if - not
2563
+ */
2564
+ Runtime.getRuntime = function(uid) {
2565
+ return runtimes[uid] ? runtimes[uid] : false;
2566
+ };
2567
+
2568
+
2569
+ /**
2570
+ Register constructor for the Runtime of new (or perhaps modified) type
2571
+
2572
+ @method addConstructor
2573
+ @static
2574
+ @param {String} type Runtime type (e.g. flash, html5, etc)
2575
+ @param {Function} construct Constructor for the Runtime type
2576
+ */
2577
+ Runtime.addConstructor = function(type, constructor) {
2578
+ constructor.prototype = EventTarget.instance;
2579
+ runtimeConstructors[type] = constructor;
2580
+ };
2581
+
2582
+
2583
+ /**
2584
+ Get the constructor for the specified type.
2585
+
2586
+ method getConstructor
2587
+ @static
2588
+ @param {String} type Runtime type (e.g. flash, html5, etc)
2589
+ @return {Function} Constructor for the Runtime type
2590
+ */
2591
+ Runtime.getConstructor = function(type) {
2592
+ return runtimeConstructors[type] || null;
2593
+ };
2594
+
2595
+
2596
+ /**
2597
+ Get info about the runtime (uid, type, capabilities)
2598
+
2599
+ @method getInfo
2600
+ @static
2601
+ @param {String} uid Unique identifier of the runtime
2602
+ @return {Mixed} Info object or null if runtime doesn't exist
2603
+ */
2604
+ Runtime.getInfo = function(uid) {
2605
+ var runtime = Runtime.getRuntime(uid);
2606
+
2607
+ if (runtime) {
2608
+ return {
2609
+ uid: runtime.uid,
2610
+ type: runtime.type,
2611
+ mode: runtime.mode,
2612
+ can: function() {
2613
+ return runtime.can.apply(runtime, arguments);
2614
+ }
2615
+ };
2616
+ }
2617
+ return null;
2618
+ };
2619
+
2620
+
2621
+ /**
2622
+ Convert caps represented by a comma-separated string to the object representation.
2623
+
2624
+ @method parseCaps
2625
+ @static
2626
+ @param {String} capStr Comma-separated list of capabilities
2627
+ @return {Object}
2628
+ */
2629
+ Runtime.parseCaps = function(capStr) {
2630
+ var capObj = {};
2631
+
2632
+ if (Basic.typeOf(capStr) !== 'string') {
2633
+ return capStr || {};
2634
+ }
2635
+
2636
+ Basic.each(capStr.split(','), function(key) {
2637
+ capObj[key] = true; // we assume it to be - true
2638
+ });
2639
+
2640
+ return capObj;
2641
+ };
2642
+
2643
+ /**
2644
+ Test the specified runtime for specific capabilities.
2645
+
2646
+ @method can
2647
+ @static
2648
+ @param {String} type Runtime type (e.g. flash, html5, etc)
2649
+ @param {String|Object} caps Set of capabilities to check
2650
+ @return {Boolean} Result of the test
2651
+ */
2652
+ Runtime.can = function(type, caps) {
2653
+ var runtime
2654
+ , constructor = Runtime.getConstructor(type)
2655
+ , mode
2656
+ ;
2657
+ if (constructor) {
2658
+ runtime = new constructor({
2659
+ required_caps: caps
2660
+ });
2661
+ mode = runtime.mode;
2662
+ runtime.destroy();
2663
+ return !!mode;
2664
+ }
2665
+ return false;
2666
+ };
2667
+
2668
+
2669
+ /**
2670
+ Figure out a runtime that supports specified capabilities.
2671
+
2672
+ @method thatCan
2673
+ @static
2674
+ @param {String|Object} caps Set of capabilities to check
2675
+ @param {String} [runtimeOrder] Comma-separated list of runtimes to check against
2676
+ @return {String} Usable runtime identifier or null
2677
+ */
2678
+ Runtime.thatCan = function(caps, runtimeOrder) {
2679
+ var types = (runtimeOrder || Runtime.order).split(/\s*,\s*/);
2680
+ for (var i in types) {
2681
+ if (Runtime.can(types[i], caps)) {
2682
+ return types[i];
2683
+ }
2684
+ }
2685
+ return null;
2686
+ };
2687
+
2688
+
2689
+ /**
2690
+ Figure out an operational mode for the specified set of capabilities.
2691
+
2692
+ @method getMode
2693
+ @static
2694
+ @param {Object} modeCaps Set of capabilities that depend on particular runtime mode
2695
+ @param {Object} [requiredCaps] Supplied set of capabilities to find operational mode for
2696
+ @param {String|Boolean} [defaultMode='browser'] Default mode to use
2697
+ @return {String|Boolean} Compatible operational mode
2698
+ */
2699
+ Runtime.getMode = function(modeCaps, requiredCaps, defaultMode) {
2700
+ var mode = null;
2701
+
2702
+ if (Basic.typeOf(defaultMode) === 'undefined') { // only if not specified
2703
+ defaultMode = 'browser';
2704
+ }
2705
+
2706
+ if (requiredCaps && !Basic.isEmptyObj(modeCaps)) {
2707
+ // loop over required caps and check if they do require the same mode
2708
+ Basic.each(requiredCaps, function(value, cap) {
2709
+ if (modeCaps.hasOwnProperty(cap)) {
2710
+ var capMode = modeCaps[cap](value);
2711
+
2712
+ // make sure we always have an array
2713
+ if (typeof(capMode) === 'string') {
2714
+ capMode = [capMode];
2715
+ }
2716
+
2717
+ if (!mode) {
2718
+ mode = capMode;
2719
+ } else if (!(mode = Basic.arrayIntersect(mode, capMode))) {
2720
+ // if cap requires conflicting mode - runtime cannot fulfill required caps
2721
+ return (mode = false);
2722
+ }
2723
+ }
2724
+ });
2725
+
2726
+ if (mode) {
2727
+ return Basic.inArray(defaultMode, mode) !== -1 ? defaultMode : mode[0];
2728
+ } else if (mode === false) {
2729
+ return false;
2730
+ }
2731
+ }
2732
+ return defaultMode;
2733
+ };
2734
+
2735
+
2736
+ /**
2737
+ Capability check that always returns true
2738
+
2739
+ @private
2740
+ @static
2741
+ @return {True}
2742
+ */
2743
+ Runtime.capTrue = function() {
2744
+ return true;
2745
+ };
2746
+
2747
+ /**
2748
+ Capability check that always returns false
2749
+
2750
+ @private
2751
+ @static
2752
+ @return {False}
2753
+ */
2754
+ Runtime.capFalse = function() {
2755
+ return false;
2756
+ };
2757
+
2758
+ /**
2759
+ Evaluate the expression to boolean value and create a function that always returns it.
2760
+
2761
+ @private
2762
+ @static
2763
+ @param {Mixed} expr Expression to evaluate
2764
+ @return {Function} Function returning the result of evaluation
2765
+ */
2766
+ Runtime.capTest = function(expr) {
2767
+ return function() {
2768
+ return !!expr;
2769
+ };
2770
+ };
2771
+
2772
+ return Runtime;
2773
+ });
2774
+
2775
+ // Included from: src/javascript/runtime/RuntimeClient.js
2776
+
2777
+ /**
2778
+ * RuntimeClient.js
2779
+ *
2780
+ * Copyright 2013, Moxiecode Systems AB
2781
+ * Released under GPL License.
2782
+ *
2783
+ * License: http://www.plupload.com/license
2784
+ * Contributing: http://www.plupload.com/contributing
2785
+ */
2786
+
2787
+ define('moxie/runtime/RuntimeClient', [
2788
+ 'moxie/core/Exceptions',
2789
+ 'moxie/core/utils/Basic',
2790
+ 'moxie/runtime/Runtime'
2791
+ ], function(x, Basic, Runtime) {
2792
+ /**
2793
+ Set of methods and properties, required by a component to acquire ability to connect to a runtime
2794
+
2795
+ @class RuntimeClient
2796
+ */
2797
+ return function RuntimeClient() {
2798
+ var runtime;
2799
+
2800
+ Basic.extend(this, {
2801
+ /**
2802
+ Connects to the runtime specified by the options. Will either connect to existing runtime or create a new one.
2803
+ Increments number of clients connected to the specified runtime.
2804
+
2805
+ @method connectRuntime
2806
+ @param {Mixed} options Can be a runtme uid or a set of key-value pairs defining requirements and pre-requisites
2807
+ */
2808
+ connectRuntime: function(options) {
2809
+ var comp = this, ruid;
2810
+
2811
+ function initialize(items) {
2812
+ var type, constructor;
2813
+
2814
+ // if we ran out of runtimes
2815
+ if (!items.length) {
2816
+ comp.trigger('RuntimeError', new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
2817
+ runtime = null;
2818
+ return;
2819
+ }
2820
+
2821
+ type = items.shift();
2822
+ constructor = Runtime.getConstructor(type);
2823
+ if (!constructor) {
2824
+ initialize(items);
2825
+ return;
2826
+ }
2827
+
2828
+ // try initializing the runtime
2829
+ runtime = new constructor(options);
2830
+
2831
+ runtime.bind('Init', function() {
2832
+ // mark runtime as initialized
2833
+ runtime.initialized = true;
2834
+
2835
+ // jailbreak ...
2836
+ setTimeout(function() {
2837
+ runtime.clients++;
2838
+ // this will be triggered on component
2839
+ comp.trigger('RuntimeInit', runtime);
2840
+ }, 1);
2841
+ });
2842
+
2843
+ runtime.bind('Error', function() {
2844
+ runtime.destroy(); // runtime cannot destroy itself from inside at a right moment, thus we do it here
2845
+ initialize(items);
2846
+ });
2847
+
2848
+ /*runtime.bind('Exception', function() { });*/
2849
+
2850
+ // check if runtime managed to pick-up operational mode
2851
+ if (!runtime.mode) {
2852
+ runtime.trigger('Error');
2853
+ return;
2854
+ }
2855
+
2856
+ runtime.init();
2857
+ }
2858
+
2859
+ // check if a particular runtime was requested
2860
+ if (Basic.typeOf(options) === 'string') {
2861
+ ruid = options;
2862
+ } else if (Basic.typeOf(options.ruid) === 'string') {
2863
+ ruid = options.ruid;
2864
+ }
2865
+
2866
+ if (ruid) {
2867
+ runtime = Runtime.getRuntime(ruid);
2868
+ if (runtime) {
2869
+ runtime.clients++;
2870
+ return runtime;
2871
+ } else {
2872
+ // there should be a runtime and there's none - weird case
2873
+ throw new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR);
2874
+ }
2875
+ }
2876
+
2877
+ // initialize a fresh one, that fits runtime list and required features best
2878
+ initialize((options.runtime_order || Runtime.order).split(/\s*,\s*/));
2879
+ },
2880
+
2881
+ /**
2882
+ Returns the runtime to which the client is currently connected.
2883
+
2884
+ @method getRuntime
2885
+ @return {Runtime} Runtime or null if client is not connected
2886
+ */
2887
+ getRuntime: function() {
2888
+ if (runtime && runtime.uid) {
2889
+ return runtime;
2890
+ }
2891
+ runtime = null; // make sure we do not leave zombies rambling around
2892
+ return null;
2893
+ },
2894
+
2895
+ /**
2896
+ Disconnects from the runtime. Decrements number of clients connected to the specified runtime.
2897
+
2898
+ @method disconnectRuntime
2899
+ */
2900
+ disconnectRuntime: function() {
2901
+ if (runtime && --runtime.clients <= 0) {
2902
+ runtime.destroy();
2903
+ runtime = null;
2904
+ }
2905
+ }
2906
+
2907
+ });
2908
+ };
2909
+
2910
+
2911
+ });
2912
+
2913
+ // Included from: src/javascript/file/Blob.js
2914
+
2915
+ /**
2916
+ * Blob.js
2917
+ *
2918
+ * Copyright 2013, Moxiecode Systems AB
2919
+ * Released under GPL License.
2920
+ *
2921
+ * License: http://www.plupload.com/license
2922
+ * Contributing: http://www.plupload.com/contributing
2923
+ */
2924
+
2925
+ define('moxie/file/Blob', [
2926
+ 'moxie/core/utils/Basic',
2927
+ 'moxie/core/utils/Encode',
2928
+ 'moxie/runtime/RuntimeClient'
2929
+ ], function(Basic, Encode, RuntimeClient) {
2930
+
2931
+ var blobpool = {};
2932
+
2933
+ /**
2934
+ @class Blob
2935
+ @constructor
2936
+ @param {String} ruid Unique id of the runtime, to which this blob belongs to
2937
+ @param {Object} blob Object "Native" blob object, as it is represented in the runtime
2938
+ */
2939
+ function Blob(ruid, blob) {
2940
+
2941
+ function _sliceDetached(start, end, type) {
2942
+ var blob, data = blobpool[this.uid];
2943
+
2944
+ if (Basic.typeOf(data) !== 'string' || !data.length) {
2945
+ return null; // or throw exception
2946
+ }
2947
+
2948
+ blob = new Blob(null, {
2949
+ type: type,
2950
+ size: end - start
2951
+ });
2952
+ blob.detach(data.substr(start, blob.size));
2953
+
2954
+ return blob;
2955
+ }
2956
+
2957
+ RuntimeClient.call(this);
2958
+
2959
+ if (ruid) {
2960
+ this.connectRuntime(ruid);
2961
+ }
2962
+
2963
+ if (!blob) {
2964
+ blob = {};
2965
+ } else if (Basic.typeOf(blob) === 'string') { // dataUrl or binary string
2966
+ blob = { data: blob };
2967
+ }
2968
+
2969
+ Basic.extend(this, {
2970
+
2971
+ /**
2972
+ Unique id of the component
2973
+
2974
+ @property uid
2975
+ @type {String}
2976
+ */
2977
+ uid: blob.uid || Basic.guid('uid_'),
2978
+
2979
+ /**
2980
+ Unique id of the connected runtime, if falsy, then runtime will have to be initialized
2981
+ before this Blob can be used, modified or sent
2982
+
2983
+ @property ruid
2984
+ @type {String}
2985
+ */
2986
+ ruid: ruid,
2987
+
2988
+ /**
2989
+ Size of blob
2990
+
2991
+ @property size
2992
+ @type {Number}
2993
+ @default 0
2994
+ */
2995
+ size: blob.size || 0,
2996
+
2997
+ /**
2998
+ Mime type of blob
2999
+
3000
+ @property type
3001
+ @type {String}
3002
+ @default ''
3003
+ */
3004
+ type: blob.type || '',
3005
+
3006
+ /**
3007
+ @method slice
3008
+ @param {Number} [start=0]
3009
+ */
3010
+ slice: function(start, end, type) {
3011
+ if (this.isDetached()) {
3012
+ return _sliceDetached.apply(this, arguments);
3013
+ }
3014
+ return this.getRuntime().exec.call(this, 'Blob', 'slice', this.getSource(), start, end, type);
3015
+ },
3016
+
3017
+ /**
3018
+ Returns "native" blob object (as it is represented in connected runtime) or null if not found
3019
+
3020
+ @method getSource
3021
+ @return {Blob} Returns "native" blob object or null if not found
3022
+ */
3023
+ getSource: function() {
3024
+ if (!blobpool[this.uid]) {
3025
+ return null;
3026
+ }
3027
+ return blobpool[this.uid];
3028
+ },
3029
+
3030
+ /**
3031
+ Detaches blob from any runtime that it depends on and initialize with standalone value
3032
+
3033
+ @method detach
3034
+ @protected
3035
+ @param {DOMString} [data=''] Standalone value
3036
+ */
3037
+ detach: function(data) {
3038
+ if (this.ruid) {
3039
+ this.getRuntime().exec.call(this, 'Blob', 'destroy', blobpool[this.uid]);
3040
+ this.disconnectRuntime();
3041
+ this.ruid = null;
3042
+ }
3043
+
3044
+ data = data || '';
3045
+
3046
+ // if dataUrl, convert to binary string
3047
+ var matches = data.match(/^data:([^;]*);base64,/);
3048
+ if (matches) {
3049
+ this.type = matches[1];
3050
+ data = Encode.atob(data.substring(data.indexOf('base64,') + 7));
3051
+ }
3052
+
3053
+ this.size = data.length;
3054
+
3055
+ blobpool[this.uid] = data;
3056
+ },
3057
+
3058
+ /**
3059
+ Checks if blob is standalone (detached of any runtime)
3060
+
3061
+ @method isDetached
3062
+ @protected
3063
+ @return {Boolean}
3064
+ */
3065
+ isDetached: function() {
3066
+ return !this.ruid && Basic.typeOf(blobpool[this.uid]) === 'string';
3067
+ },
3068
+
3069
+ /**
3070
+ Destroy Blob and free any resources it was using
3071
+
3072
+ @method destroy
3073
+ */
3074
+ destroy: function() {
3075
+ this.detach();
3076
+ delete blobpool[this.uid];
3077
+ }
3078
+ });
3079
+
3080
+
3081
+ if (blob.data) {
3082
+ this.detach(blob.data); // auto-detach if payload has been passed
3083
+ } else {
3084
+ blobpool[this.uid] = blob;
3085
+ }
3086
+ }
3087
+
3088
+ return Blob;
3089
+ });
3090
+
3091
+ // Included from: src/javascript/file/File.js
3092
+
3093
+ /**
3094
+ * File.js
3095
+ *
3096
+ * Copyright 2013, Moxiecode Systems AB
3097
+ * Released under GPL License.
3098
+ *
3099
+ * License: http://www.plupload.com/license
3100
+ * Contributing: http://www.plupload.com/contributing
3101
+ */
3102
+
3103
+ define('moxie/file/File', [
3104
+ 'moxie/core/utils/Basic',
3105
+ 'moxie/core/utils/Mime',
3106
+ 'moxie/file/Blob'
3107
+ ], function(Basic, Mime, Blob) {
3108
+ /**
3109
+ @class File
3110
+ @extends Blob
3111
+ @constructor
3112
+ @param {String} ruid Unique id of the runtime, to which this blob belongs to
3113
+ @param {Object} file Object "Native" file object, as it is represented in the runtime
3114
+ */
3115
+ function File(ruid, file) {
3116
+ var name, type;
3117
+
3118
+ if (!file) { // avoid extra errors in case we overlooked something
3119
+ file = {};
3120
+ }
3121
+
3122
+ // figure out the type
3123
+ if (file.type && file.type !== '') {
3124
+ type = file.type;
3125
+ } else {
3126
+ type = Mime.getFileMime(file.name);
3127
+ }
3128
+
3129
+ // sanitize file name or generate new one
3130
+ if (file.name) {
3131
+ name = file.name.replace(/\\/g, '/');
3132
+ name = name.substr(name.lastIndexOf('/') + 1);
3133
+ } else {
3134
+ var prefix = type.split('/')[0];
3135
+ name = Basic.guid((prefix !== '' ? prefix : 'file') + '_');
3136
+
3137
+ if (Mime.extensions[type]) {
3138
+ name += '.' + Mime.extensions[type][0]; // append proper extension if possible
3139
+ }
3140
+ }
3141
+
3142
+ Blob.apply(this, arguments);
3143
+
3144
+ Basic.extend(this, {
3145
+ /**
3146
+ File mime type
3147
+
3148
+ @property type
3149
+ @type {String}
3150
+ @default ''
3151
+ */
3152
+ type: type || '',
3153
+
3154
+ /**
3155
+ File name
3156
+
3157
+ @property name
3158
+ @type {String}
3159
+ @default UID
3160
+ */
3161
+ name: name || Basic.guid('file_'),
3162
+
3163
+ /**
3164
+ Date of last modification
3165
+
3166
+ @property lastModifiedDate
3167
+ @type {String}
3168
+ @default now
3169
+ */
3170
+ lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString() // Thu Aug 23 2012 19:40:00 GMT+0400 (GET)
3171
+ });
3172
+ }
3173
+
3174
+ File.prototype = Blob.prototype;
3175
+
3176
+ return File;
3177
+ });
3178
+
3179
+ // Included from: src/javascript/file/FileInput.js
3180
+
3181
+ /**
3182
+ * FileInput.js
3183
+ *
3184
+ * Copyright 2013, Moxiecode Systems AB
3185
+ * Released under GPL License.
3186
+ *
3187
+ * License: http://www.plupload.com/license
3188
+ * Contributing: http://www.plupload.com/contributing
3189
+ */
3190
+
3191
+ define('moxie/file/FileInput', [
3192
+ 'moxie/core/utils/Basic',
3193
+ 'moxie/core/utils/Mime',
3194
+ 'moxie/core/utils/Dom',
3195
+ 'moxie/core/Exceptions',
3196
+ 'moxie/core/EventTarget',
3197
+ 'moxie/core/I18n',
3198
+ 'moxie/file/File',
3199
+ 'moxie/runtime/Runtime',
3200
+ 'moxie/runtime/RuntimeClient'
3201
+ ], function(Basic, Mime, Dom, x, EventTarget, I18n, File, Runtime, RuntimeClient) {
3202
+ /**
3203
+ Provides a convenient way to create cross-browser file-picker. Generates file selection dialog on click,
3204
+ converts selected files to _File_ objects, to be used in conjunction with _Image_, preloaded in memory
3205
+ with _FileReader_ or uploaded to a server through _XMLHttpRequest_.
3206
+
3207
+ @class FileInput
3208
+ @constructor
3209
+ @extends EventTarget
3210
+ @uses RuntimeClient
3211
+ @param {Object|String|DOMElement} options If options is string or node, argument is considered as _browse\_button_.
3212
+ @param {String|DOMElement} options.browse_button DOM Element to turn into file picker.
3213
+ @param {Array} [options.accept] Array of mime types to accept. By default accepts all.
3214
+ @param {String} [options.file='file'] Name of the file field (not the filename).
3215
+ @param {Boolean} [options.multiple=false] Enable selection of multiple files.
3216
+ @param {Boolean} [options.directory=false] Turn file input into the folder input (cannot be both at the same time).
3217
+ @param {String|DOMElement} [options.container] DOM Element to use as a container for file-picker. Defaults to parentNode
3218
+ for _browse\_button_.
3219
+ @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support.
3220
+
3221
+ @example
3222
+ <div id="container">
3223
+ <a id="file-picker" href="javascript:;">Browse...</a>
3224
+ </div>
3225
+
3226
+ <script>
3227
+ var fileInput = new mOxie.FileInput({
3228
+ browse_button: 'file-picker', // or document.getElementById('file-picker')
3229
+ container: 'container',
3230
+ accept: [
3231
+ {title: "Image files", extensions: "jpg,gif,png"} // accept only images
3232
+ ],
3233
+ multiple: true // allow multiple file selection
3234
+ });
3235
+
3236
+ fileInput.onchange = function(e) {
3237
+ // do something to files array
3238
+ console.info(e.target.files); // or this.files or fileInput.files
3239
+ };
3240
+
3241
+ fileInput.init(); // initialize
3242
+ </script>
3243
+ */
3244
+ var dispatches = [
3245
+ /**
3246
+ Dispatched when runtime is connected and file-picker is ready to be used.
3247
+
3248
+ @event ready
3249
+ @param {Object} event
3250
+ */
3251
+ 'ready',
3252
+
3253
+ /**
3254
+ Dispatched right after [ready](#event_ready) event, and whenever [refresh()](#method_refresh) is invoked.
3255
+ Check [corresponding documentation entry](#method_refresh) for more info.
3256
+
3257
+ @event refresh
3258
+ @param {Object} event
3259
+ */
3260
+
3261
+ /**
3262
+ Dispatched when selection of files in the dialog is complete.
3263
+
3264
+ @event change
3265
+ @param {Object} event
3266
+ */
3267
+ 'change',
3268
+
3269
+ 'cancel', // TODO: might be useful
3270
+
3271
+ /**
3272
+ Dispatched when mouse cursor enters file-picker area. Can be used to style element
3273
+ accordingly.
3274
+
3275
+ @event mouseenter
3276
+ @param {Object} event
3277
+ */
3278
+ 'mouseenter',
3279
+
3280
+ /**
3281
+ Dispatched when mouse cursor leaves file-picker area. Can be used to style element
3282
+ accordingly.
3283
+
3284
+ @event mouseleave
3285
+ @param {Object} event
3286
+ */
3287
+ 'mouseleave',
3288
+
3289
+ /**
3290
+ Dispatched when functional mouse button is pressed on top of file-picker area.
3291
+
3292
+ @event mousedown
3293
+ @param {Object} event
3294
+ */
3295
+ 'mousedown',
3296
+
3297
+ /**
3298
+ Dispatched when functional mouse button is released on top of file-picker area.
3299
+
3300
+ @event mouseup
3301
+ @param {Object} event
3302
+ */
3303
+ 'mouseup'
3304
+ ];
3305
+
3306
+ function FileInput(options) {
3307
+ var self = this,
3308
+ container, browseButton, defaults;
3309
+
3310
+ // if flat argument passed it should be browse_button id
3311
+ if (Basic.inArray(Basic.typeOf(options), ['string', 'node']) !== -1) {
3312
+ options = { browse_button : options };
3313
+ }
3314
+
3315
+ // this will help us to find proper default container
3316
+ browseButton = Dom.get(options.browse_button);
3317
+ if (!browseButton) {
3318
+ // browse button is required
3319
+ throw new x.DOMException(x.DOMException.NOT_FOUND_ERR);
3320
+ }
3321
+
3322
+ // figure out the options
3323
+ defaults = {
3324
+ accept: [{
3325
+ title: I18n.translate('All Files'),
3326
+ extensions: '*'
3327
+ }],
3328
+ name: 'file',
3329
+ multiple: false,
3330
+ required_caps: false,
3331
+ container: browseButton.parentNode || document.body
3332
+ };
3333
+
3334
+ options = Basic.extend({}, defaults, options);
3335
+
3336
+ // convert to object representation
3337
+ if (typeof(options.required_caps) === 'string') {
3338
+ options.required_caps = Runtime.parseCaps(options.required_caps);
3339
+ }
3340
+
3341
+ // normalize accept option (could be list of mime types or array of title/extensions pairs)
3342
+ if (typeof(options.accept) === 'string') {
3343
+ options.accept = Mime.mimes2extList(options.accept);
3344
+ }
3345
+
3346
+ container = Dom.get(options.container);
3347
+ // make sure we have container
3348
+ if (!container) {
3349
+ container = document.body;
3350
+ }
3351
+
3352
+ // make container relative, if it's not
3353
+ if (Dom.getStyle(container, 'position') === 'static') {
3354
+ container.style.position = 'relative';
3355
+ }
3356
+
3357
+ container = browseButton = null; // IE
3358
+
3359
+ RuntimeClient.call(self);
3360
+
3361
+ Basic.extend(self, {
3362
+ /**
3363
+ Unique id of the component
3364
+
3365
+ @property uid
3366
+ @protected
3367
+ @readOnly
3368
+ @type {String}
3369
+ @default UID
3370
+ */
3371
+ uid: Basic.guid('uid_'),
3372
+
3373
+ /**
3374
+ Unique id of the connected runtime, if any.
3375
+
3376
+ @property ruid
3377
+ @protected
3378
+ @type {String}
3379
+ */
3380
+ ruid: null,
3381
+
3382
+ /**
3383
+ Unique id of the runtime container. Useful to get hold of it for various manipulations.
3384
+
3385
+ @property shimid
3386
+ @protected
3387
+ @type {String}
3388
+ */
3389
+ shimid: null,
3390
+
3391
+ /**
3392
+ Array of selected mOxie.File objects
3393
+
3394
+ @property files
3395
+ @type {Array}
3396
+ @default null
3397
+ */
3398
+ files: null,
3399
+
3400
+ /**
3401
+ Initializes the file-picker, connects it to runtime and dispatches event ready when done.
3402
+
3403
+ @method init
3404
+ */
3405
+ init: function() {
3406
+ self.convertEventPropsToHandlers(dispatches);
3407
+
3408
+ self.bind('RuntimeInit', function(e, runtime) {
3409
+ self.ruid = runtime.uid;
3410
+ self.shimid = runtime.shimid;
3411
+
3412
+ self.bind("Ready", function() {
3413
+ self.trigger("Refresh");
3414
+ }, 999);
3415
+
3416
+ self.bind("Change", function() {
3417
+ var files = runtime.exec.call(self, 'FileInput', 'getFiles');
3418
+
3419
+ self.files = [];
3420
+
3421
+ Basic.each(files, function(file) {
3422
+ // ignore empty files (IE10 for example hangs if you try to send them via XHR)
3423
+ if (file.size === 0) {
3424
+ return true;
3425
+ }
3426
+ self.files.push(new File(self.ruid, file));
3427
+ });
3428
+ }, 999);
3429
+
3430
+ // re-position and resize shim container
3431
+ self.bind('Refresh', function() {
3432
+ var pos, size, browseButton, shimContainer;
3433
+
3434
+ browseButton = Dom.get(options.browse_button);
3435
+ shimContainer = Dom.get(runtime.shimid); // do not use runtime.getShimContainer(), since it will create container if it doesn't exist
3436
+
3437
+ if (browseButton) {
3438
+ pos = Dom.getPos(browseButton, Dom.get(options.container));
3439
+ size = Dom.getSize(browseButton);
3440
+
3441
+ if (shimContainer) {
3442
+ Basic.extend(shimContainer.style, {
3443
+ top : pos.y + 'px',
3444
+ left : pos.x + 'px',
3445
+ width : size.w + 'px',
3446
+ height : size.h + 'px'
3447
+ });
3448
+ }
3449
+ }
3450
+ shimContainer = browseButton = null;
3451
+ });
3452
+
3453
+ runtime.exec.call(self, 'FileInput', 'init', options);
3454
+ });
3455
+
3456
+ // runtime needs: options.required_features, options.runtime_order and options.container
3457
+ self.connectRuntime(Basic.extend({}, options, {
3458
+ required_caps: {
3459
+ select_file: true
3460
+ }
3461
+ }));
3462
+ },
3463
+
3464
+ /**
3465
+ Disables file-picker element, so that it doesn't react to mouse clicks.
3466
+
3467
+ @method disable
3468
+ @param {Boolean} [state=true] Disable component if - true, enable if - false
3469
+ */
3470
+ disable: function(state) {
3471
+ var runtime = this.getRuntime();
3472
+ if (runtime) {
3473
+ runtime.exec.call(this, 'FileInput', 'disable', Basic.typeOf(state) === 'undefined' ? true : state);
3474
+ }
3475
+ },
3476
+
3477
+
3478
+ /**
3479
+ Reposition and resize dialog trigger to match the position and size of browse_button element.
3480
+
3481
+ @method refresh
3482
+ */
3483
+ refresh: function() {
3484
+ self.trigger("Refresh");
3485
+ },
3486
+
3487
+
3488
+ /**
3489
+ Destroy component.
3490
+
3491
+ @method destroy
3492
+ */
3493
+ destroy: function() {
3494
+ var runtime = this.getRuntime();
3495
+ if (runtime) {
3496
+ runtime.exec.call(this, 'FileInput', 'destroy');
3497
+ this.disconnectRuntime();
3498
+ }
3499
+
3500
+ if (Basic.typeOf(this.files) === 'array') {
3501
+ // no sense in leaving associated files behind
3502
+ Basic.each(this.files, function(file) {
3503
+ file.destroy();
3504
+ });
3505
+ }
3506
+ this.files = null;
3507
+ }
3508
+ });
3509
+ }
3510
+
3511
+ FileInput.prototype = EventTarget.instance;
3512
+
3513
+ return FileInput;
3514
+ });
3515
+
3516
+ // Included from: src/javascript/file/FileDrop.js
3517
+
3518
+ /**
3519
+ * FileDrop.js
3520
+ *
3521
+ * Copyright 2013, Moxiecode Systems AB
3522
+ * Released under GPL License.
3523
+ *
3524
+ * License: http://www.plupload.com/license
3525
+ * Contributing: http://www.plupload.com/contributing
3526
+ */
3527
+
3528
+ define('moxie/file/FileDrop', [
3529
+ 'moxie/core/I18n',
3530
+ 'moxie/core/utils/Dom',
3531
+ 'moxie/core/Exceptions',
3532
+ 'moxie/core/utils/Basic',
3533
+ 'moxie/file/File',
3534
+ 'moxie/runtime/RuntimeClient',
3535
+ 'moxie/core/EventTarget',
3536
+ 'moxie/core/utils/Mime'
3537
+ ], function(I18n, Dom, x, Basic, File, RuntimeClient, EventTarget, Mime) {
3538
+ /**
3539
+ Turn arbitrary DOM element to a drop zone accepting files. Converts selected files to _File_ objects, to be used
3540
+ in conjunction with _Image_, preloaded in memory with _FileReader_ or uploaded to a server through
3541
+ _XMLHttpRequest_.
3542
+
3543
+ @example
3544
+ <div id="drop_zone">
3545
+ Drop files here
3546
+ </div>
3547
+ <br />
3548
+ <div id="filelist"></div>
3549
+
3550
+ <script type="text/javascript">
3551
+ var fileDrop = new mOxie.FileDrop('drop_zone'), fileList = mOxie.get('filelist');
3552
+
3553
+ fileDrop.ondrop = function() {
3554
+ mOxie.each(this.files, function(file) {
3555
+ fileList.innerHTML += '<div>' + file.name + '</div>';
3556
+ });
3557
+ };
3558
+
3559
+ fileDrop.init();
3560
+ </script>
3561
+
3562
+ @class FileDrop
3563
+ @constructor
3564
+ @extends EventTarget
3565
+ @uses RuntimeClient
3566
+ @param {Object|String} options If options has typeof string, argument is considered as options.drop_zone
3567
+ @param {String|DOMElement} options.drop_zone DOM Element to turn into a drop zone
3568
+ @param {Array} [options.accept] Array of mime types to accept. By default accepts all
3569
+ @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support
3570
+ */
3571
+ var dispatches = [
3572
+ /**
3573
+ Dispatched when runtime is connected and drop zone is ready to accept files.
3574
+
3575
+ @event ready
3576
+ @param {Object} event
3577
+ */
3578
+ 'ready',
3579
+
3580
+ /**
3581
+ Dispatched when dragging cursor enters the drop zone.
3582
+
3583
+ @event dragenter
3584
+ @param {Object} event
3585
+ */
3586
+ 'dragenter',
3587
+
3588
+ /**
3589
+ Dispatched when dragging cursor leaves the drop zone.
3590
+
3591
+ @event dragleave
3592
+ @param {Object} event
3593
+ */
3594
+ 'dragleave',
3595
+
3596
+ /**
3597
+ Dispatched when file is dropped onto the drop zone.
3598
+
3599
+ @event drop
3600
+ @param {Object} event
3601
+ */
3602
+ 'drop',
3603
+
3604
+ /**
3605
+ Dispatched if error occurs.
3606
+
3607
+ @event error
3608
+ @param {Object} event
3609
+ */
3610
+ 'error'
3611
+ ];
3612
+
3613
+ function FileDrop(options) {
3614
+ var self = this, defaults;
3615
+
3616
+ // if flat argument passed it should be drop_zone id
3617
+ if (typeof(options) === 'string') {
3618
+ options = { drop_zone : options };
3619
+ }
3620
+
3621
+ // figure out the options
3622
+ defaults = {
3623
+ accept: [{
3624
+ title: I18n.translate('All Files'),
3625
+ extensions: '*'
3626
+ }],
3627
+ required_caps: {
3628
+ drag_and_drop: true
3629
+ }
3630
+ };
3631
+
3632
+ options = typeof(options) === 'object' ? Basic.extend({}, defaults, options) : defaults;
3633
+
3634
+ // this will help us to find proper default container
3635
+ options.container = Dom.get(options.drop_zone) || document.body;
3636
+
3637
+ // make container relative, if it is not
3638
+ if (Dom.getStyle(options.container, 'position') === 'static') {
3639
+ options.container.style.position = 'relative';
3640
+ }
3641
+
3642
+ // normalize accept option (could be list of mime types or array of title/extensions pairs)
3643
+ if (typeof(options.accept) === 'string') {
3644
+ options.accept = Mime.mimes2extList(options.accept);
3645
+ }
3646
+
3647
+ RuntimeClient.call(self);
3648
+
3649
+ Basic.extend(self, {
3650
+ uid: Basic.guid('uid_'),
3651
+
3652
+ ruid: null,
3653
+
3654
+ files: null,
3655
+
3656
+ init: function() {
3657
+
3658
+ self.convertEventPropsToHandlers(dispatches);
3659
+
3660
+ self.bind('RuntimeInit', function(e, runtime) {
3661
+ self.ruid = runtime.uid;
3662
+
3663
+ self.bind("Drop", function() {
3664
+ var files = runtime.exec.call(self, 'FileDrop', 'getFiles');
3665
+
3666
+ self.files = [];
3667
+
3668
+ Basic.each(files, function(file) {
3669
+ self.files.push(new File(self.ruid, file));
3670
+ });
3671
+ }, 999);
3672
+
3673
+ runtime.exec.call(self, 'FileDrop', 'init', options);
3674
+
3675
+ self.dispatchEvent('ready');
3676
+ });
3677
+
3678
+ // runtime needs: options.required_features, options.runtime_order and options.container
3679
+ self.connectRuntime(options); // throws RuntimeError
3680
+ },
3681
+
3682
+ destroy: function() {
3683
+ var runtime = this.getRuntime();
3684
+ if (runtime) {
3685
+ runtime.exec.call(this, 'FileDrop', 'destroy');
3686
+ this.disconnectRuntime();
3687
+ }
3688
+ this.files = null;
3689
+ }
3690
+ });
3691
+ }
3692
+
3693
+ FileDrop.prototype = EventTarget.instance;
3694
+
3695
+ return FileDrop;
3696
+ });
3697
+
3698
+ // Included from: src/javascript/runtime/RuntimeTarget.js
3699
+
3700
+ /**
3701
+ * RuntimeTarget.js
3702
+ *
3703
+ * Copyright 2013, Moxiecode Systems AB
3704
+ * Released under GPL License.
3705
+ *
3706
+ * License: http://www.plupload.com/license
3707
+ * Contributing: http://www.plupload.com/contributing
3708
+ */
3709
+
3710
+ define('moxie/runtime/RuntimeTarget', [
3711
+ 'moxie/core/utils/Basic',
3712
+ 'moxie/runtime/RuntimeClient',
3713
+ "moxie/core/EventTarget"
3714
+ ], function(Basic, RuntimeClient, EventTarget) {
3715
+ /**
3716
+ Instance of this class can be used as a target for the events dispatched by shims,
3717
+ when allowing them onto components is for either reason inappropriate
3718
+
3719
+ @class RuntimeTarget
3720
+ @constructor
3721
+ @protected
3722
+ @extends EventTarget
3723
+ */
3724
+ function RuntimeTarget() {
3725
+ this.uid = Basic.guid('uid_');
3726
+
3727
+ RuntimeClient.call(this);
3728
+
3729
+ this.destroy = function() {
3730
+ this.disconnectRuntime();
3731
+ this.unbindAll();
3732
+ };
3733
+ }
3734
+
3735
+ RuntimeTarget.prototype = EventTarget.instance;
3736
+
3737
+ return RuntimeTarget;
3738
+ });
3739
+
3740
+ // Included from: src/javascript/file/FileReader.js
3741
+
3742
+ /**
3743
+ * FileReader.js
3744
+ *
3745
+ * Copyright 2013, Moxiecode Systems AB
3746
+ * Released under GPL License.
3747
+ *
3748
+ * License: http://www.plupload.com/license
3749
+ * Contributing: http://www.plupload.com/contributing
3750
+ */
3751
+
3752
+ define('moxie/file/FileReader', [
3753
+ 'moxie/core/utils/Basic',
3754
+ 'moxie/core/utils/Encode',
3755
+ 'moxie/core/Exceptions',
3756
+ 'moxie/core/EventTarget',
3757
+ 'moxie/file/Blob',
3758
+ 'moxie/file/File',
3759
+ 'moxie/runtime/RuntimeTarget'
3760
+ ], function(Basic, Encode, x, EventTarget, Blob, File, RuntimeTarget) {
3761
+ /**
3762
+ Utility for preloading o.Blob/o.File objects in memory. By design closely follows [W3C FileReader](http://www.w3.org/TR/FileAPI/#dfn-filereader)
3763
+ interface. Where possible uses native FileReader, where - not falls back to shims.
3764
+
3765
+ @class FileReader
3766
+ @constructor FileReader
3767
+ @extends EventTarget
3768
+ @uses RuntimeClient
3769
+ */
3770
+ var dispatches = [
3771
+
3772
+ /**
3773
+ Dispatched when the read starts.
3774
+
3775
+ @event loadstart
3776
+ @param {Object} event
3777
+ */
3778
+ 'loadstart',
3779
+
3780
+ /**
3781
+ Dispatched while reading (and decoding) blob, and reporting partial Blob data (progess.loaded/progress.total).
3782
+
3783
+ @event progress
3784
+ @param {Object} event
3785
+ */
3786
+ 'progress',
3787
+
3788
+ /**
3789
+ Dispatched when the read has successfully completed.
3790
+
3791
+ @event load
3792
+ @param {Object} event
3793
+ */
3794
+ 'load',
3795
+
3796
+ /**
3797
+ Dispatched when the read has been aborted. For instance, by invoking the abort() method.
3798
+
3799
+ @event abort
3800
+ @param {Object} event
3801
+ */
3802
+ 'abort',
3803
+
3804
+ /**
3805
+ Dispatched when the read has failed.
3806
+
3807
+ @event error
3808
+ @param {Object} event
3809
+ */
3810
+ 'error',
3811
+
3812
+ /**
3813
+ Dispatched when the request has completed (either in success or failure).
3814
+
3815
+ @event loadend
3816
+ @param {Object} event
3817
+ */
3818
+ 'loadend'
3819
+ ];
3820
+
3821
+ function FileReader() {
3822
+ var self = this, _fr;
3823
+
3824
+ Basic.extend(this, {
3825
+ /**
3826
+ UID of the component instance.
3827
+
3828
+ @property uid
3829
+ @type {String}
3830
+ */
3831
+ uid: Basic.guid('uid_'),
3832
+
3833
+ /**
3834
+ Contains current state of FileReader object. Can take values of FileReader.EMPTY, FileReader.LOADING
3835
+ and FileReader.DONE.
3836
+
3837
+ @property readyState
3838
+ @type {Number}
3839
+ @default FileReader.EMPTY
3840
+ */
3841
+ readyState: FileReader.EMPTY,
3842
+
3843
+ /**
3844
+ Result of the successful read operation.
3845
+
3846
+ @property result
3847
+ @type {String}
3848
+ */
3849
+ result: null,
3850
+
3851
+ /**
3852
+ Stores the error of failed asynchronous read operation.
3853
+
3854
+ @property error
3855
+ @type {DOMError}
3856
+ */
3857
+ error: null,
3858
+
3859
+ /**
3860
+ Initiates reading of File/Blob object contents to binary string.
3861
+
3862
+ @method readAsBinaryString
3863
+ @param {Blob|File} blob Object to preload
3864
+ */
3865
+ readAsBinaryString: function(blob) {
3866
+ _read.call(this, 'readAsBinaryString', blob);
3867
+ },
3868
+
3869
+ /**
3870
+ Initiates reading of File/Blob object contents to dataURL string.
3871
+
3872
+ @method readAsDataURL
3873
+ @param {Blob|File} blob Object to preload
3874
+ */
3875
+ readAsDataURL: function(blob) {
3876
+ _read.call(this, 'readAsDataURL', blob);
3877
+ },
3878
+
3879
+ /**
3880
+ Initiates reading of File/Blob object contents to string.
3881
+
3882
+ @method readAsText
3883
+ @param {Blob|File} blob Object to preload
3884
+ */
3885
+ readAsText: function(blob) {
3886
+ _read.call(this, 'readAsText', blob);
3887
+ },
3888
+
3889
+ /**
3890
+ Aborts preloading process.
3891
+
3892
+ @method abort
3893
+ */
3894
+ abort: function() {
3895
+ this.result = null;
3896
+
3897
+ if (Basic.inArray(this.readyState, [FileReader.EMPTY, FileReader.DONE]) !== -1) {
3898
+ return;
3899
+ } else if (this.readyState === FileReader.LOADING) {
3900
+ this.readyState = FileReader.DONE;
3901
+ }
3902
+
3903
+ if (_fr) {
3904
+ _fr.getRuntime().exec.call(this, 'FileReader', 'abort');
3905
+ }
3906
+
3907
+ this.trigger('abort');
3908
+ this.trigger('loadend');
3909
+ },
3910
+
3911
+ /**
3912
+ Destroy component and release resources.
3913
+
3914
+ @method destroy
3915
+ */
3916
+ destroy: function() {
3917
+ this.abort();
3918
+
3919
+ if (_fr) {
3920
+ _fr.getRuntime().exec.call(this, 'FileReader', 'destroy');
3921
+ _fr.disconnectRuntime();
3922
+ }
3923
+
3924
+ self = _fr = null;
3925
+ }
3926
+ });
3927
+
3928
+
3929
+ function _read(op, blob) {
3930
+ _fr = new RuntimeTarget();
3931
+
3932
+ function error(err) {
3933
+ self.readyState = FileReader.DONE;
3934
+ self.error = err;
3935
+ self.trigger('error');
3936
+ loadEnd();
3937
+ }
3938
+
3939
+ function loadEnd() {
3940
+ _fr.destroy();
3941
+ _fr = null;
3942
+ self.trigger('loadend');
3943
+ }
3944
+
3945
+ function exec(runtime) {
3946
+ _fr.bind('Error', function(e, err) {
3947
+ error(err);
3948
+ });
3949
+
3950
+ _fr.bind('Progress', function(e) {
3951
+ self.result = runtime.exec.call(_fr, 'FileReader', 'getResult');
3952
+ self.trigger(e);
3953
+ });
3954
+
3955
+ _fr.bind('Load', function(e) {
3956
+ self.readyState = FileReader.DONE;
3957
+ self.result = runtime.exec.call(_fr, 'FileReader', 'getResult');
3958
+ self.trigger(e);
3959
+ loadEnd();
3960
+ });
3961
+
3962
+ runtime.exec.call(_fr, 'FileReader', 'read', op, blob);
3963
+ }
3964
+
3965
+ this.convertEventPropsToHandlers(dispatches);
3966
+
3967
+ if (this.readyState === FileReader.LOADING) {
3968
+ return error(new x.DOMException(x.DOMException.INVALID_STATE_ERR));
3969
+ }
3970
+
3971
+ this.readyState = FileReader.LOADING;
3972
+ this.trigger('loadstart');
3973
+
3974
+ // if source is o.Blob/o.File
3975
+ if (blob instanceof Blob) {
3976
+ if (blob.isDetached()) {
3977
+ var src = blob.getSource();
3978
+ switch (op) {
3979
+ case 'readAsText':
3980
+ case 'readAsBinaryString':
3981
+ this.result = src;
3982
+ break;
3983
+ case 'readAsDataURL':
3984
+ this.result = 'data:' + blob.type + ';base64,' + Encode.btoa(src);
3985
+ break;
3986
+ }
3987
+ this.readyState = FileReader.DONE;
3988
+ this.trigger('load');
3989
+ loadEnd();
3990
+ } else {
3991
+ exec(_fr.connectRuntime(blob.ruid));
3992
+ }
3993
+ } else {
3994
+ error(new x.DOMException(x.DOMException.NOT_FOUND_ERR));
3995
+ }
3996
+ }
3997
+ }
3998
+
3999
+ /**
4000
+ Initial FileReader state
4001
+
4002
+ @property EMPTY
4003
+ @type {Number}
4004
+ @final
4005
+ @static
4006
+ @default 0
4007
+ */
4008
+ FileReader.EMPTY = 0;
4009
+
4010
+ /**
4011
+ FileReader switches to this state when it is preloading the source
4012
+
4013
+ @property LOADING
4014
+ @type {Number}
4015
+ @final
4016
+ @static
4017
+ @default 1
4018
+ */
4019
+ FileReader.LOADING = 1;
4020
+
4021
+ /**
4022
+ Preloading is complete, this is a final state
4023
+
4024
+ @property DONE
4025
+ @type {Number}
4026
+ @final
4027
+ @static
4028
+ @default 2
4029
+ */
4030
+ FileReader.DONE = 2;
4031
+
4032
+ FileReader.prototype = EventTarget.instance;
4033
+
4034
+ return FileReader;
4035
+ });
4036
+
4037
+ // Included from: src/javascript/core/utils/Url.js
4038
+
4039
+ /**
4040
+ * Url.js
4041
+ *
4042
+ * Copyright 2013, Moxiecode Systems AB
4043
+ * Released under GPL License.
4044
+ *
4045
+ * License: http://www.plupload.com/license
4046
+ * Contributing: http://www.plupload.com/contributing
4047
+ */
4048
+
4049
+ define('moxie/core/utils/Url', [], function() {
4050
+ /**
4051
+ Parse url into separate components and fill in absent parts with parts from current url,
4052
+ based on https://raw.github.com/kvz/phpjs/master/functions/url/parse_url.js
4053
+
4054
+ @method parseUrl
4055
+ @for Utils
4056
+ @static
4057
+ @param {String} url Url to parse (defaults to empty string if undefined)
4058
+ @return {Object} Hash containing extracted uri components
4059
+ */
4060
+ var parseUrl = function(url, currentUrl) {
4061
+ var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment']
4062
+ , i = key.length
4063
+ , ports = {
4064
+ http: 80,
4065
+ https: 443
4066
+ }
4067
+ , uri = {}
4068
+ , regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/
4069
+ , m = regex.exec(url || '')
4070
+ ;
4071
+
4072
+ while (i--) {
4073
+ if (m[i]) {
4074
+ uri[key[i]] = m[i];
4075
+ }
4076
+ }
4077
+
4078
+ // when url is relative, we set the origin and the path ourselves
4079
+ if (!uri.scheme) {
4080
+ // come up with defaults
4081
+ if (!currentUrl || typeof(currentUrl) === 'string') {
4082
+ currentUrl = parseUrl(currentUrl || document.location.href);
4083
+ }
4084
+
4085
+ uri.scheme = currentUrl.scheme;
4086
+ uri.host = currentUrl.host;
4087
+ uri.port = currentUrl.port;
4088
+
4089
+ var path = '';
4090
+ // for urls without trailing slash we need to figure out the path
4091
+ if (/^[^\/]/.test(uri.path)) {
4092
+ path = currentUrl.path;
4093
+ // if path ends with a filename, strip it
4094
+ if (!/(\/|\/[^\.]+)$/.test(path)) {
4095
+ path = path.replace(/\/[^\/]+$/, '/');
4096
+ } else {
4097
+ path += '/';
4098
+ }
4099
+ }
4100
+ uri.path = path + (uri.path || ''); // site may reside at domain.com or domain.com/subdir
4101
+ }
4102
+
4103
+ if (!uri.port) {
4104
+ uri.port = ports[uri.scheme] || 80;
4105
+ }
4106
+
4107
+ uri.port = parseInt(uri.port, 10);
4108
+
4109
+ if (!uri.path) {
4110
+ uri.path = "/";
4111
+ }
4112
+
4113
+ delete uri.source;
4114
+
4115
+ return uri;
4116
+ };
4117
+
4118
+ /**
4119
+ Resolve url - among other things will turn relative url to absolute
4120
+
4121
+ @method resolveUrl
4122
+ @static
4123
+ @param {String} url Either absolute or relative
4124
+ @return {String} Resolved, absolute url
4125
+ */
4126
+ var resolveUrl = function(url) {
4127
+ var ports = { // we ignore default ports
4128
+ http: 80,
4129
+ https: 443
4130
+ }
4131
+ , urlp = parseUrl(url)
4132
+ ;
4133
+
4134
+ return urlp.scheme + '://' + urlp.host + (urlp.port !== ports[urlp.scheme] ? ':' + urlp.port : '') + urlp.path + (urlp.query ? urlp.query : '');
4135
+ };
4136
+
4137
+ /**
4138
+ Check if specified url has the same origin as the current document
4139
+
4140
+ @method hasSameOrigin
4141
+ @param {String|Object} url
4142
+ @return {Boolean}
4143
+ */
4144
+ var hasSameOrigin = function(url) {
4145
+ function origin(url) {
4146
+ return [url.scheme, url.host, url.port].join('/');
4147
+ }
4148
+
4149
+ if (typeof url === 'string') {
4150
+ url = parseUrl(url);
4151
+ }
4152
+
4153
+ return origin(parseUrl()) === origin(url);
4154
+ };
4155
+
4156
+ return {
4157
+ parseUrl: parseUrl,
4158
+ resolveUrl: resolveUrl,
4159
+ hasSameOrigin: hasSameOrigin
4160
+ };
4161
+ });
4162
+
4163
+ // Included from: src/javascript/file/FileReaderSync.js
4164
+
4165
+ /**
4166
+ * FileReaderSync.js
4167
+ *
4168
+ * Copyright 2013, Moxiecode Systems AB
4169
+ * Released under GPL License.
4170
+ *
4171
+ * License: http://www.plupload.com/license
4172
+ * Contributing: http://www.plupload.com/contributing
4173
+ */
4174
+
4175
+ define('moxie/file/FileReaderSync', [
4176
+ 'moxie/core/utils/Basic',
4177
+ 'moxie/runtime/RuntimeClient',
4178
+ 'moxie/core/utils/Encode'
4179
+ ], function(Basic, RuntimeClient, Encode) {
4180
+ /**
4181
+ Synchronous FileReader implementation. Something like this is available in WebWorkers environment, here
4182
+ it can be used to read only preloaded blobs/files and only below certain size (not yet sure what that'd be,
4183
+ but probably < 1mb). Not meant to be used directly by user.
4184
+
4185
+ @class FileReaderSync
4186
+ @private
4187
+ @constructor
4188
+ */
4189
+ return function() {
4190
+ RuntimeClient.call(this);
4191
+
4192
+ Basic.extend(this, {
4193
+ uid: Basic.guid('uid_'),
4194
+
4195
+ readAsBinaryString: function(blob) {
4196
+ return _read.call(this, 'readAsBinaryString', blob);
4197
+ },
4198
+
4199
+ readAsDataURL: function(blob) {
4200
+ return _read.call(this, 'readAsDataURL', blob);
4201
+ },
4202
+
4203
+ /*readAsArrayBuffer: function(blob) {
4204
+ return _read.call(this, 'readAsArrayBuffer', blob);
4205
+ },*/
4206
+
4207
+ readAsText: function(blob) {
4208
+ return _read.call(this, 'readAsText', blob);
4209
+ }
4210
+ });
4211
+
4212
+ function _read(op, blob) {
4213
+ if (blob.isDetached()) {
4214
+ var src = blob.getSource();
4215
+ switch (op) {
4216
+ case 'readAsBinaryString':
4217
+ return src;
4218
+ case 'readAsDataURL':
4219
+ return 'data:' + blob.type + ';base64,' + Encode.btoa(src);
4220
+ case 'readAsText':
4221
+ var txt = '';
4222
+ for (var i = 0, length = src.length; i < length; i++) {
4223
+ txt += String.fromCharCode(src[i]);
4224
+ }
4225
+ return txt;
4226
+ }
4227
+ } else {
4228
+ var result = this.connectRuntime(blob.ruid).exec.call(this, 'FileReaderSync', 'read', op, blob);
4229
+ this.disconnectRuntime();
4230
+ return result;
4231
+ }
4232
+ }
4233
+ };
4234
+ });
4235
+
4236
+ // Included from: src/javascript/xhr/FormData.js
4237
+
4238
+ /**
4239
+ * FormData.js
4240
+ *
4241
+ * Copyright 2013, Moxiecode Systems AB
4242
+ * Released under GPL License.
4243
+ *
4244
+ * License: http://www.plupload.com/license
4245
+ * Contributing: http://www.plupload.com/contributing
4246
+ */
4247
+
4248
+ define("moxie/xhr/FormData", [
4249
+ "moxie/core/Exceptions",
4250
+ "moxie/core/utils/Basic",
4251
+ "moxie/file/Blob"
4252
+ ], function(x, Basic, Blob) {
4253
+ /**
4254
+ FormData
4255
+
4256
+ @class FormData
4257
+ @constructor
4258
+ */
4259
+ function FormData() {
4260
+ var _blob, _fields = [];
4261
+
4262
+ Basic.extend(this, {
4263
+ /**
4264
+ Append another key-value pair to the FormData object
4265
+
4266
+ @method append
4267
+ @param {String} name Name for the new field
4268
+ @param {String|Blob|Array|Object} value Value for the field
4269
+ */
4270
+ append: function(name, value) {
4271
+ var self = this, valueType = Basic.typeOf(value);
4272
+
4273
+ // according to specs value might be either Blob or String
4274
+ if (value instanceof Blob) {
4275
+ _blob = {
4276
+ name: name,
4277
+ value: value // unfortunately we can only send single Blob in one FormData
4278
+ };
4279
+ } else if ('array' === valueType) {
4280
+ name += '[]';
4281
+
4282
+ Basic.each(value, function(value) {
4283
+ self.append(name, value);
4284
+ });
4285
+ } else if ('object' === valueType) {
4286
+ Basic.each(value, function(value, key) {
4287
+ self.append(name + '[' + key + ']', value);
4288
+ });
4289
+ } else if ('null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN(value)) {
4290
+ self.append(name, "false");
4291
+ } else {
4292
+ _fields.push({
4293
+ name: name,
4294
+ value: value.toString()
4295
+ });
4296
+ }
4297
+ },
4298
+
4299
+ /**
4300
+ Checks if FormData contains Blob.
4301
+
4302
+ @method hasBlob
4303
+ @return {Boolean}
4304
+ */
4305
+ hasBlob: function() {
4306
+ return !!this.getBlob();
4307
+ },
4308
+
4309
+ /**
4310
+ Retrieves blob.
4311
+
4312
+ @method getBlob
4313
+ @return {Object} Either Blob if found or null
4314
+ */
4315
+ getBlob: function() {
4316
+ return _blob && _blob.value || null;
4317
+ },
4318
+
4319
+ /**
4320
+ Retrieves blob field name.
4321
+
4322
+ @method getBlobName
4323
+ @return {String} Either Blob field name or null
4324
+ */
4325
+ getBlobName: function() {
4326
+ return _blob && _blob.name || null;
4327
+ },
4328
+
4329
+ /**
4330
+ Loop over the fields in FormData and invoke the callback for each of them.
4331
+
4332
+ @method each
4333
+ @param {Function} cb Callback to call for each field
4334
+ */
4335
+ each: function(cb) {
4336
+ Basic.each(_fields, function(field) {
4337
+ cb(field.value, field.name);
4338
+ });
4339
+
4340
+ if (_blob) {
4341
+ cb(_blob.value, _blob.name);
4342
+ }
4343
+ },
4344
+
4345
+ destroy: function() {
4346
+ _blob = null;
4347
+ _fields = [];
4348
+ }
4349
+ });
4350
+ }
4351
+
4352
+ return FormData;
4353
+ });
4354
+
4355
+ // Included from: src/javascript/xhr/XMLHttpRequest.js
4356
+
4357
+ /**
4358
+ * XMLHttpRequest.js
4359
+ *
4360
+ * Copyright 2013, Moxiecode Systems AB
4361
+ * Released under GPL License.
4362
+ *
4363
+ * License: http://www.plupload.com/license
4364
+ * Contributing: http://www.plupload.com/contributing
4365
+ */
4366
+
4367
+ define("moxie/xhr/XMLHttpRequest", [
4368
+ "moxie/core/utils/Basic",
4369
+ "moxie/core/Exceptions",
4370
+ "moxie/core/EventTarget",
4371
+ "moxie/core/utils/Encode",
4372
+ "moxie/core/utils/Url",
4373
+ "moxie/runtime/Runtime",
4374
+ "moxie/runtime/RuntimeTarget",
4375
+ "moxie/file/Blob",
4376
+ "moxie/file/FileReaderSync",
4377
+ "moxie/xhr/FormData",
4378
+ "moxie/core/utils/Env",
4379
+ "moxie/core/utils/Mime"
4380
+ ], function(Basic, x, EventTarget, Encode, Url, Runtime, RuntimeTarget, Blob, FileReaderSync, FormData, Env, Mime) {
4381
+
4382
+ var httpCode = {
4383
+ 100: 'Continue',
4384
+ 101: 'Switching Protocols',
4385
+ 102: 'Processing',
4386
+
4387
+ 200: 'OK',
4388
+ 201: 'Created',
4389
+ 202: 'Accepted',
4390
+ 203: 'Non-Authoritative Information',
4391
+ 204: 'No Content',
4392
+ 205: 'Reset Content',
4393
+ 206: 'Partial Content',
4394
+ 207: 'Multi-Status',
4395
+ 226: 'IM Used',
4396
+
4397
+ 300: 'Multiple Choices',
4398
+ 301: 'Moved Permanently',
4399
+ 302: 'Found',
4400
+ 303: 'See Other',
4401
+ 304: 'Not Modified',
4402
+ 305: 'Use Proxy',
4403
+ 306: 'Reserved',
4404
+ 307: 'Temporary Redirect',
4405
+
4406
+ 400: 'Bad Request',
4407
+ 401: 'Unauthorized',
4408
+ 402: 'Payment Required',
4409
+ 403: 'Forbidden',
4410
+ 404: 'Not Found',
4411
+ 405: 'Method Not Allowed',
4412
+ 406: 'Not Acceptable',
4413
+ 407: 'Proxy Authentication Required',
4414
+ 408: 'Request Timeout',
4415
+ 409: 'Conflict',
4416
+ 410: 'Gone',
4417
+ 411: 'Length Required',
4418
+ 412: 'Precondition Failed',
4419
+ 413: 'Request Entity Too Large',
4420
+ 414: 'Request-URI Too Long',
4421
+ 415: 'Unsupported Media Type',
4422
+ 416: 'Requested Range Not Satisfiable',
4423
+ 417: 'Expectation Failed',
4424
+ 422: 'Unprocessable Entity',
4425
+ 423: 'Locked',
4426
+ 424: 'Failed Dependency',
4427
+ 426: 'Upgrade Required',
4428
+
4429
+ 500: 'Internal Server Error',
4430
+ 501: 'Not Implemented',
4431
+ 502: 'Bad Gateway',
4432
+ 503: 'Service Unavailable',
4433
+ 504: 'Gateway Timeout',
4434
+ 505: 'HTTP Version Not Supported',
4435
+ 506: 'Variant Also Negotiates',
4436
+ 507: 'Insufficient Storage',
4437
+ 510: 'Not Extended'
4438
+ };
4439
+
4440
+ function XMLHttpRequestUpload() {
4441
+ this.uid = Basic.guid('uid_');
4442
+ }
4443
+
4444
+ XMLHttpRequestUpload.prototype = EventTarget.instance;
4445
+
4446
+ /**
4447
+ Implementation of XMLHttpRequest
4448
+
4449
+ @class XMLHttpRequest
4450
+ @constructor
4451
+ @uses RuntimeClient
4452
+ @extends EventTarget
4453
+ */
4454
+ var dispatches = ['loadstart', 'progress', 'abort', 'error', 'load', 'timeout', 'loadend']; // & readystatechange (for historical reasons)
4455
+
4456
+ var NATIVE = 1, RUNTIME = 2;
4457
+
4458
+ function XMLHttpRequest() {
4459
+ var self = this,
4460
+ // this (together with _p() @see below) is here to gracefully upgrade to setter/getter syntax where possible
4461
+ props = {
4462
+ /**
4463
+ The amount of milliseconds a request can take before being terminated. Initially zero. Zero means there is no timeout.
4464
+
4465
+ @property timeout
4466
+ @type Number
4467
+ @default 0
4468
+ */
4469
+ timeout: 0,
4470
+
4471
+ /**
4472
+ Current state, can take following values:
4473
+ UNSENT (numeric value 0)
4474
+ The object has been constructed.
4475
+
4476
+ OPENED (numeric value 1)
4477
+ The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method.
4478
+
4479
+ HEADERS_RECEIVED (numeric value 2)
4480
+ All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available.
4481
+
4482
+ LOADING (numeric value 3)
4483
+ The response entity body is being received.
4484
+
4485
+ DONE (numeric value 4)
4486
+
4487
+ @property readyState
4488
+ @type Number
4489
+ @default 0 (UNSENT)
4490
+ */
4491
+ readyState: XMLHttpRequest.UNSENT,
4492
+
4493
+ /**
4494
+ True when user credentials are to be included in a cross-origin request. False when they are to be excluded
4495
+ in a cross-origin request and when cookies are to be ignored in its response. Initially false.
4496
+
4497
+ @property withCredentials
4498
+ @type Boolean
4499
+ @default false
4500
+ */
4501
+ withCredentials: false,
4502
+
4503
+ /**
4504
+ Returns the HTTP status code.
4505
+
4506
+ @property status
4507
+ @type Number
4508
+ @default 0
4509
+ */
4510
+ status: 0,
4511
+
4512
+ /**
4513
+ Returns the HTTP status text.
4514
+
4515
+ @property statusText
4516
+ @type String
4517
+ */
4518
+ statusText: "",
4519
+
4520
+ /**
4521
+ Returns the response type. Can be set to change the response type. Values are:
4522
+ the empty string (default), "arraybuffer", "blob", "document", "json", and "text".
4523
+
4524
+ @property responseType
4525
+ @type String
4526
+ */
4527
+ responseType: "",
4528
+
4529
+ /**
4530
+ Returns the document response entity body.
4531
+
4532
+ Throws an "InvalidStateError" exception if responseType is not the empty string or "document".
4533
+
4534
+ @property responseXML
4535
+ @type Document
4536
+ */
4537
+ responseXML: null,
4538
+
4539
+ /**
4540
+ Returns the text response entity body.
4541
+
4542
+ Throws an "InvalidStateError" exception if responseType is not the empty string or "text".
4543
+
4544
+ @property responseText
4545
+ @type String
4546
+ */
4547
+ responseText: null,
4548
+
4549
+ /**
4550
+ Returns the response entity body (http://www.w3.org/TR/XMLHttpRequest/#response-entity-body).
4551
+ Can become: ArrayBuffer, Blob, Document, JSON, Text
4552
+
4553
+ @property response
4554
+ @type Mixed
4555
+ */
4556
+ response: null
4557
+ },
4558
+
4559
+ _async = true,
4560
+ _url,
4561
+ _method,
4562
+ _headers = {},
4563
+ _user,
4564
+ _password,
4565
+ _encoding = null,
4566
+ _mimeType = null,
4567
+
4568
+ // flags
4569
+ _sync_flag = false,
4570
+ _send_flag = false,
4571
+ _upload_events_flag = false,
4572
+ _upload_complete_flag = false,
4573
+ _error_flag = false,
4574
+ _same_origin_flag = false,
4575
+
4576
+ // times
4577
+ _start_time,
4578
+ _timeoutset_time,
4579
+
4580
+ _finalMime = null,
4581
+ _finalCharset = null,
4582
+
4583
+ _options = {},
4584
+ _xhr,
4585
+ _responseHeaders = '',
4586
+ _responseHeadersBag
4587
+ ;
4588
+
4589
+
4590
+ Basic.extend(this, props, {
4591
+ /**
4592
+ Unique id of the component
4593
+
4594
+ @property uid
4595
+ @type String
4596
+ */
4597
+ uid: Basic.guid('uid_'),
4598
+
4599
+ /**
4600
+ Target for Upload events
4601
+
4602
+ @property upload
4603
+ @type XMLHttpRequestUpload
4604
+ */
4605
+ upload: new XMLHttpRequestUpload(),
4606
+
4607
+
4608
+ /**
4609
+ Sets the request method, request URL, synchronous flag, request username, and request password.
4610
+
4611
+ Throws a "SyntaxError" exception if one of the following is true:
4612
+
4613
+ method is not a valid HTTP method.
4614
+ url cannot be resolved.
4615
+ url contains the "user:password" format in the userinfo production.
4616
+ Throws a "SecurityError" exception if method is a case-insensitive match for CONNECT, TRACE or TRACK.
4617
+
4618
+ Throws an "InvalidAccessError" exception if one of the following is true:
4619
+
4620
+ Either user or password is passed as argument and the origin of url does not match the XMLHttpRequest origin.
4621
+ There is an associated XMLHttpRequest document and either the timeout attribute is not zero,
4622
+ the withCredentials attribute is true, or the responseType attribute is not the empty string.
4623
+
4624
+
4625
+ @method open
4626
+ @param {String} method HTTP method to use on request
4627
+ @param {String} url URL to request
4628
+ @param {Boolean} [async=true] If false request will be done in synchronous manner. Asynchronous by default.
4629
+ @param {String} [user] Username to use in HTTP authentication process on server-side
4630
+ @param {String} [password] Password to use in HTTP authentication process on server-side
4631
+ */
4632
+ open: function(method, url, async, user, password) {
4633
+ var urlp;
4634
+
4635
+ // first two arguments are required
4636
+ if (!method || !url) {
4637
+ throw new x.DOMException(x.DOMException.SYNTAX_ERR);
4638
+ }
4639
+
4640
+ // 2 - check if any code point in method is higher than U+00FF or after deflating method it does not match the method
4641
+ if (/[\u0100-\uffff]/.test(method) || Encode.utf8_encode(method) !== method) {
4642
+ throw new x.DOMException(x.DOMException.SYNTAX_ERR);
4643
+ }
4644
+
4645
+ // 3
4646
+ if (!!~Basic.inArray(method.toUpperCase(), ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'TRACE', 'TRACK'])) {
4647
+ _method = method.toUpperCase();
4648
+ }
4649
+
4650
+
4651
+ // 4 - allowing these methods poses a security risk
4652
+ if (!!~Basic.inArray(_method, ['CONNECT', 'TRACE', 'TRACK'])) {
4653
+ throw new x.DOMException(x.DOMException.SECURITY_ERR);
4654
+ }
4655
+
4656
+ // 5
4657
+ url = Encode.utf8_encode(url);
4658
+
4659
+ // 6 - Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError".
4660
+ urlp = Url.parseUrl(url);
4661
+
4662
+ _same_origin_flag = Url.hasSameOrigin(urlp);
4663
+
4664
+ // 7 - manually build up absolute url
4665
+ _url = Url.resolveUrl(url);
4666
+
4667
+ // 9-10, 12-13
4668
+ if ((user || password) && !_same_origin_flag) {
4669
+ throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
4670
+ }
4671
+
4672
+ _user = user || urlp.user;
4673
+ _password = password || urlp.pass;
4674
+
4675
+ // 11
4676
+ _async = async || true;
4677
+
4678
+ if (_async === false && (_p('timeout') || _p('withCredentials') || _p('responseType') !== "")) {
4679
+ throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
4680
+ }
4681
+
4682
+ // 14 - terminate abort()
4683
+
4684
+ // 15 - terminate send()
4685
+
4686
+ // 18
4687
+ _sync_flag = !_async;
4688
+ _send_flag = false;
4689
+ _headers = {};
4690
+ _reset.call(this);
4691
+
4692
+ // 19
4693
+ _p('readyState', XMLHttpRequest.OPENED);
4694
+
4695
+ // 20
4696
+ this.convertEventPropsToHandlers(['readystatechange']); // unify event handlers
4697
+ this.dispatchEvent('readystatechange');
4698
+ },
4699
+
4700
+ /**
4701
+ Appends an header to the list of author request headers, or if header is already
4702
+ in the list of author request headers, combines its value with value.
4703
+
4704
+ Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.
4705
+ Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value
4706
+ is not a valid HTTP header field value.
4707
+
4708
+ @method setRequestHeader
4709
+ @param {String} header
4710
+ @param {String|Number} value
4711
+ */
4712
+ setRequestHeader: function(header, value) {
4713
+ var uaHeaders = [ // these headers are controlled by the user agent
4714
+ "accept-charset",
4715
+ "accept-encoding",
4716
+ "access-control-request-headers",
4717
+ "access-control-request-method",
4718
+ "connection",
4719
+ "content-length",
4720
+ "cookie",
4721
+ "cookie2",
4722
+ "content-transfer-encoding",
4723
+ "date",
4724
+ "expect",
4725
+ "host",
4726
+ "keep-alive",
4727
+ "origin",
4728
+ "referer",
4729
+ "te",
4730
+ "trailer",
4731
+ "transfer-encoding",
4732
+ "upgrade",
4733
+ "user-agent",
4734
+ "via"
4735
+ ];
4736
+
4737
+ // 1-2
4738
+ if (_p('readyState') !== XMLHttpRequest.OPENED || _send_flag) {
4739
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
4740
+ }
4741
+
4742
+ // 3
4743
+ if (/[\u0100-\uffff]/.test(header) || Encode.utf8_encode(header) !== header) {
4744
+ throw new x.DOMException(x.DOMException.SYNTAX_ERR);
4745
+ }
4746
+
4747
+ // 4
4748
+ /* this step is seemingly bypassed in browsers, probably to allow various unicode characters in header values
4749
+ if (/[\u0100-\uffff]/.test(value) || Encode.utf8_encode(value) !== value) {
4750
+ throw new x.DOMException(x.DOMException.SYNTAX_ERR);
4751
+ }*/
4752
+
4753
+ header = Basic.trim(header).toLowerCase();
4754
+
4755
+ // setting of proxy-* and sec-* headers is prohibited by spec
4756
+ if (!!~Basic.inArray(header, uaHeaders) || /^(proxy\-|sec\-)/.test(header)) {
4757
+ return false;
4758
+ }
4759
+
4760
+ // camelize
4761
+ // browsers lowercase header names (at least for custom ones)
4762
+ // header = header.replace(/\b\w/g, function($1) { return $1.toUpperCase(); });
4763
+
4764
+ if (!_headers[header]) {
4765
+ _headers[header] = value;
4766
+ } else {
4767
+ // http://tools.ietf.org/html/rfc2616#section-4.2 (last paragraph)
4768
+ _headers[header] += ', ' + value;
4769
+ }
4770
+ return true;
4771
+ },
4772
+
4773
+ /**
4774
+ Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2.
4775
+
4776
+ @method getAllResponseHeaders
4777
+ @return {String} reponse headers or empty string
4778
+ */
4779
+ getAllResponseHeaders: function() {
4780
+ return _responseHeaders || '';
4781
+ },
4782
+
4783
+ /**
4784
+ Returns the header field value from the response of which the field name matches header,
4785
+ unless the field name is Set-Cookie or Set-Cookie2.
4786
+
4787
+ @method getResponseHeader
4788
+ @param {String} header
4789
+ @return {String} value(s) for the specified header or null
4790
+ */
4791
+ getResponseHeader: function(header) {
4792
+ header = header.toLowerCase();
4793
+
4794
+ if (_error_flag || !!~Basic.inArray(header, ['set-cookie', 'set-cookie2'])) {
4795
+ return null;
4796
+ }
4797
+
4798
+ if (_responseHeaders && _responseHeaders !== '') {
4799
+ // if we didn't parse response headers until now, do it and keep for later
4800
+ if (!_responseHeadersBag) {
4801
+ _responseHeadersBag = {};
4802
+ Basic.each(_responseHeaders.split(/\r\n/), function(line) {
4803
+ var pair = line.split(/:\s+/);
4804
+ if (pair.length === 2) { // last line might be empty, omit
4805
+ pair[0] = Basic.trim(pair[0]); // just in case
4806
+ _responseHeadersBag[pair[0].toLowerCase()] = { // simply to retain header name in original form
4807
+ header: pair[0],
4808
+ value: Basic.trim(pair[1])
4809
+ };
4810
+ }
4811
+ });
4812
+ }
4813
+ if (_responseHeadersBag.hasOwnProperty(header)) {
4814
+ return _responseHeadersBag[header].header + ': ' + _responseHeadersBag[header].value;
4815
+ }
4816
+ }
4817
+ return null;
4818
+ },
4819
+
4820
+ /**
4821
+ Sets the Content-Type header for the response to mime.
4822
+ Throws an "InvalidStateError" exception if the state is LOADING or DONE.
4823
+ Throws a "SyntaxError" exception if mime is not a valid media type.
4824
+
4825
+ @method overrideMimeType
4826
+ @param String mime Mime type to set
4827
+ */
4828
+ overrideMimeType: function(mime) {
4829
+ var matches, charset;
4830
+
4831
+ // 1
4832
+ if (!!~Basic.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) {
4833
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
4834
+ }
4835
+
4836
+ // 2
4837
+ mime = Basic.trim(mime.toLowerCase());
4838
+
4839
+ if (/;/.test(mime) && (matches = mime.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))) {
4840
+ mime = matches[1];
4841
+ if (matches[2]) {
4842
+ charset = matches[2];
4843
+ }
4844
+ }
4845
+
4846
+ if (!Mime.mimes[mime]) {
4847
+ throw new x.DOMException(x.DOMException.SYNTAX_ERR);
4848
+ }
4849
+
4850
+ // 3-4
4851
+ _finalMime = mime;
4852
+ _finalCharset = charset;
4853
+ },
4854
+
4855
+ /**
4856
+ Initiates the request. The optional argument provides the request entity body.
4857
+ The argument is ignored if request method is GET or HEAD.
4858
+
4859
+ Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.
4860
+
4861
+ @method send
4862
+ @param {Blob|Document|String|FormData} [data] Request entity body
4863
+ @param {Object} [options] Set of requirements and pre-requisities for runtime initialization
4864
+ */
4865
+ send: function(data, options) {
4866
+ if (Basic.typeOf(options) === 'string') {
4867
+ _options = { ruid: options };
4868
+ } else if (!options) {
4869
+ _options = {};
4870
+ } else {
4871
+ _options = options;
4872
+ }
4873
+
4874
+ this.convertEventPropsToHandlers(dispatches);
4875
+ this.upload.convertEventPropsToHandlers(dispatches);
4876
+
4877
+ // 1-2
4878
+ if (this.readyState !== XMLHttpRequest.OPENED || _send_flag) {
4879
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
4880
+ }
4881
+
4882
+ // 3
4883
+ // sending Blob
4884
+ if (data instanceof Blob) {
4885
+ _options.ruid = data.ruid;
4886
+ _mimeType = data.type || 'application/octet-stream';
4887
+ }
4888
+
4889
+ // FormData
4890
+ else if (data instanceof FormData) {
4891
+ if (data.hasBlob()) {
4892
+ var blob = data.getBlob();
4893
+ _options.ruid = blob.ruid;
4894
+ _mimeType = blob.type || 'application/octet-stream';
4895
+ }
4896
+ }
4897
+
4898
+ // DOMString
4899
+ else if (typeof data === 'string') {
4900
+ _encoding = 'UTF-8';
4901
+ _mimeType = 'text/plain;charset=UTF-8';
4902
+
4903
+ // data should be converted to Unicode and encoded as UTF-8
4904
+ data = Encode.utf8_encode(data);
4905
+ }
4906
+
4907
+ // if withCredentials not set, but requested, set it automatically
4908
+ if (!this.withCredentials) {
4909
+ this.withCredentials = (_options.required_caps && _options.required_caps.send_browser_cookies) && !_same_origin_flag;
4910
+ }
4911
+
4912
+ // 4 - storage mutex
4913
+ // 5
4914
+ _upload_events_flag = (!_sync_flag && this.upload.hasEventListener()); // DSAP
4915
+ // 6
4916
+ _error_flag = false;
4917
+ // 7
4918
+ _upload_complete_flag = !data;
4919
+ // 8 - Asynchronous steps
4920
+ if (!_sync_flag) {
4921
+ // 8.1
4922
+ _send_flag = true;
4923
+ // 8.2
4924
+ // this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
4925
+ // 8.3
4926
+ //if (!_upload_complete_flag) {
4927
+ // this.upload.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr
4928
+ //}
4929
+ }
4930
+ // 8.5 - Return the send() method call, but continue running the steps in this algorithm.
4931
+ _doXHR.call(this, data);
4932
+ },
4933
+
4934
+ /**
4935
+ Cancels any network activity.
4936
+
4937
+ @method abort
4938
+ */
4939
+ abort: function() {
4940
+ _error_flag = true;
4941
+ _sync_flag = false;
4942
+
4943
+ if (!~Basic.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED, XMLHttpRequest.DONE])) {
4944
+ _p('readyState', XMLHttpRequest.DONE);
4945
+ _send_flag = false;
4946
+
4947
+ if (_xhr) {
4948
+ _xhr.getRuntime().exec.call(_xhr, 'XMLHttpRequest', 'abort', _upload_complete_flag);
4949
+ } else {
4950
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
4951
+ }
4952
+
4953
+ _upload_complete_flag = true;
4954
+ } else {
4955
+ _p('readyState', XMLHttpRequest.UNSENT);
4956
+ }
4957
+ },
4958
+
4959
+ destroy: function() {
4960
+ if (_xhr) {
4961
+ if (Basic.typeOf(_xhr.destroy) === 'function') {
4962
+ _xhr.destroy();
4963
+ }
4964
+ _xhr = null;
4965
+ }
4966
+
4967
+ this.unbindAll();
4968
+
4969
+ if (this.upload) {
4970
+ this.upload.unbindAll();
4971
+ this.upload = null;
4972
+ }
4973
+ }
4974
+ });
4975
+
4976
+ /* this is nice, but maybe too lengthy
4977
+
4978
+ // if supported by JS version, set getters/setters for specific properties
4979
+ o.defineProperty(this, 'readyState', {
4980
+ configurable: false,
4981
+
4982
+ get: function() {
4983
+ return _p('readyState');
4984
+ }
4985
+ });
4986
+
4987
+ o.defineProperty(this, 'timeout', {
4988
+ configurable: false,
4989
+
4990
+ get: function() {
4991
+ return _p('timeout');
4992
+ },
4993
+
4994
+ set: function(value) {
4995
+
4996
+ if (_sync_flag) {
4997
+ throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
4998
+ }
4999
+
5000
+ // timeout still should be measured relative to the start time of request
5001
+ _timeoutset_time = (new Date).getTime();
5002
+
5003
+ _p('timeout', value);
5004
+ }
5005
+ });
5006
+
5007
+ // the withCredentials attribute has no effect when fetching same-origin resources
5008
+ o.defineProperty(this, 'withCredentials', {
5009
+ configurable: false,
5010
+
5011
+ get: function() {
5012
+ return _p('withCredentials');
5013
+ },
5014
+
5015
+ set: function(value) {
5016
+ // 1-2
5017
+ if (!~o.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED]) || _send_flag) {
5018
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5019
+ }
5020
+
5021
+ // 3-4
5022
+ if (_anonymous_flag || _sync_flag) {
5023
+ throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
5024
+ }
5025
+
5026
+ // 5
5027
+ _p('withCredentials', value);
5028
+ }
5029
+ });
5030
+
5031
+ o.defineProperty(this, 'status', {
5032
+ configurable: false,
5033
+
5034
+ get: function() {
5035
+ return _p('status');
5036
+ }
5037
+ });
5038
+
5039
+ o.defineProperty(this, 'statusText', {
5040
+ configurable: false,
5041
+
5042
+ get: function() {
5043
+ return _p('statusText');
5044
+ }
5045
+ });
5046
+
5047
+ o.defineProperty(this, 'responseType', {
5048
+ configurable: false,
5049
+
5050
+ get: function() {
5051
+ return _p('responseType');
5052
+ },
5053
+
5054
+ set: function(value) {
5055
+ // 1
5056
+ if (!!~o.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) {
5057
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5058
+ }
5059
+
5060
+ // 2
5061
+ if (_sync_flag) {
5062
+ throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR);
5063
+ }
5064
+
5065
+ // 3
5066
+ _p('responseType', value.toLowerCase());
5067
+ }
5068
+ });
5069
+
5070
+ o.defineProperty(this, 'responseText', {
5071
+ configurable: false,
5072
+
5073
+ get: function() {
5074
+ // 1
5075
+ if (!~o.inArray(_p('responseType'), ['', 'text'])) {
5076
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5077
+ }
5078
+
5079
+ // 2-3
5080
+ if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) {
5081
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5082
+ }
5083
+
5084
+ return _p('responseText');
5085
+ }
5086
+ });
5087
+
5088
+ o.defineProperty(this, 'responseXML', {
5089
+ configurable: false,
5090
+
5091
+ get: function() {
5092
+ // 1
5093
+ if (!~o.inArray(_p('responseType'), ['', 'document'])) {
5094
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5095
+ }
5096
+
5097
+ // 2-3
5098
+ if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) {
5099
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5100
+ }
5101
+
5102
+ return _p('responseXML');
5103
+ }
5104
+ });
5105
+
5106
+ o.defineProperty(this, 'response', {
5107
+ configurable: false,
5108
+
5109
+ get: function() {
5110
+ if (!!~o.inArray(_p('responseType'), ['', 'text'])) {
5111
+ if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) {
5112
+ return '';
5113
+ }
5114
+ }
5115
+
5116
+ if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) {
5117
+ return null;
5118
+ }
5119
+
5120
+ return _p('response');
5121
+ }
5122
+ });
5123
+
5124
+ */
5125
+
5126
+ function _p(prop, value) {
5127
+ if (!props.hasOwnProperty(prop)) {
5128
+ return;
5129
+ }
5130
+ if (arguments.length === 1) { // get
5131
+ return Env.can('define_property') ? props[prop] : self[prop];
5132
+ } else { // set
5133
+ if (Env.can('define_property')) {
5134
+ props[prop] = value;
5135
+ } else {
5136
+ self[prop] = value;
5137
+ }
5138
+ }
5139
+ }
5140
+
5141
+ /*
5142
+ function _toASCII(str, AllowUnassigned, UseSTD3ASCIIRules) {
5143
+ // TODO: http://tools.ietf.org/html/rfc3490#section-4.1
5144
+ return str.toLowerCase();
5145
+ }
5146
+ */
5147
+
5148
+
5149
+ function _doXHR(data) {
5150
+ var self = this;
5151
+
5152
+ _start_time = new Date().getTime();
5153
+
5154
+ _xhr = new RuntimeTarget();
5155
+
5156
+ function loadEnd() {
5157
+ _xhr.destroy();
5158
+ _xhr = null;
5159
+ self.dispatchEvent('loadend');
5160
+ self = null;
5161
+ }
5162
+
5163
+ function exec(runtime) {
5164
+ _xhr.bind('LoadStart', function(e) {
5165
+ _p('readyState', XMLHttpRequest.LOADING);
5166
+ self.dispatchEvent('readystatechange');
5167
+
5168
+ self.dispatchEvent(e);
5169
+
5170
+ if (_upload_events_flag) {
5171
+ self.upload.dispatchEvent(e);
5172
+ }
5173
+ });
5174
+
5175
+ _xhr.bind('Progress', function(e) {
5176
+ if (_p('readyState') !== XMLHttpRequest.LOADING) {
5177
+ _p('readyState', XMLHttpRequest.LOADING); // LoadStart unreliable (in Flash for example)
5178
+ self.dispatchEvent('readystatechange');
5179
+ }
5180
+ self.dispatchEvent(e);
5181
+ });
5182
+
5183
+ _xhr.bind('UploadProgress', function(e) {
5184
+ if (_upload_events_flag) {
5185
+ self.upload.dispatchEvent({
5186
+ type: 'progress',
5187
+ lengthComputable: false,
5188
+ total: e.total,
5189
+ loaded: e.loaded
5190
+ });
5191
+ }
5192
+ });
5193
+
5194
+ _xhr.bind('Load', function(e) {
5195
+ _p('readyState', XMLHttpRequest.DONE);
5196
+ _p('status', Number(runtime.exec.call(_xhr, 'XMLHttpRequest', 'getStatus') || 0));
5197
+ _p('statusText', httpCode[_p('status')] || "");
5198
+
5199
+ _p('response', runtime.exec.call(_xhr, 'XMLHttpRequest', 'getResponse', _p('responseType')));
5200
+
5201
+ if (!!~Basic.inArray(_p('responseType'), ['text', ''])) {
5202
+ _p('responseText', _p('response'));
5203
+ } else if (_p('responseType') === 'document') {
5204
+ _p('responseXML', _p('response'));
5205
+ }
5206
+
5207
+ _responseHeaders = runtime.exec.call(_xhr, 'XMLHttpRequest', 'getAllResponseHeaders');
5208
+
5209
+ self.dispatchEvent('readystatechange');
5210
+
5211
+ if (_p('status') > 0) { // status 0 usually means that server is unreachable
5212
+ if (_upload_events_flag) {
5213
+ self.upload.dispatchEvent(e);
5214
+ }
5215
+ self.dispatchEvent(e);
5216
+ } else {
5217
+ _error_flag = true;
5218
+ self.dispatchEvent('error');
5219
+ }
5220
+ loadEnd();
5221
+ });
5222
+
5223
+ _xhr.bind('Abort', function(e) {
5224
+ self.dispatchEvent(e);
5225
+ loadEnd();
5226
+ });
5227
+
5228
+ _xhr.bind('Error', function(e) {
5229
+ _error_flag = true;
5230
+ _p('readyState', XMLHttpRequest.DONE);
5231
+ self.dispatchEvent('readystatechange');
5232
+ _upload_complete_flag = true;
5233
+ self.dispatchEvent(e);
5234
+ loadEnd();
5235
+ });
5236
+
5237
+ runtime.exec.call(_xhr, 'XMLHttpRequest', 'send', {
5238
+ url: _url,
5239
+ method: _method,
5240
+ async: _async,
5241
+ user: _user,
5242
+ password: _password,
5243
+ headers: _headers,
5244
+ mimeType: _mimeType,
5245
+ encoding: _encoding,
5246
+ responseType: self.responseType,
5247
+ withCredentials: self.withCredentials,
5248
+ options: _options
5249
+ }, data);
5250
+ }
5251
+
5252
+ // clarify our requirements
5253
+ if (typeof(_options.required_caps) === 'string') {
5254
+ _options.required_caps = Runtime.parseCaps(_options.required_caps);
5255
+ }
5256
+
5257
+ _options.required_caps = Basic.extend({}, _options.required_caps, {
5258
+ return_response_type: self.responseType
5259
+ });
5260
+
5261
+ if (data instanceof FormData) {
5262
+ _options.required_caps.send_multipart = true;
5263
+ }
5264
+
5265
+ if (!_same_origin_flag) {
5266
+ _options.required_caps.do_cors = true;
5267
+ }
5268
+
5269
+
5270
+ if (_options.ruid) { // we do not need to wait if we can connect directly
5271
+ exec(_xhr.connectRuntime(_options));
5272
+ } else {
5273
+ _xhr.bind('RuntimeInit', function(e, runtime) {
5274
+ exec(runtime);
5275
+ });
5276
+ _xhr.bind('RuntimeError', function(e, err) {
5277
+ self.dispatchEvent('RuntimeError', err);
5278
+ });
5279
+ _xhr.connectRuntime(_options);
5280
+ }
5281
+ }
5282
+
5283
+
5284
+ function _reset() {
5285
+ _p('responseText', "");
5286
+ _p('responseXML', null);
5287
+ _p('response', null);
5288
+ _p('status', 0);
5289
+ _p('statusText', "");
5290
+ _start_time = _timeoutset_time = null;
5291
+ }
5292
+ }
5293
+
5294
+ XMLHttpRequest.UNSENT = 0;
5295
+ XMLHttpRequest.OPENED = 1;
5296
+ XMLHttpRequest.HEADERS_RECEIVED = 2;
5297
+ XMLHttpRequest.LOADING = 3;
5298
+ XMLHttpRequest.DONE = 4;
5299
+
5300
+ XMLHttpRequest.prototype = EventTarget.instance;
5301
+
5302
+ return XMLHttpRequest;
5303
+ });
5304
+
5305
+ // Included from: src/javascript/runtime/Transporter.js
5306
+
5307
+ /**
5308
+ * Transporter.js
5309
+ *
5310
+ * Copyright 2013, Moxiecode Systems AB
5311
+ * Released under GPL License.
5312
+ *
5313
+ * License: http://www.plupload.com/license
5314
+ * Contributing: http://www.plupload.com/contributing
5315
+ */
5316
+
5317
+ define("moxie/runtime/Transporter", [
5318
+ "moxie/core/utils/Basic",
5319
+ "moxie/core/utils/Encode",
5320
+ "moxie/runtime/RuntimeClient",
5321
+ "moxie/core/EventTarget"
5322
+ ], function(Basic, Encode, RuntimeClient, EventTarget) {
5323
+ function Transporter() {
5324
+ var mod, _runtime, _data, _size, _pos, _chunk_size;
5325
+
5326
+ RuntimeClient.call(this);
5327
+
5328
+ Basic.extend(this, {
5329
+ uid: Basic.guid('uid_'),
5330
+
5331
+ state: Transporter.IDLE,
5332
+
5333
+ result: null,
5334
+
5335
+ transport: function(data, type, options) {
5336
+ var self = this;
5337
+
5338
+ options = Basic.extend({
5339
+ chunk_size: 204798
5340
+ }, options);
5341
+
5342
+ // should divide by three, base64 requires this
5343
+ if ((mod = options.chunk_size % 3)) {
5344
+ options.chunk_size += 3 - mod;
5345
+ }
5346
+
5347
+ _chunk_size = options.chunk_size;
5348
+
5349
+ _reset.call(this);
5350
+ _data = data;
5351
+ _size = data.length;
5352
+
5353
+ if (Basic.typeOf(options) === 'string' || options.ruid) {
5354
+ _run.call(self, type, this.connectRuntime(options));
5355
+ } else {
5356
+ // we require this to run only once
5357
+ var cb = function(e, runtime) {
5358
+ self.unbind("RuntimeInit", cb);
5359
+ _run.call(self, type, runtime);
5360
+ };
5361
+ this.bind("RuntimeInit", cb);
5362
+ this.connectRuntime(options);
5363
+ }
5364
+ },
5365
+
5366
+ abort: function() {
5367
+ var self = this;
5368
+
5369
+ self.state = Transporter.IDLE;
5370
+ if (_runtime) {
5371
+ _runtime.exec.call(self, 'Transporter', 'clear');
5372
+ self.trigger("TransportingAborted");
5373
+ }
5374
+
5375
+ _reset.call(self);
5376
+ },
5377
+
5378
+
5379
+ destroy: function() {
5380
+ this.unbindAll();
5381
+ _runtime = null;
5382
+ this.disconnectRuntime();
5383
+ _reset.call(this);
5384
+ }
5385
+ });
5386
+
5387
+ function _reset() {
5388
+ _size = _pos = 0;
5389
+ _data = this.result = null;
5390
+ }
5391
+
5392
+ function _run(type, runtime) {
5393
+ var self = this;
5394
+
5395
+ _runtime = runtime;
5396
+
5397
+ //self.unbind("RuntimeInit");
5398
+
5399
+ self.bind("TransportingProgress", function(e) {
5400
+ _pos = e.loaded;
5401
+
5402
+ if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) {
5403
+ _transport.call(self);
5404
+ }
5405
+ }, 999);
5406
+
5407
+ self.bind("TransportingComplete", function() {
5408
+ _pos = _size;
5409
+ self.state = Transporter.DONE;
5410
+ _data = null; // clean a bit
5411
+ self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || '');
5412
+ }, 999);
5413
+
5414
+ self.state = Transporter.BUSY;
5415
+ self.trigger("TransportingStarted");
5416
+ _transport.call(self);
5417
+ }
5418
+
5419
+ function _transport() {
5420
+ var self = this,
5421
+ chunk,
5422
+ bytesLeft = _size - _pos;
5423
+
5424
+ if (_chunk_size > bytesLeft) {
5425
+ _chunk_size = bytesLeft;
5426
+ }
5427
+
5428
+ chunk = Encode.btoa(_data.substr(_pos, _chunk_size));
5429
+ _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size);
5430
+ }
5431
+ }
5432
+
5433
+ Transporter.IDLE = 0;
5434
+ Transporter.BUSY = 1;
5435
+ Transporter.DONE = 2;
5436
+
5437
+ Transporter.prototype = EventTarget.instance;
5438
+
5439
+ return Transporter;
5440
+ });
5441
+
5442
+ // Included from: src/javascript/image/Image.js
5443
+
5444
+ /**
5445
+ * Image.js
5446
+ *
5447
+ * Copyright 2013, Moxiecode Systems AB
5448
+ * Released under GPL License.
5449
+ *
5450
+ * License: http://www.plupload.com/license
5451
+ * Contributing: http://www.plupload.com/contributing
5452
+ */
5453
+
5454
+ define("moxie/image/Image", [
5455
+ "moxie/core/utils/Basic",
5456
+ "moxie/core/utils/Dom",
5457
+ "moxie/core/Exceptions",
5458
+ "moxie/file/FileReaderSync",
5459
+ "moxie/xhr/XMLHttpRequest",
5460
+ "moxie/runtime/Runtime",
5461
+ "moxie/runtime/RuntimeClient",
5462
+ "moxie/runtime/Transporter",
5463
+ "moxie/core/utils/Env",
5464
+ "moxie/core/EventTarget",
5465
+ "moxie/file/Blob",
5466
+ "moxie/file/File",
5467
+ "moxie/core/utils/Encode"
5468
+ ], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) {
5469
+ /**
5470
+ Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data.
5471
+
5472
+ @class Image
5473
+ @constructor
5474
+ @extends EventTarget
5475
+ */
5476
+ var dispatches = [
5477
+ 'progress',
5478
+
5479
+ /**
5480
+ Dispatched when loading is complete.
5481
+
5482
+ @event load
5483
+ @param {Object} event
5484
+ */
5485
+ 'load',
5486
+
5487
+ 'error',
5488
+
5489
+ /**
5490
+ Dispatched when resize operation is complete.
5491
+
5492
+ @event resize
5493
+ @param {Object} event
5494
+ */
5495
+ 'resize',
5496
+
5497
+ /**
5498
+ Dispatched when visual representation of the image is successfully embedded
5499
+ into the corresponsing container.
5500
+
5501
+ @event embedded
5502
+ @param {Object} event
5503
+ */
5504
+ 'embedded'
5505
+ ];
5506
+
5507
+ function Image() {
5508
+ RuntimeClient.call(this);
5509
+
5510
+ Basic.extend(this, {
5511
+ /**
5512
+ Unique id of the component
5513
+
5514
+ @property uid
5515
+ @type {String}
5516
+ */
5517
+ uid: Basic.guid('uid_'),
5518
+
5519
+ /**
5520
+ Unique id of the connected runtime, if any.
5521
+
5522
+ @property ruid
5523
+ @type {String}
5524
+ */
5525
+ ruid: null,
5526
+
5527
+ /**
5528
+ Name of the file, that was used to create an image, if available. If not equals to empty string.
5529
+
5530
+ @property name
5531
+ @type {String}
5532
+ @default ""
5533
+ */
5534
+ name: "",
5535
+
5536
+ /**
5537
+ Size of the image in bytes. Actual value is set only after image is preloaded.
5538
+
5539
+ @property size
5540
+ @type {Number}
5541
+ @default 0
5542
+ */
5543
+ size: 0,
5544
+
5545
+ /**
5546
+ Width of the image. Actual value is set only after image is preloaded.
5547
+
5548
+ @property width
5549
+ @type {Number}
5550
+ @default 0
5551
+ */
5552
+ width: 0,
5553
+
5554
+ /**
5555
+ Height of the image. Actual value is set only after image is preloaded.
5556
+
5557
+ @property height
5558
+ @type {Number}
5559
+ @default 0
5560
+ */
5561
+ height: 0,
5562
+
5563
+ /**
5564
+ Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded.
5565
+
5566
+ @property type
5567
+ @type {String}
5568
+ @default ""
5569
+ */
5570
+ type: "",
5571
+
5572
+ /**
5573
+ Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded.
5574
+
5575
+ @property meta
5576
+ @type {Object}
5577
+ @default {}
5578
+ */
5579
+ meta: {},
5580
+
5581
+ /**
5582
+ Alias for load method, that takes another mOxie.Image object as a source (see load).
5583
+
5584
+ @method clone
5585
+ @param {Image} src Source for the image
5586
+ @param {Boolean} [exact=false] Whether to activate in-depth clone mode
5587
+ */
5588
+ clone: function() {
5589
+ this.load.apply(this, arguments);
5590
+ },
5591
+
5592
+ /**
5593
+ Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File,
5594
+ native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL,
5595
+ Image will be downloaded from remote destination and loaded in memory.
5596
+
5597
+ @example
5598
+ var img = new mOxie.Image();
5599
+ img.onload = function() {
5600
+ var blob = img.getAsBlob();
5601
+
5602
+ var formData = new mOxie.FormData();
5603
+ formData.append('file', blob);
5604
+
5605
+ var xhr = new mOxie.XMLHttpRequest();
5606
+ xhr.onload = function() {
5607
+ // upload complete
5608
+ };
5609
+ xhr.open('post', 'upload.php');
5610
+ xhr.send(formData);
5611
+ };
5612
+ img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg)
5613
+
5614
+
5615
+ @method load
5616
+ @param {Image|Blob|File|String} src Source for the image
5617
+ @param {Boolean|Object} [mixed]
5618
+ */
5619
+ load: function() {
5620
+ // this is here because to bind properly we need an uid first, which is created above
5621
+ this.bind('Load Resize', function() {
5622
+ _updateInfo.call(this);
5623
+ }, 999);
5624
+
5625
+ this.convertEventPropsToHandlers(dispatches);
5626
+
5627
+ _load.apply(this, arguments);
5628
+ },
5629
+
5630
+ /**
5631
+ Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions.
5632
+
5633
+ @method downsize
5634
+ @param {Number} width Resulting width
5635
+ @param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
5636
+ @param {Boolean} [crop=false] Whether to crop the image to exact dimensions
5637
+ @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
5638
+ */
5639
+ downsize: function(width, height, crop, preserveHeaders) {
5640
+ try {
5641
+ if (!this.size) { // only preloaded image objects can be used as source
5642
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5643
+ }
5644
+
5645
+ // no way to reliably intercept the crash due to high resolution, so we simply avoid it
5646
+ if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
5647
+ throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
5648
+ }
5649
+
5650
+ if (!width && !height || Basic.typeOf(crop) === 'undefined') {
5651
+ crop = false;
5652
+ }
5653
+
5654
+ width = width || this.width;
5655
+ height = height || this.height;
5656
+
5657
+ preserveHeaders = (Basic.typeOf(preserveHeaders) === 'undefined' ? true : !!preserveHeaders);
5658
+
5659
+ this.getRuntime().exec.call(this, 'Image', 'downsize', width, height, crop, preserveHeaders);
5660
+ } catch(ex) {
5661
+ // for now simply trigger error event
5662
+ this.trigger('error', ex);
5663
+ }
5664
+ },
5665
+
5666
+ /**
5667
+ Alias for downsize(width, height, true). (see downsize)
5668
+
5669
+ @method crop
5670
+ @param {Number} width Resulting width
5671
+ @param {Number} [height=width] Resulting height (optional, if not supplied will default to width)
5672
+ @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize)
5673
+ */
5674
+ crop: function(width, height, preserveHeaders) {
5675
+ this.downsize(width, height, true, preserveHeaders);
5676
+ },
5677
+
5678
+ getAsCanvas: function() {
5679
+ if (!Env.can('create_canvas')) {
5680
+ throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
5681
+ }
5682
+
5683
+ var runtime = this.connectRuntime(this.ruid);
5684
+ return runtime.exec.call(this, 'Image', 'getAsCanvas');
5685
+ },
5686
+
5687
+ /**
5688
+ Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws
5689
+ DOMException.INVALID_STATE_ERR).
5690
+
5691
+ @method getAsBlob
5692
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
5693
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
5694
+ @return {Blob} Image as Blob
5695
+ */
5696
+ getAsBlob: function(type, quality) {
5697
+ if (!this.size) {
5698
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5699
+ }
5700
+
5701
+ if (!type) {
5702
+ type = 'image/jpeg';
5703
+ }
5704
+
5705
+ if (type === 'image/jpeg' && !quality) {
5706
+ quality = 90;
5707
+ }
5708
+
5709
+ return this.getRuntime().exec.call(this, 'Image', 'getAsBlob', type, quality);
5710
+ },
5711
+
5712
+ /**
5713
+ Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws
5714
+ DOMException.INVALID_STATE_ERR).
5715
+
5716
+ @method getAsDataURL
5717
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
5718
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
5719
+ @return {String} Image as dataURL string
5720
+ */
5721
+ getAsDataURL: function(type, quality) {
5722
+ if (!this.size) {
5723
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5724
+ }
5725
+ return this.getRuntime().exec.call(this, 'Image', 'getAsDataURL', type, quality);
5726
+ },
5727
+
5728
+ /**
5729
+ Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws
5730
+ DOMException.INVALID_STATE_ERR).
5731
+
5732
+ @method getAsBinaryString
5733
+ @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png
5734
+ @param {Number} [quality=90] Applicable only together with mime type image/jpeg
5735
+ @return {String} Image as binary string
5736
+ */
5737
+ getAsBinaryString: function(type, quality) {
5738
+ var dataUrl = this.getAsDataURL(type, quality);
5739
+ return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7));
5740
+ },
5741
+
5742
+ /**
5743
+ Embeds the image, or better to say, it's visual representation into the specified node. Depending on the runtime
5744
+ in use, might be a canvas, or image (actual ) element or shim object (Flash or SilverLight - very rare, used for
5745
+ legacy browsers that do not have canvas or proper dataURI support).
5746
+
5747
+ @method embed
5748
+ @param {DOMElement} el DOM element to insert the image object into
5749
+ @param {Object} options Set of key/value pairs controlling the mime type, dimensions and cropping factor of resulting
5750
+ representation
5751
+ */
5752
+ embed: function(el) {
5753
+ var self = this
5754
+ , imgCopy
5755
+ , type, quality, crop
5756
+ , options = arguments[1] || {}
5757
+ , width = this.width
5758
+ , height = this.height
5759
+ , runtime // this has to be outside of all the closures to contain proper runtime
5760
+ ;
5761
+
5762
+ function onResize() {
5763
+ // if possible, embed a canvas element directly
5764
+ if (Env.can('create_canvas')) {
5765
+ var canvas = imgCopy.getAsCanvas();
5766
+ if (canvas) {
5767
+ el.appendChild(canvas);
5768
+ canvas = null;
5769
+ imgCopy.destroy();
5770
+ self.trigger('embedded');
5771
+ return;
5772
+ }
5773
+ }
5774
+
5775
+ var dataUrl = imgCopy.getAsDataURL(type, quality);
5776
+ if (!dataUrl) {
5777
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
5778
+ }
5779
+
5780
+ if (Env.can('use_data_uri_of', dataUrl.length)) {
5781
+ el.innerHTML = '<img src="' + dataUrl + '" width="' + imgCopy.width + '" height="' + imgCopy.height + '" />';
5782
+ imgCopy.destroy();
5783
+ self.trigger('embedded');
5784
+ } else {
5785
+ var tr = new Transporter();
5786
+
5787
+ tr.bind("TransportingComplete", function() {
5788
+ runtime = self.connectRuntime(this.result.ruid);
5789
+
5790
+ self.bind("Embedded", function() {
5791
+ // position and size properly
5792
+ Basic.extend(runtime.getShimContainer().style, {
5793
+ //position: 'relative',
5794
+ top: '0px',
5795
+ left: '0px',
5796
+ width: imgCopy.width + 'px',
5797
+ height: imgCopy.height + 'px'
5798
+ });
5799
+
5800
+ // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's
5801
+ // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and
5802
+ // sometimes 8 and they do not have this problem, we can comment this for now
5803
+ /*tr.bind("RuntimeInit", function(e, runtime) {
5804
+ tr.destroy();
5805
+ runtime.destroy();
5806
+ onResize.call(self); // re-feed our image data
5807
+ });*/
5808
+
5809
+ runtime = null;
5810
+ }, 999);
5811
+
5812
+ runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height);
5813
+ imgCopy.destroy();
5814
+ });
5815
+
5816
+ tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, Basic.extend({}, options, {
5817
+ required_caps: {
5818
+ display_media: true
5819
+ },
5820
+ runtime_order: 'flash,silverlight',
5821
+ container: el
5822
+ }));
5823
+ }
5824
+ }
5825
+
5826
+ try {
5827
+ if (!(el = Dom.get(el))) {
5828
+ throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR);
5829
+ }
5830
+
5831
+ if (!this.size) { // only preloaded image objects can be used as source
5832
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5833
+ }
5834
+
5835
+ if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) {
5836
+ throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR);
5837
+ }
5838
+
5839
+ type = options.type || this.type || 'image/jpeg';
5840
+ quality = options.quality || 90;
5841
+ crop = Basic.typeOf(options.crop) !== 'undefined' ? options.crop : false;
5842
+
5843
+ // figure out dimensions for the thumb
5844
+ if (options.width) {
5845
+ width = options.width;
5846
+ height = options.height || width;
5847
+ } else {
5848
+ // if container element has > 0 dimensions, take them
5849
+ var dimensions = Dom.getSize(el);
5850
+ if (dimensions.w && dimensions.h) { // both should be > 0
5851
+ width = dimensions.w;
5852
+ height = dimensions.h;
5853
+ }
5854
+ }
5855
+
5856
+ imgCopy = new Image();
5857
+
5858
+ imgCopy.bind("Resize", function() {
5859
+ onResize.call(self);
5860
+ });
5861
+
5862
+ imgCopy.bind("Load", function() {
5863
+ imgCopy.downsize(width, height, crop, false);
5864
+ });
5865
+
5866
+ imgCopy.clone(this, false);
5867
+
5868
+ return imgCopy;
5869
+ } catch(ex) {
5870
+ // for now simply trigger error event
5871
+ this.trigger('error', ex);
5872
+ }
5873
+ },
5874
+
5875
+ /**
5876
+ Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object.
5877
+
5878
+ @method destroy
5879
+ */
5880
+ destroy: function() {
5881
+ if (this.ruid) {
5882
+ this.getRuntime().exec.call(this, 'Image', 'destroy');
5883
+ this.disconnectRuntime();
5884
+ }
5885
+ this.unbindAll();
5886
+ }
5887
+ });
5888
+
5889
+
5890
+ function _updateInfo(info) {
5891
+ if (!info) {
5892
+ info = this.getRuntime().exec.call(this, 'Image', 'getInfo');
5893
+ }
5894
+
5895
+ this.size = info.size;
5896
+ this.width = info.width;
5897
+ this.height = info.height;
5898
+ this.type = info.type;
5899
+ this.meta = info.meta;
5900
+
5901
+ // update file name, only if empty
5902
+ if (this.name === '') {
5903
+ this.name = info.name;
5904
+ }
5905
+ }
5906
+
5907
+
5908
+ function _load(src) {
5909
+ var srcType = Basic.typeOf(src);
5910
+
5911
+ try {
5912
+ // if source is Image
5913
+ if (src instanceof Image) {
5914
+ if (!src.size) { // only preloaded image objects can be used as source
5915
+ throw new x.DOMException(x.DOMException.INVALID_STATE_ERR);
5916
+ }
5917
+ _loadFromImage.apply(this, arguments);
5918
+ }
5919
+ // if source is o.Blob/o.File
5920
+ else if (src instanceof Blob) {
5921
+ if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) {
5922
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
5923
+ }
5924
+ _loadFromBlob.apply(this, arguments);
5925
+ }
5926
+ // if native blob/file
5927
+ else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) {
5928
+ _load.call(this, new File(null, src), arguments[1]);
5929
+ }
5930
+ // if String
5931
+ else if (srcType === 'string') {
5932
+ // if dataUrl String
5933
+ if (/^data:[^;]*;base64,/.test(src)) {
5934
+ _load.call(this, new Blob(null, { data: src }), arguments[1]);
5935
+ }
5936
+ // else assume Url, either relative or absolute
5937
+ else {
5938
+ _loadFromUrl.apply(this, arguments);
5939
+ }
5940
+ }
5941
+ // if source seems to be an img node
5942
+ else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') {
5943
+ _load.call(this, src.src, arguments[1]);
5944
+ }
5945
+ else {
5946
+ throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR);
5947
+ }
5948
+ } catch(ex) {
5949
+ // for now simply trigger error event
5950
+ this.trigger('error', ex);
5951
+ }
5952
+ }
5953
+
5954
+
5955
+ function _loadFromImage(img, exact) {
5956
+ var runtime = this.connectRuntime(img.ruid);
5957
+ this.ruid = runtime.uid;
5958
+ runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact));
5959
+ }
5960
+
5961
+
5962
+ function _loadFromBlob(blob, options) {
5963
+ var self = this;
5964
+
5965
+ self.name = blob.name || '';
5966
+
5967
+ function exec(runtime) {
5968
+ self.ruid = runtime.uid;
5969
+ runtime.exec.call(self, 'Image', 'loadFromBlob', blob);
5970
+ }
5971
+
5972
+ if (blob.isDetached()) {
5973
+ this.bind('RuntimeInit', function(e, runtime) {
5974
+ exec(runtime);
5975
+ });
5976
+
5977
+ // convert to object representation
5978
+ if (options && typeof(options.required_caps) === 'string') {
5979
+ options.required_caps = Runtime.parseCaps(options.required_caps);
5980
+ }
5981
+
5982
+ this.connectRuntime(Basic.extend({
5983
+ required_caps: {
5984
+ access_image_binary: true,
5985
+ resize_image: true
5986
+ }
5987
+ }, options));
5988
+ } else {
5989
+ exec(this.connectRuntime(blob.ruid));
5990
+ }
5991
+ }
5992
+
5993
+
5994
+ function _loadFromUrl(url, options) {
5995
+ var self = this, xhr;
5996
+
5997
+ xhr = new XMLHttpRequest();
5998
+
5999
+ xhr.open('get', url);
6000
+ xhr.responseType = 'blob';
6001
+
6002
+ xhr.onprogress = function(e) {
6003
+ self.trigger(e);
6004
+ };
6005
+
6006
+ xhr.onload = function() {
6007
+ _loadFromBlob.call(self, xhr.response, true);
6008
+ };
6009
+
6010
+ xhr.onerror = function(e) {
6011
+ self.trigger(e);
6012
+ };
6013
+
6014
+ xhr.onloadend = function() {
6015
+ xhr.destroy();
6016
+ };
6017
+
6018
+ xhr.bind('RuntimeError', function(e, err) {
6019
+ self.trigger('RuntimeError', err);
6020
+ });
6021
+
6022
+ xhr.send(null, options);
6023
+ }
6024
+ }
6025
+
6026
+ // virtual world will crash on you if image has a resolution higher than this:
6027
+ Image.MAX_RESIZE_WIDTH = 6500;
6028
+ Image.MAX_RESIZE_HEIGHT = 6500;
6029
+
6030
+ Image.prototype = EventTarget.instance;
6031
+
6032
+ return Image;
6033
+ });
6034
+
6035
+ // Included from: src/javascript/runtime/html5/Runtime.js
6036
+
6037
+ /**
6038
+ * Runtime.js
6039
+ *
6040
+ * Copyright 2013, Moxiecode Systems AB
6041
+ * Released under GPL License.
6042
+ *
6043
+ * License: http://www.plupload.com/license
6044
+ * Contributing: http://www.plupload.com/contributing
6045
+ */
6046
+
6047
+ /*global File:true */
6048
+
6049
+ /**
6050
+ Defines constructor for HTML5 runtime.
6051
+
6052
+ @class moxie/runtime/html5/Runtime
6053
+ @private
6054
+ */
6055
+ define("moxie/runtime/html5/Runtime", [
6056
+ "moxie/core/utils/Basic",
6057
+ "moxie/core/Exceptions",
6058
+ "moxie/runtime/Runtime",
6059
+ "moxie/core/utils/Env"
6060
+ ], function(Basic, x, Runtime, Env) {
6061
+
6062
+ var type = "html5", extensions = {};
6063
+
6064
+ function Html5Runtime(options) {
6065
+ var I = this
6066
+ , Test = Runtime.capTest
6067
+ , True = Runtime.capTrue
6068
+ ;
6069
+
6070
+ var caps = Basic.extend({
6071
+ access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL),
6072
+ access_image_binary: function() {
6073
+ return I.can('access_binary') && !!extensions.Image;
6074
+ },
6075
+ display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')),
6076
+ do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()),
6077
+ drag_and_drop: Test(function() {
6078
+ // this comes directly from Modernizr: http://www.modernizr.com/
6079
+ var div = document.createElement('div');
6080
+ // IE has support for drag and drop since version 5, but doesn't support dropping files from desktop
6081
+ return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && (Env.browser !== 'IE' || Env.version > 9);
6082
+ }()),
6083
+ filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
6084
+ return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10);
6085
+ }()),
6086
+ return_response_headers: True,
6087
+ return_response_type: function(responseType) {
6088
+ if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported
6089
+ return true;
6090
+ }
6091
+ return Env.can('return_response_type', responseType);
6092
+ },
6093
+ return_status_code: True,
6094
+ report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload),
6095
+ resize_image: function() {
6096
+ return I.can('access_binary') && Env.can('create_canvas');
6097
+ },
6098
+ select_file: function() {
6099
+ return Env.can('use_fileinput') && window.File;
6100
+ },
6101
+ select_folder: function() {
6102
+ return I.can('select_file') && Env.browser === 'Chrome' && Env.version >= 21;
6103
+ },
6104
+ select_multiple: function() {
6105
+ // it is buggy on Safari Windows and iOS
6106
+ return I.can('select_file') &&
6107
+ !(Env.browser === 'Safari' && Env.os === 'Windows') &&
6108
+ !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.4", '<'));
6109
+ },
6110
+ send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))),
6111
+ send_custom_headers: Test(window.XMLHttpRequest),
6112
+ send_multipart: function() {
6113
+ return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string');
6114
+ },
6115
+ slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)),
6116
+ stream_upload: function(){
6117
+ return I.can('slice_blob') && I.can('send_multipart');
6118
+ },
6119
+ summon_file_dialog: Test(function() { // yeah... some dirty sniffing here...
6120
+ return (Env.browser === 'Firefox' && Env.version >= 4) ||
6121
+ (Env.browser === 'Opera' && Env.version >= 12) ||
6122
+ (Env.browser === 'IE' && Env.version >= 10) ||
6123
+ !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']);
6124
+ }()),
6125
+ upload_filesize: True
6126
+ },
6127
+ arguments[2]
6128
+ );
6129
+
6130
+ Runtime.call(this, options, (arguments[1] || type), caps);
6131
+
6132
+
6133
+ Basic.extend(this, {
6134
+
6135
+ init : function() {
6136
+ this.trigger("Init");
6137
+ },
6138
+
6139
+ destroy: (function(destroy) { // extend default destroy method
6140
+ return function() {
6141
+ destroy.call(I);
6142
+ destroy = I = null;
6143
+ };
6144
+ }(this.destroy))
6145
+ });
6146
+
6147
+ Basic.extend(this.getShim(), extensions);
6148
+ }
6149
+
6150
+ Runtime.addConstructor(type, Html5Runtime);
6151
+
6152
+ return extensions;
6153
+ });
6154
+
6155
+ // Included from: src/javascript/runtime/html5/file/Blob.js
6156
+
6157
+ /**
6158
+ * Blob.js
6159
+ *
6160
+ * Copyright 2013, Moxiecode Systems AB
6161
+ * Released under GPL License.
6162
+ *
6163
+ * License: http://www.plupload.com/license
6164
+ * Contributing: http://www.plupload.com/contributing
6165
+ */
6166
+
6167
+ /**
6168
+ @class moxie/runtime/html5/file/Blob
6169
+ @private
6170
+ */
6171
+ define("moxie/runtime/html5/file/Blob", [
6172
+ "moxie/runtime/html5/Runtime",
6173
+ "moxie/file/Blob"
6174
+ ], function(extensions, Blob) {
6175
+
6176
+ function HTML5Blob() {
6177
+ function w3cBlobSlice(blob, start, end) {
6178
+ var blobSlice;
6179
+
6180
+ if (window.File.prototype.slice) {
6181
+ try {
6182
+ blob.slice(); // depricated version will throw WRONG_ARGUMENTS_ERR exception
6183
+ return blob.slice(start, end);
6184
+ } catch (e) {
6185
+ // depricated slice method
6186
+ return blob.slice(start, end - start);
6187
+ }
6188
+ // slice method got prefixed: https://bugzilla.mozilla.org/show_bug.cgi?id=649672
6189
+ } else if ((blobSlice = window.File.prototype.webkitSlice || window.File.prototype.mozSlice)) {
6190
+ return blobSlice.call(blob, start, end);
6191
+ } else {
6192
+ return null; // or throw some exception
6193
+ }
6194
+ }
6195
+
6196
+ this.slice = function() {
6197
+ return new Blob(this.getRuntime().uid, w3cBlobSlice.apply(this, arguments));
6198
+ };
6199
+ }
6200
+
6201
+ return (extensions.Blob = HTML5Blob);
6202
+ });
6203
+
6204
+ // Included from: src/javascript/core/utils/Events.js
6205
+
6206
+ /**
6207
+ * Events.js
6208
+ *
6209
+ * Copyright 2013, Moxiecode Systems AB
6210
+ * Released under GPL License.
6211
+ *
6212
+ * License: http://www.plupload.com/license
6213
+ * Contributing: http://www.plupload.com/contributing
6214
+ */
6215
+
6216
+ define('moxie/core/utils/Events', [
6217
+ 'moxie/core/utils/Basic'
6218
+ ], function(Basic) {
6219
+ var eventhash = {}, uid = 'moxie_' + Basic.guid();
6220
+
6221
+ // IE W3C like event funcs
6222
+ function preventDefault() {
6223
+ this.returnValue = false;
6224
+ }
6225
+
6226
+ function stopPropagation() {
6227
+ this.cancelBubble = true;
6228
+ }
6229
+
6230
+ /**
6231
+ Adds an event handler to the specified object and store reference to the handler
6232
+ in objects internal Plupload registry (@see removeEvent).
6233
+
6234
+ @method addEvent
6235
+ @for Utils
6236
+ @static
6237
+ @param {Object} obj DOM element like object to add handler to.
6238
+ @param {String} name Name to add event listener to.
6239
+ @param {Function} callback Function to call when event occurs.
6240
+ @param {String} [key] that might be used to add specifity to the event record.
6241
+ */
6242
+ var addEvent = function(obj, name, callback, key) {
6243
+ var func, events;
6244
+
6245
+ name = name.toLowerCase();
6246
+
6247
+ // Add event listener
6248
+ if (obj.addEventListener) {
6249
+ func = callback;
6250
+
6251
+ obj.addEventListener(name, func, false);
6252
+ } else if (obj.attachEvent) {
6253
+ func = function() {
6254
+ var evt = window.event;
6255
+
6256
+ if (!evt.target) {
6257
+ evt.target = evt.srcElement;
6258
+ }
6259
+
6260
+ evt.preventDefault = preventDefault;
6261
+ evt.stopPropagation = stopPropagation;
6262
+
6263
+ callback(evt);
6264
+ };
6265
+
6266
+ obj.attachEvent('on' + name, func);
6267
+ }
6268
+
6269
+ // Log event handler to objects internal mOxie registry
6270
+ if (!obj[uid]) {
6271
+ obj[uid] = Basic.guid();
6272
+ }
6273
+
6274
+ if (!eventhash.hasOwnProperty(obj[uid])) {
6275
+ eventhash[obj[uid]] = {};
6276
+ }
6277
+
6278
+ events = eventhash[obj[uid]];
6279
+
6280
+ if (!events.hasOwnProperty(name)) {
6281
+ events[name] = [];
6282
+ }
6283
+
6284
+ events[name].push({
6285
+ func: func,
6286
+ orig: callback, // store original callback for IE
6287
+ key: key
6288
+ });
6289
+ };
6290
+
6291
+
6292
+ /**
6293
+ Remove event handler from the specified object. If third argument (callback)
6294
+ is not specified remove all events with the specified name.
6295
+
6296
+ @method removeEvent
6297
+ @static
6298
+ @param {Object} obj DOM element to remove event listener(s) from.
6299
+ @param {String} name Name of event listener to remove.
6300
+ @param {Function|String} [callback] might be a callback or unique key to match.
6301
+ */
6302
+ var removeEvent = function(obj, name, callback) {
6303
+ var type, undef;
6304
+
6305
+ name = name.toLowerCase();
6306
+
6307
+ if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) {
6308
+ type = eventhash[obj[uid]][name];
6309
+ } else {
6310
+ return;
6311
+ }
6312
+
6313
+ for (var i = type.length - 1; i >= 0; i--) {
6314
+ // undefined or not, key should match
6315
+ if (type[i].orig === callback || type[i].key === callback) {
6316
+ if (obj.removeEventListener) {
6317
+ obj.removeEventListener(name, type[i].func, false);
6318
+ } else if (obj.detachEvent) {
6319
+ obj.detachEvent('on'+name, type[i].func);
6320
+ }
6321
+
6322
+ type[i].orig = null;
6323
+ type[i].func = null;
6324
+ type.splice(i, 1);
6325
+
6326
+ // If callback was passed we are done here, otherwise proceed
6327
+ if (callback !== undef) {
6328
+ break;
6329
+ }
6330
+ }
6331
+ }
6332
+
6333
+ // If event array got empty, remove it
6334
+ if (!type.length) {
6335
+ delete eventhash[obj[uid]][name];
6336
+ }
6337
+
6338
+ // If mOxie registry has become empty, remove it
6339
+ if (Basic.isEmptyObj(eventhash[obj[uid]])) {
6340
+ delete eventhash[obj[uid]];
6341
+
6342
+ // IE doesn't let you remove DOM object property with - delete
6343
+ try {
6344
+ delete obj[uid];
6345
+ } catch(e) {
6346
+ obj[uid] = undef;
6347
+ }
6348
+ }
6349
+ };
6350
+
6351
+
6352
+ /**
6353
+ Remove all kind of events from the specified object
6354
+
6355
+ @method removeAllEvents
6356
+ @static
6357
+ @param {Object} obj DOM element to remove event listeners from.
6358
+ @param {String} [key] unique key to match, when removing events.
6359
+ */
6360
+ var removeAllEvents = function(obj, key) {
6361
+ if (!obj || !obj[uid]) {
6362
+ return;
6363
+ }
6364
+
6365
+ Basic.each(eventhash[obj[uid]], function(events, name) {
6366
+ removeEvent(obj, name, key);
6367
+ });
6368
+ };
6369
+
6370
+ return {
6371
+ addEvent: addEvent,
6372
+ removeEvent: removeEvent,
6373
+ removeAllEvents: removeAllEvents
6374
+ };
6375
+ });
6376
+
6377
+ // Included from: src/javascript/runtime/html5/file/FileInput.js
6378
+
6379
+ /**
6380
+ * FileInput.js
6381
+ *
6382
+ * Copyright 2013, Moxiecode Systems AB
6383
+ * Released under GPL License.
6384
+ *
6385
+ * License: http://www.plupload.com/license
6386
+ * Contributing: http://www.plupload.com/contributing
6387
+ */
6388
+
6389
+ /**
6390
+ @class moxie/runtime/html5/file/FileInput
6391
+ @private
6392
+ */
6393
+ define("moxie/runtime/html5/file/FileInput", [
6394
+ "moxie/runtime/html5/Runtime",
6395
+ "moxie/core/utils/Basic",
6396
+ "moxie/core/utils/Dom",
6397
+ "moxie/core/utils/Events",
6398
+ "moxie/core/utils/Mime",
6399
+ "moxie/core/utils/Env"
6400
+ ], function(extensions, Basic, Dom, Events, Mime, Env) {
6401
+
6402
+ function FileInput() {
6403
+ var _files = [], _options;
6404
+
6405
+ Basic.extend(this, {
6406
+ init: function(options) {
6407
+ var comp = this, I = comp.getRuntime(), input, shimContainer, mimes, browseButton, zIndex, top;
6408
+
6409
+ _options = options;
6410
+ _files = [];
6411
+
6412
+ // figure out accept string
6413
+ mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept, I.can('filter_by_extension'));
6414
+
6415
+ shimContainer = I.getShimContainer();
6416
+
6417
+ shimContainer.innerHTML = '<input id="' + I.uid +'" type="file" style="font-size:999px;opacity:0;"' +
6418
+ (_options.multiple && I.can('select_multiple') ? 'multiple' : '') +
6419
+ (_options.directory && I.can('select_folder') ? 'webkitdirectory directory' : '') + // Chrome 11+
6420
+ (mimes ? ' accept="' + mimes.join(',') + '"' : '') + ' />';
6421
+
6422
+ input = Dom.get(I.uid);
6423
+
6424
+ // prepare file input to be placed underneath the browse_button element
6425
+ Basic.extend(input.style, {
6426
+ position: 'absolute',
6427
+ top: 0,
6428
+ left: 0,
6429
+ width: '100%',
6430
+ height: '100%'
6431
+ });
6432
+
6433
+
6434
+ browseButton = Dom.get(_options.browse_button);
6435
+
6436
+ // Route click event to the input[type=file] element for browsers that support such behavior
6437
+ if (I.can('summon_file_dialog')) {
6438
+ if (Dom.getStyle(browseButton, 'position') === 'static') {
6439
+ browseButton.style.position = 'relative';
6440
+ }
6441
+
6442
+ zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;
6443
+
6444
+ browseButton.style.zIndex = zIndex;
6445
+ shimContainer.style.zIndex = zIndex - 1;
6446
+
6447
+ Events.addEvent(browseButton, 'click', function(e) {
6448
+ var input = Dom.get(I.uid);
6449
+ if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
6450
+ input.click();
6451
+ }
6452
+ e.preventDefault();
6453
+ }, comp.uid);
6454
+ }
6455
+
6456
+ /* Since we have to place input[type=file] on top of the browse_button for some browsers,
6457
+ browse_button loses interactivity, so we restore it here */
6458
+ top = I.can('summon_file_dialog') ? browseButton : shimContainer;
6459
+
6460
+ Events.addEvent(top, 'mouseover', function() {
6461
+ comp.trigger('mouseenter');
6462
+ }, comp.uid);
6463
+
6464
+ Events.addEvent(top, 'mouseout', function() {
6465
+ comp.trigger('mouseleave');
6466
+ }, comp.uid);
6467
+
6468
+ Events.addEvent(top, 'mousedown', function() {
6469
+ comp.trigger('mousedown');
6470
+ }, comp.uid);
6471
+
6472
+ Events.addEvent(Dom.get(_options.container), 'mouseup', function() {
6473
+ comp.trigger('mouseup');
6474
+ }, comp.uid);
6475
+
6476
+
6477
+ input.onchange = function onChange() { // there should be only one handler for this
6478
+ _files = [];
6479
+
6480
+ if (_options.directory) {
6481
+ // folders are represented by dots, filter them out (Chrome 11+)
6482
+ Basic.each(this.files, function(file) {
6483
+ if (file.name !== ".") { // if it doesn't looks like a folder
6484
+ _files.push(file);
6485
+ }
6486
+ });
6487
+ } else {
6488
+ _files = [].slice.call(this.files);
6489
+ }
6490
+
6491
+ // clearing the value enables the user to select the same file again if they want to
6492
+ if (Env.browser !== 'IE') {
6493
+ this.value = '';
6494
+ } else {
6495
+ // in IE input[type="file"] is read-only so the only way to reset it is to re-insert it
6496
+ var clone = this.cloneNode(true);
6497
+ this.parentNode.replaceChild(clone, this);
6498
+ clone.onchange = onChange;
6499
+ }
6500
+ comp.trigger('change');
6501
+ };
6502
+
6503
+ // ready event is perfectly asynchronous
6504
+ comp.trigger({
6505
+ type: 'ready',
6506
+ async: true
6507
+ });
6508
+
6509
+ shimContainer = null;
6510
+ },
6511
+
6512
+ getFiles: function() {
6513
+ return _files;
6514
+ },
6515
+
6516
+ disable: function(state) {
6517
+ var I = this.getRuntime(), input;
6518
+
6519
+ if ((input = Dom.get(I.uid))) {
6520
+ input.disabled = !!state;
6521
+ }
6522
+ },
6523
+
6524
+ destroy: function() {
6525
+ var I = this.getRuntime()
6526
+ , shim = I.getShim()
6527
+ , shimContainer = I.getShimContainer()
6528
+ ;
6529
+
6530
+ Events.removeAllEvents(shimContainer, this.uid);
6531
+ Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
6532
+ Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid);
6533
+
6534
+ if (shimContainer) {
6535
+ shimContainer.innerHTML = '';
6536
+ }
6537
+
6538
+ shim.removeInstance(this.uid);
6539
+
6540
+ _files = _options = shimContainer = shim = null;
6541
+ }
6542
+ });
6543
+ }
6544
+
6545
+ return (extensions.FileInput = FileInput);
6546
+ });
6547
+
6548
+ // Included from: src/javascript/runtime/html5/file/FileDrop.js
6549
+
6550
+ /**
6551
+ * FileDrop.js
6552
+ *
6553
+ * Copyright 2013, Moxiecode Systems AB
6554
+ * Released under GPL License.
6555
+ *
6556
+ * License: http://www.plupload.com/license
6557
+ * Contributing: http://www.plupload.com/contributing
6558
+ */
6559
+
6560
+ /**
6561
+ @class moxie/runtime/html5/file/FileDrop
6562
+ @private
6563
+ */
6564
+ define("moxie/runtime/html5/file/FileDrop", [
6565
+ "moxie/runtime/html5/Runtime",
6566
+ "moxie/core/utils/Basic",
6567
+ "moxie/core/utils/Dom",
6568
+ "moxie/core/utils/Events",
6569
+ "moxie/core/utils/Mime"
6570
+ ], function(extensions, Basic, Dom, Events, Mime) {
6571
+
6572
+ function FileDrop() {
6573
+ var _files = [], _allowedExts = [], _options;
6574
+
6575
+ Basic.extend(this, {
6576
+ init: function(options) {
6577
+ var comp = this, dropZone;
6578
+
6579
+ _options = options;
6580
+ _allowedExts = _extractExts(_options.accept);
6581
+ dropZone = _options.container;
6582
+
6583
+ Events.addEvent(dropZone, 'dragover', function(e) {
6584
+ e.preventDefault();
6585
+ e.stopPropagation();
6586
+ e.dataTransfer.dropEffect = 'copy';
6587
+ }, comp.uid);
6588
+
6589
+ Events.addEvent(dropZone, 'drop', function(e) {
6590
+ e.preventDefault();
6591
+ e.stopPropagation();
6592
+
6593
+ _files = [];
6594
+
6595
+ // Chrome 21+ accepts folders via Drag'n'Drop
6596
+ if (e.dataTransfer.items && e.dataTransfer.items[0].webkitGetAsEntry) {
6597
+ _readItems(e.dataTransfer.items, function() {
6598
+ comp.trigger("drop");
6599
+ });
6600
+ } else {
6601
+ Basic.each(e.dataTransfer.files, function(file) {
6602
+ if (_isAcceptable(file)) {
6603
+ _files.push(file);
6604
+ }
6605
+ });
6606
+ comp.trigger("drop");
6607
+ }
6608
+ }, comp.uid);
6609
+
6610
+ Events.addEvent(dropZone, 'dragenter', function(e) {
6611
+ e.preventDefault();
6612
+ e.stopPropagation();
6613
+ comp.trigger("dragenter");
6614
+ }, comp.uid);
6615
+
6616
+ Events.addEvent(dropZone, 'dragleave', function(e) {
6617
+ e.preventDefault();
6618
+ e.stopPropagation();
6619
+ comp.trigger("dragleave");
6620
+ }, comp.uid);
6621
+ },
6622
+
6623
+ getFiles: function() {
6624
+ return _files;
6625
+ },
6626
+
6627
+ destroy: function() {
6628
+ Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
6629
+ _files = _allowedExts = _options = null;
6630
+ }
6631
+ });
6632
+
6633
+
6634
+ function _extractExts(accept) {
6635
+ var exts = [];
6636
+ for (var i = 0; i < accept.length; i++) {
6637
+ [].push.apply(exts, accept[i].extensions.split(/\s*,\s*/));
6638
+ }
6639
+ return Basic.inArray('*', exts) === -1 ? exts : [];
6640
+ }
6641
+
6642
+
6643
+ function _isAcceptable(file) {
6644
+ var ext = Mime.getFileExtension(file.name);
6645
+ return !ext || !_allowedExts.length || Basic.inArray(ext, _allowedExts) !== -1;
6646
+ }
6647
+
6648
+
6649
+ function _readItems(items, cb) {
6650
+ var entries = [];
6651
+ Basic.each(items, function(item) {
6652
+ var entry = item.webkitGetAsEntry();
6653
+ // Address #998 (https://code.google.com/p/chromium/issues/detail?id=332579)
6654
+ if (entry) {
6655
+ // file() fails on OSX when the filename contains a special character (e.g. umlaut): see #61
6656
+ if (entry.isFile) {
6657
+ var file = item.getAsFile();
6658
+ if (_isAcceptable(file)) {
6659
+ _files.push(file);
6660
+ }
6661
+ } else {
6662
+ entries.push(entry);
6663
+ }
6664
+ }
6665
+ });
6666
+
6667
+ if (entries.length) {
6668
+ _readEntries(entries, cb);
6669
+ } else {
6670
+ cb();
6671
+ }
6672
+ }
6673
+
6674
+
6675
+ function _readEntries(entries, cb) {
6676
+ var queue = [];
6677
+ Basic.each(entries, function(entry) {
6678
+ queue.push(function(cbcb) {
6679
+ _readEntry(entry, cbcb);
6680
+ });
6681
+ });
6682
+ Basic.inSeries(queue, function() {
6683
+ cb();
6684
+ });
6685
+ }
6686
+
6687
+ function _readEntry(entry, cb) {
6688
+ if (entry.isFile) {
6689
+ entry.file(function(file) {
6690
+ if (_isAcceptable(file)) {
6691
+ _files.push(file);
6692
+ }
6693
+ cb();
6694
+ }, function() {
6695
+ // fire an error event maybe
6696
+ cb();
6697
+ });
6698
+ } else if (entry.isDirectory) {
6699
+ _readDirEntry(entry, cb);
6700
+ } else {
6701
+ cb(); // not file, not directory? what then?..
6702
+ }
6703
+ }
6704
+
6705
+ function _readDirEntry(dirEntry, cb) {
6706
+ var entries = [], dirReader = dirEntry.createReader();
6707
+
6708
+ // keep quering recursively till no more entries
6709
+ function getEntries(cbcb) {
6710
+ dirReader.readEntries(function(moreEntries) {
6711
+ if (moreEntries.length) {
6712
+ [].push.apply(entries, moreEntries);
6713
+ getEntries(cbcb);
6714
+ } else {
6715
+ cbcb();
6716
+ }
6717
+ }, cbcb);
6718
+ }
6719
+
6720
+ // ...and you thought FileReader was crazy...
6721
+ getEntries(function() {
6722
+ _readEntries(entries, cb);
6723
+ });
6724
+ }
6725
+ }
6726
+
6727
+ return (extensions.FileDrop = FileDrop);
6728
+ });
6729
+
6730
+ // Included from: src/javascript/runtime/html5/file/FileReader.js
6731
+
6732
+ /**
6733
+ * FileReader.js
6734
+ *
6735
+ * Copyright 2013, Moxiecode Systems AB
6736
+ * Released under GPL License.
6737
+ *
6738
+ * License: http://www.plupload.com/license
6739
+ * Contributing: http://www.plupload.com/contributing
6740
+ */
6741
+
6742
+ /**
6743
+ @class moxie/runtime/html5/file/FileReader
6744
+ @private
6745
+ */
6746
+ define("moxie/runtime/html5/file/FileReader", [
6747
+ "moxie/runtime/html5/Runtime",
6748
+ "moxie/core/utils/Encode",
6749
+ "moxie/core/utils/Basic"
6750
+ ], function(extensions, Encode, Basic) {
6751
+
6752
+ function FileReader() {
6753
+ var _fr, _convertToBinary = false;
6754
+
6755
+ Basic.extend(this, {
6756
+
6757
+ read: function(op, blob) {
6758
+ var target = this;
6759
+
6760
+ _fr = new window.FileReader();
6761
+
6762
+ _fr.addEventListener('progress', function(e) {
6763
+ target.trigger(e);
6764
+ });
6765
+
6766
+ _fr.addEventListener('load', function(e) {
6767
+ target.trigger(e);
6768
+ });
6769
+
6770
+ _fr.addEventListener('error', function(e) {
6771
+ target.trigger(e, _fr.error);
6772
+ });
6773
+
6774
+ _fr.addEventListener('loadend', function() {
6775
+ _fr = null;
6776
+ });
6777
+
6778
+ if (Basic.typeOf(_fr[op]) === 'function') {
6779
+ _convertToBinary = false;
6780
+ _fr[op](blob.getSource());
6781
+ } else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+
6782
+ _convertToBinary = true;
6783
+ _fr.readAsDataURL(blob.getSource());
6784
+ }
6785
+ },
6786
+
6787
+ getResult: function() {
6788
+ return _fr && _fr.result ? (_convertToBinary ? _toBinary(_fr.result) : _fr.result) : null;
6789
+ },
6790
+
6791
+ abort: function() {
6792
+ if (_fr) {
6793
+ _fr.abort();
6794
+ }
6795
+ },
6796
+
6797
+ destroy: function() {
6798
+ _fr = null;
6799
+ }
6800
+ });
6801
+
6802
+ function _toBinary(str) {
6803
+ return Encode.atob(str.substring(str.indexOf('base64,') + 7));
6804
+ }
6805
+ }
6806
+
6807
+ return (extensions.FileReader = FileReader);
6808
+ });
6809
+
6810
+ // Included from: src/javascript/runtime/html5/xhr/XMLHttpRequest.js
6811
+
6812
+ /**
6813
+ * XMLHttpRequest.js
6814
+ *
6815
+ * Copyright 2013, Moxiecode Systems AB
6816
+ * Released under GPL License.
6817
+ *
6818
+ * License: http://www.plupload.com/license
6819
+ * Contributing: http://www.plupload.com/contributing
6820
+ */
6821
+
6822
+ /*global ActiveXObject:true */
6823
+
6824
+ /**
6825
+ @class moxie/runtime/html5/xhr/XMLHttpRequest
6826
+ @private
6827
+ */
6828
+ define("moxie/runtime/html5/xhr/XMLHttpRequest", [
6829
+ "moxie/runtime/html5/Runtime",
6830
+ "moxie/core/utils/Basic",
6831
+ "moxie/core/utils/Mime",
6832
+ "moxie/core/utils/Url",
6833
+ "moxie/file/File",
6834
+ "moxie/file/Blob",
6835
+ "moxie/xhr/FormData",
6836
+ "moxie/core/Exceptions",
6837
+ "moxie/core/utils/Env"
6838
+ ], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env) {
6839
+
6840
+ function XMLHttpRequest() {
6841
+ var self = this
6842
+ , _xhr
6843
+ , _filename
6844
+ ;
6845
+
6846
+ Basic.extend(this, {
6847
+ send: function(meta, data) {
6848
+ var target = this
6849
+ , isGecko2_5_6 = (Env.browser === 'Mozilla' && Env.version >= 4 && Env.version < 7)
6850
+ , isAndroidBrowser = Env.browser === 'Android Browser'
6851
+ , mustSendAsBinary = false
6852
+ ;
6853
+
6854
+ // extract file name
6855
+ _filename = meta.url.replace(/^.+?\/([\w\-\.]+)$/, '$1').toLowerCase();
6856
+
6857
+ _xhr = _getNativeXHR();
6858
+ _xhr.open(meta.method, meta.url, meta.async, meta.user, meta.password);
6859
+
6860
+
6861
+ // prepare data to be sent
6862
+ if (data instanceof Blob) {
6863
+ if (data.isDetached()) {
6864
+ mustSendAsBinary = true;
6865
+ }
6866
+ data = data.getSource();
6867
+ } else if (data instanceof FormData) {
6868
+
6869
+ if (data.hasBlob()) {
6870
+ if (data.getBlob().isDetached()) {
6871
+ data = _prepareMultipart.call(target, data); // _xhr must be instantiated and be in OPENED state
6872
+ mustSendAsBinary = true;
6873
+ } else if ((isGecko2_5_6 || isAndroidBrowser) && Basic.typeOf(data.getBlob().getSource()) === 'blob' && window.FileReader) {
6874
+ // Gecko 2/5/6 can't send blob in FormData: https://bugzilla.mozilla.org/show_bug.cgi?id=649150
6875
+ // Android browsers (default one and Dolphin) seem to have the same issue, see: #613
6876
+ _preloadAndSend.call(target, meta, data);
6877
+ return; // _preloadAndSend will reinvoke send() with transmutated FormData =%D
6878
+ }
6879
+ }
6880
+
6881
+ // transfer fields to real FormData
6882
+ if (data instanceof FormData) { // if still a FormData, e.g. not mangled by _prepareMultipart()
6883
+ var fd = new window.FormData();
6884
+ data.each(function(value, name) {
6885
+ if (value instanceof Blob) {
6886
+ fd.append(name, value.getSource());
6887
+ } else {
6888
+ fd.append(name, value);
6889
+ }
6890
+ });
6891
+ data = fd;
6892
+ }
6893
+ }
6894
+
6895
+
6896
+ // if XHR L2
6897
+ if (_xhr.upload) {
6898
+ if (meta.withCredentials) {
6899
+ _xhr.withCredentials = true;
6900
+ }
6901
+
6902
+ _xhr.addEventListener('load', function(e) {
6903
+ target.trigger(e);
6904
+ });
6905
+
6906
+ _xhr.addEventListener('error', function(e) {
6907
+ target.trigger(e);
6908
+ });
6909
+
6910
+ // additionally listen to progress events
6911
+ _xhr.addEventListener('progress', function(e) {
6912
+ target.trigger(e);
6913
+ });
6914
+
6915
+ _xhr.upload.addEventListener('progress', function(e) {
6916
+ target.trigger({
6917
+ type: 'UploadProgress',
6918
+ loaded: e.loaded,
6919
+ total: e.total
6920
+ });
6921
+ });
6922
+ // ... otherwise simulate XHR L2
6923
+ } else {
6924
+ _xhr.onreadystatechange = function onReadyStateChange() {
6925
+
6926
+ // fake Level 2 events
6927
+ switch (_xhr.readyState) {
6928
+
6929
+ case 1: // XMLHttpRequest.OPENED
6930
+ // readystatechanged is fired twice for OPENED state (in IE and Mozilla) - neu
6931
+ break;
6932
+
6933
+ // looks like HEADERS_RECEIVED (state 2) is not reported in Opera (or it's old versions) - neu
6934
+ case 2: // XMLHttpRequest.HEADERS_RECEIVED
6935
+ break;
6936
+
6937
+ case 3: // XMLHttpRequest.LOADING
6938
+ // try to fire progress event for not XHR L2
6939
+ var total, loaded;
6940
+
6941
+ try {
6942
+ if (Url.hasSameOrigin(meta.url)) { // Content-Length not accessible for cross-domain on some browsers
6943
+ total = _xhr.getResponseHeader('Content-Length') || 0; // old Safari throws an exception here
6944
+ }
6945
+
6946
+ if (_xhr.responseText) { // responseText was introduced in IE7
6947
+ loaded = _xhr.responseText.length;
6948
+ }
6949
+ } catch(ex) {
6950
+ total = loaded = 0;
6951
+ }
6952
+
6953
+ target.trigger({
6954
+ type: 'progress',
6955
+ lengthComputable: !!total,
6956
+ total: parseInt(total, 10),
6957
+ loaded: loaded
6958
+ });
6959
+ break;
6960
+
6961
+ case 4: // XMLHttpRequest.DONE
6962
+ // release readystatechange handler (mostly for IE)
6963
+ _xhr.onreadystatechange = function() {};
6964
+
6965
+ // usually status 0 is returned when server is unreachable, but FF also fails to status 0 for 408 timeout
6966
+ if (_xhr.status === 0) {
6967
+ target.trigger('error');
6968
+ } else {
6969
+ target.trigger('load');
6970
+ }
6971
+ break;
6972
+ }
6973
+ };
6974
+ }
6975
+
6976
+
6977
+ // set request headers
6978
+ if (!Basic.isEmptyObj(meta.headers)) {
6979
+ Basic.each(meta.headers, function(value, header) {
6980
+ _xhr.setRequestHeader(header, value);
6981
+ });
6982
+ }
6983
+
6984
+ // request response type
6985
+ if ("" !== meta.responseType && 'responseType' in _xhr) {
6986
+ if ('json' === meta.responseType && !Env.can('return_response_type', 'json')) { // we can fake this one
6987
+ _xhr.responseType = 'text';
6988
+ } else {
6989
+ _xhr.responseType = meta.responseType;
6990
+ }
6991
+ }
6992
+
6993
+ // send ...
6994
+ if (!mustSendAsBinary) {
6995
+ _xhr.send(data);
6996
+ } else {
6997
+ if (_xhr.sendAsBinary) { // Gecko
6998
+ _xhr.sendAsBinary(data);
6999
+ } else { // other browsers having support for typed arrays
7000
+ (function() {
7001
+ // mimic Gecko's sendAsBinary
7002
+ var ui8a = new Uint8Array(data.length);
7003
+ for (var i = 0; i < data.length; i++) {
7004
+ ui8a[i] = (data.charCodeAt(i) & 0xff);
7005
+ }
7006
+ _xhr.send(ui8a.buffer);
7007
+ }());
7008
+ }
7009
+ }
7010
+
7011
+ target.trigger('loadstart');
7012
+ },
7013
+
7014
+ getStatus: function() {
7015
+ // according to W3C spec it should return 0 for readyState < 3, but instead it throws an exception
7016
+ try {
7017
+ if (_xhr) {
7018
+ return _xhr.status;
7019
+ }
7020
+ } catch(ex) {}
7021
+ return 0;
7022
+ },
7023
+
7024
+ getResponse: function(responseType) {
7025
+ var I = this.getRuntime();
7026
+
7027
+ try {
7028
+ switch (responseType) {
7029
+ case 'blob':
7030
+ var file = new File(I.uid, _xhr.response);
7031
+
7032
+ // try to extract file name from content-disposition if possible (might be - not, if CORS for example)
7033
+ var disposition = _xhr.getResponseHeader('Content-Disposition');
7034
+ if (disposition) {
7035
+ // extract filename from response header if available
7036
+ var match = disposition.match(/filename=([\'\"'])([^\1]+)\1/);
7037
+ if (match) {
7038
+ _filename = match[2];
7039
+ }
7040
+ }
7041
+ file.name = _filename;
7042
+
7043
+ // pre-webkit Opera doesn't set type property on the blob response
7044
+ if (!file.type) {
7045
+ file.type = Mime.getFileMime(_filename);
7046
+ }
7047
+ return file;
7048
+
7049
+ case 'json':
7050
+ if (!Env.can('return_response_type', 'json')) {
7051
+ return _xhr.status === 200 && !!window.JSON ? JSON.parse(_xhr.responseText) : null;
7052
+ }
7053
+ return _xhr.response;
7054
+
7055
+ case 'document':
7056
+ return _getDocument(_xhr);
7057
+
7058
+ default:
7059
+ return _xhr.responseText !== '' ? _xhr.responseText : null; // against the specs, but for consistency across the runtimes
7060
+ }
7061
+ } catch(ex) {
7062
+ return null;
7063
+ }
7064
+ },
7065
+
7066
+ getAllResponseHeaders: function() {
7067
+ try {
7068
+ return _xhr.getAllResponseHeaders();
7069
+ } catch(ex) {}
7070
+ return '';
7071
+ },
7072
+
7073
+ abort: function() {
7074
+ if (_xhr) {
7075
+ _xhr.abort();
7076
+ }
7077
+ },
7078
+
7079
+ destroy: function() {
7080
+ self = _filename = null;
7081
+ }
7082
+ });
7083
+
7084
+
7085
+ // here we go... ugly fix for ugly bug
7086
+ function _preloadAndSend(meta, data) {
7087
+ var target = this, blob, fr;
7088
+
7089
+ // get original blob
7090
+ blob = data.getBlob().getSource();
7091
+
7092
+ // preload blob in memory to be sent as binary string
7093
+ fr = new window.FileReader();
7094
+ fr.onload = function() {
7095
+ // overwrite original blob
7096
+ data.append(data.getBlobName(), new Blob(null, {
7097
+ type: blob.type,
7098
+ data: fr.result
7099
+ }));
7100
+ // invoke send operation again
7101
+ self.send.call(target, meta, data);
7102
+ };
7103
+ fr.readAsBinaryString(blob);
7104
+ }
7105
+
7106
+
7107
+ function _getNativeXHR() {
7108
+ if (window.XMLHttpRequest && !(Env.browser === 'IE' && Env.version < 8)) { // IE7 has native XHR but it's buggy
7109
+ return new window.XMLHttpRequest();
7110
+ } else {
7111
+ return (function() {
7112
+ var progIDs = ['Msxml2.XMLHTTP.6.0', 'Microsoft.XMLHTTP']; // if 6.0 available, use it, otherwise failback to default 3.0
7113
+ for (var i = 0; i < progIDs.length; i++) {
7114
+ try {
7115
+ return new ActiveXObject(progIDs[i]);
7116
+ } catch (ex) {}
7117
+ }
7118
+ })();
7119
+ }
7120
+ }
7121
+
7122
+ // @credits Sergey Ilinsky (http://www.ilinsky.com/)
7123
+ function _getDocument(xhr) {
7124
+ var rXML = xhr.responseXML;
7125
+ var rText = xhr.responseText;
7126
+
7127
+ // Try parsing responseText (@see: http://www.ilinsky.com/articles/XMLHttpRequest/#bugs-ie-responseXML-content-type)
7128
+ if (Env.browser === 'IE' && rText && rXML && !rXML.documentElement && /[^\/]+\/[^\+]+\+xml/.test(xhr.getResponseHeader("Content-Type"))) {
7129
+ rXML = new window.ActiveXObject("Microsoft.XMLDOM");
7130
+ rXML.async = false;
7131
+ rXML.validateOnParse = false;
7132
+ rXML.loadXML(rText);
7133
+ }
7134
+
7135
+ // Check if there is no error in document
7136
+ if (rXML) {
7137
+ if ((Env.browser === 'IE' && rXML.parseError !== 0) || !rXML.documentElement || rXML.documentElement.tagName === "parsererror") {
7138
+ return null;
7139
+ }
7140
+ }
7141
+ return rXML;
7142
+ }
7143
+
7144
+
7145
+ function _prepareMultipart(fd) {
7146
+ var boundary = '----moxieboundary' + new Date().getTime()
7147
+ , dashdash = '--'
7148
+ , crlf = '\r\n'
7149
+ , multipart = ''
7150
+ , I = this.getRuntime()
7151
+ ;
7152
+
7153
+ if (!I.can('send_binary_string')) {
7154
+ throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
7155
+ }
7156
+
7157
+ _xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
7158
+
7159
+ // append multipart parameters
7160
+ fd.each(function(value, name) {
7161
+ // Firefox 3.6 failed to convert multibyte characters to UTF-8 in sendAsBinary(),
7162
+ // so we try it here ourselves with: unescape(encodeURIComponent(value))
7163
+ if (value instanceof Blob) {
7164
+ // Build RFC2388 blob
7165
+ multipart += dashdash + boundary + crlf +
7166
+ 'Content-Disposition: form-data; name="' + name + '"; filename="' + unescape(encodeURIComponent(value.name || 'blob')) + '"' + crlf +
7167
+ 'Content-Type: ' + (value.type || 'application/octet-stream') + crlf + crlf +
7168
+ value.getSource() + crlf;
7169
+ } else {
7170
+ multipart += dashdash + boundary + crlf +
7171
+ 'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf +
7172
+ unescape(encodeURIComponent(value)) + crlf;
7173
+ }
7174
+ });
7175
+
7176
+ multipart += dashdash + boundary + dashdash + crlf;
7177
+
7178
+ return multipart;
7179
+ }
7180
+ }
7181
+
7182
+ return (extensions.XMLHttpRequest = XMLHttpRequest);
7183
+ });
7184
+
7185
+ // Included from: src/javascript/runtime/html5/utils/BinaryReader.js
7186
+
7187
+ /**
7188
+ * BinaryReader.js
7189
+ *
7190
+ * Copyright 2013, Moxiecode Systems AB
7191
+ * Released under GPL License.
7192
+ *
7193
+ * License: http://www.plupload.com/license
7194
+ * Contributing: http://www.plupload.com/contributing
7195
+ */
7196
+
7197
+ /**
7198
+ @class moxie/runtime/html5/utils/BinaryReader
7199
+ @private
7200
+ */
7201
+ define("moxie/runtime/html5/utils/BinaryReader", [], function() {
7202
+ return function() {
7203
+ var II = false, bin;
7204
+
7205
+ // Private functions
7206
+ function read(idx, size) {
7207
+ var mv = II ? 0 : -8 * (size - 1), sum = 0, i;
7208
+
7209
+ for (i = 0; i < size; i++) {
7210
+ sum |= (bin.charCodeAt(idx + i) << Math.abs(mv + i*8));
7211
+ }
7212
+
7213
+ return sum;
7214
+ }
7215
+
7216
+ function putstr(segment, idx, length) {
7217
+ length = arguments.length === 3 ? length : bin.length - idx - 1;
7218
+ bin = bin.substr(0, idx) + segment + bin.substr(length + idx);
7219
+ }
7220
+
7221
+ function write(idx, num, size) {
7222
+ var str = '', mv = II ? 0 : -8 * (size - 1), i;
7223
+
7224
+ for (i = 0; i < size; i++) {
7225
+ str += String.fromCharCode((num >> Math.abs(mv + i*8)) & 255);
7226
+ }
7227
+
7228
+ putstr(str, idx, size);
7229
+ }
7230
+
7231
+ // Public functions
7232
+ return {
7233
+ II: function(order) {
7234
+ if (order === undefined) {
7235
+ return II;
7236
+ } else {
7237
+ II = order;
7238
+ }
7239
+ },
7240
+
7241
+ init: function(binData) {
7242
+ II = false;
7243
+ bin = binData;
7244
+ },
7245
+
7246
+ SEGMENT: function(idx, length, segment) {
7247
+ switch (arguments.length) {
7248
+ case 1:
7249
+ return bin.substr(idx, bin.length - idx - 1);
7250
+ case 2:
7251
+ return bin.substr(idx, length);
7252
+ case 3:
7253
+ putstr(segment, idx, length);
7254
+ break;
7255
+ default: return bin;
7256
+ }
7257
+ },
7258
+
7259
+ BYTE: function(idx) {
7260
+ return read(idx, 1);
7261
+ },
7262
+
7263
+ SHORT: function(idx) {
7264
+ return read(idx, 2);
7265
+ },
7266
+
7267
+ LONG: function(idx, num) {
7268
+ if (num === undefined) {
7269
+ return read(idx, 4);
7270
+ } else {
7271
+ write(idx, num, 4);
7272
+ }
7273
+ },
7274
+
7275
+ SLONG: function(idx) { // 2's complement notation
7276
+ var num = read(idx, 4);
7277
+
7278
+ return (num > 2147483647 ? num - 4294967296 : num);
7279
+ },
7280
+
7281
+ STRING: function(idx, size) {
7282
+ var str = '';
7283
+
7284
+ for (size += idx; idx < size; idx++) {
7285
+ str += String.fromCharCode(read(idx, 1));
7286
+ }
7287
+
7288
+ return str;
7289
+ }
7290
+ };
7291
+ };
7292
+ });
7293
+
7294
+ // Included from: src/javascript/runtime/html5/image/JPEGHeaders.js
7295
+
7296
+ /**
7297
+ * JPEGHeaders.js
7298
+ *
7299
+ * Copyright 2013, Moxiecode Systems AB
7300
+ * Released under GPL License.
7301
+ *
7302
+ * License: http://www.plupload.com/license
7303
+ * Contributing: http://www.plupload.com/contributing
7304
+ */
7305
+
7306
+ /**
7307
+ @class moxie/runtime/html5/image/JPEGHeaders
7308
+ @private
7309
+ */
7310
+ define("moxie/runtime/html5/image/JPEGHeaders", [
7311
+ "moxie/runtime/html5/utils/BinaryReader"
7312
+ ], function(BinaryReader) {
7313
+
7314
+ return function JPEGHeaders(data) {
7315
+ var headers = [], read, idx, marker, length = 0;
7316
+
7317
+ read = new BinaryReader();
7318
+ read.init(data);
7319
+
7320
+ // Check if data is jpeg
7321
+ if (read.SHORT(0) !== 0xFFD8) {
7322
+ return;
7323
+ }
7324
+
7325
+ idx = 2;
7326
+
7327
+ while (idx <= data.length) {
7328
+ marker = read.SHORT(idx);
7329
+
7330
+ // omit RST (restart) markers
7331
+ if (marker >= 0xFFD0 && marker <= 0xFFD7) {
7332
+ idx += 2;
7333
+ continue;
7334
+ }
7335
+
7336
+ // no headers allowed after SOS marker
7337
+ if (marker === 0xFFDA || marker === 0xFFD9) {
7338
+ break;
7339
+ }
7340
+
7341
+ length = read.SHORT(idx + 2) + 2;
7342
+
7343
+ // APPn marker detected
7344
+ if (marker >= 0xFFE1 && marker <= 0xFFEF) {
7345
+ headers.push({
7346
+ hex: marker,
7347
+ name: 'APP' + (marker & 0x000F),
7348
+ start: idx,
7349
+ length: length,
7350
+ segment: read.SEGMENT(idx, length)
7351
+ });
7352
+ }
7353
+
7354
+ idx += length;
7355
+ }
7356
+
7357
+ read.init(null); // free memory
7358
+
7359
+ return {
7360
+ headers: headers,
7361
+
7362
+ restore: function(data) {
7363
+ var max, i;
7364
+
7365
+ read.init(data);
7366
+
7367
+ idx = read.SHORT(2) == 0xFFE0 ? 4 + read.SHORT(4) : 2;
7368
+
7369
+ for (i = 0, max = headers.length; i < max; i++) {
7370
+ read.SEGMENT(idx, 0, headers[i].segment);
7371
+ idx += headers[i].length;
7372
+ }
7373
+
7374
+ data = read.SEGMENT();
7375
+ read.init(null);
7376
+ return data;
7377
+ },
7378
+
7379
+ strip: function(data) {
7380
+ var headers, jpegHeaders, i;
7381
+
7382
+ jpegHeaders = new JPEGHeaders(data);
7383
+ headers = jpegHeaders.headers;
7384
+ jpegHeaders.purge();
7385
+
7386
+ read.init(data);
7387
+
7388
+ i = headers.length;
7389
+ while (i--) {
7390
+ read.SEGMENT(headers[i].start, headers[i].length, '');
7391
+ }
7392
+
7393
+ data = read.SEGMENT();
7394
+ read.init(null);
7395
+ return data;
7396
+ },
7397
+
7398
+ get: function(name) {
7399
+ var array = [];
7400
+
7401
+ for (var i = 0, max = headers.length; i < max; i++) {
7402
+ if (headers[i].name === name.toUpperCase()) {
7403
+ array.push(headers[i].segment);
7404
+ }
7405
+ }
7406
+ return array;
7407
+ },
7408
+
7409
+ set: function(name, segment) {
7410
+ var array = [], i, ii, max;
7411
+
7412
+ if (typeof(segment) === 'string') {
7413
+ array.push(segment);
7414
+ } else {
7415
+ array = segment;
7416
+ }
7417
+
7418
+ for (i = ii = 0, max = headers.length; i < max; i++) {
7419
+ if (headers[i].name === name.toUpperCase()) {
7420
+ headers[i].segment = array[ii];
7421
+ headers[i].length = array[ii].length;
7422
+ ii++;
7423
+ }
7424
+ if (ii >= array.length) {
7425
+ break;
7426
+ }
7427
+ }
7428
+ },
7429
+
7430
+ purge: function() {
7431
+ headers = [];
7432
+ read.init(null);
7433
+ read = null;
7434
+ }
7435
+ };
7436
+ };
7437
+ });
7438
+
7439
+ // Included from: src/javascript/runtime/html5/image/ExifParser.js
7440
+
7441
+ /**
7442
+ * ExifParser.js
7443
+ *
7444
+ * Copyright 2013, Moxiecode Systems AB
7445
+ * Released under GPL License.
7446
+ *
7447
+ * License: http://www.plupload.com/license
7448
+ * Contributing: http://www.plupload.com/contributing
7449
+ */
7450
+
7451
+ /**
7452
+ @class moxie/runtime/html5/image/ExifParser
7453
+ @private
7454
+ */
7455
+ define("moxie/runtime/html5/image/ExifParser", [
7456
+ "moxie/core/utils/Basic",
7457
+ "moxie/runtime/html5/utils/BinaryReader"
7458
+ ], function(Basic, BinaryReader) {
7459
+
7460
+ return function ExifParser() {
7461
+ // Private ExifParser fields
7462
+ var data, tags, Tiff, offsets = {}, tagDescs;
7463
+
7464
+ data = new BinaryReader();
7465
+
7466
+ tags = {
7467
+ tiff : {
7468
+ /*
7469
+ The image orientation viewed in terms of rows and columns.
7470
+
7471
+ 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
7472
+ 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
7473
+ 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
7474
+ 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
7475
+ 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
7476
+ 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
7477
+ 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
7478
+ 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
7479
+ */
7480
+ 0x0112: 'Orientation',
7481
+ 0x010E: 'ImageDescription',
7482
+ 0x010F: 'Make',
7483
+ 0x0110: 'Model',
7484
+ 0x0131: 'Software',
7485
+ 0x8769: 'ExifIFDPointer',
7486
+ 0x8825: 'GPSInfoIFDPointer'
7487
+ },
7488
+ exif : {
7489
+ 0x9000: 'ExifVersion',
7490
+ 0xA001: 'ColorSpace',
7491
+ 0xA002: 'PixelXDimension',
7492
+ 0xA003: 'PixelYDimension',
7493
+ 0x9003: 'DateTimeOriginal',
7494
+ 0x829A: 'ExposureTime',
7495
+ 0x829D: 'FNumber',
7496
+ 0x8827: 'ISOSpeedRatings',
7497
+ 0x9201: 'ShutterSpeedValue',
7498
+ 0x9202: 'ApertureValue' ,
7499
+ 0x9207: 'MeteringMode',
7500
+ 0x9208: 'LightSource',
7501
+ 0x9209: 'Flash',
7502
+ 0x920A: 'FocalLength',
7503
+ 0xA402: 'ExposureMode',
7504
+ 0xA403: 'WhiteBalance',
7505
+ 0xA406: 'SceneCaptureType',
7506
+ 0xA404: 'DigitalZoomRatio',
7507
+ 0xA408: 'Contrast',
7508
+ 0xA409: 'Saturation',
7509
+ 0xA40A: 'Sharpness'
7510
+ },
7511
+ gps : {
7512
+ 0x0000: 'GPSVersionID',
7513
+ 0x0001: 'GPSLatitudeRef',
7514
+ 0x0002: 'GPSLatitude',
7515
+ 0x0003: 'GPSLongitudeRef',
7516
+ 0x0004: 'GPSLongitude'
7517
+ }
7518
+ };
7519
+
7520
+ tagDescs = {
7521
+ 'ColorSpace': {
7522
+ 1: 'sRGB',
7523
+ 0: 'Uncalibrated'
7524
+ },
7525
+
7526
+ 'MeteringMode': {
7527
+ 0: 'Unknown',
7528
+ 1: 'Average',
7529
+ 2: 'CenterWeightedAverage',
7530
+ 3: 'Spot',
7531
+ 4: 'MultiSpot',
7532
+ 5: 'Pattern',
7533
+ 6: 'Partial',
7534
+ 255: 'Other'
7535
+ },
7536
+
7537
+ 'LightSource': {
7538
+ 1: 'Daylight',
7539
+ 2: 'Fliorescent',
7540
+ 3: 'Tungsten',
7541
+ 4: 'Flash',
7542
+ 9: 'Fine weather',
7543
+ 10: 'Cloudy weather',
7544
+ 11: 'Shade',
7545
+ 12: 'Daylight fluorescent (D 5700 - 7100K)',
7546
+ 13: 'Day white fluorescent (N 4600 -5400K)',
7547
+ 14: 'Cool white fluorescent (W 3900 - 4500K)',
7548
+ 15: 'White fluorescent (WW 3200 - 3700K)',
7549
+ 17: 'Standard light A',
7550
+ 18: 'Standard light B',
7551
+ 19: 'Standard light C',
7552
+ 20: 'D55',
7553
+ 21: 'D65',
7554
+ 22: 'D75',
7555
+ 23: 'D50',
7556
+ 24: 'ISO studio tungsten',
7557
+ 255: 'Other'
7558
+ },
7559
+
7560
+ 'Flash': {
7561
+ 0x0000: 'Flash did not fire.',
7562
+ 0x0001: 'Flash fired.',
7563
+ 0x0005: 'Strobe return light not detected.',
7564
+ 0x0007: 'Strobe return light detected.',
7565
+ 0x0009: 'Flash fired, compulsory flash mode',
7566
+ 0x000D: 'Flash fired, compulsory flash mode, return light not detected',
7567
+ 0x000F: 'Flash fired, compulsory flash mode, return light detected',
7568
+ 0x0010: 'Flash did not fire, compulsory flash mode',
7569
+ 0x0018: 'Flash did not fire, auto mode',
7570
+ 0x0019: 'Flash fired, auto mode',
7571
+ 0x001D: 'Flash fired, auto mode, return light not detected',
7572
+ 0x001F: 'Flash fired, auto mode, return light detected',
7573
+ 0x0020: 'No flash function',
7574
+ 0x0041: 'Flash fired, red-eye reduction mode',
7575
+ 0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
7576
+ 0x0047: 'Flash fired, red-eye reduction mode, return light detected',
7577
+ 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
7578
+ 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
7579
+ 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
7580
+ 0x0059: 'Flash fired, auto mode, red-eye reduction mode',
7581
+ 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
7582
+ 0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
7583
+ },
7584
+
7585
+ 'ExposureMode': {
7586
+ 0: 'Auto exposure',
7587
+ 1: 'Manual exposure',
7588
+ 2: 'Auto bracket'
7589
+ },
7590
+
7591
+ 'WhiteBalance': {
7592
+ 0: 'Auto white balance',
7593
+ 1: 'Manual white balance'
7594
+ },
7595
+
7596
+ 'SceneCaptureType': {
7597
+ 0: 'Standard',
7598
+ 1: 'Landscape',
7599
+ 2: 'Portrait',
7600
+ 3: 'Night scene'
7601
+ },
7602
+
7603
+ 'Contrast': {
7604
+ 0: 'Normal',
7605
+ 1: 'Soft',
7606
+ 2: 'Hard'
7607
+ },
7608
+
7609
+ 'Saturation': {
7610
+ 0: 'Normal',
7611
+ 1: 'Low saturation',
7612
+ 2: 'High saturation'
7613
+ },
7614
+
7615
+ 'Sharpness': {
7616
+ 0: 'Normal',
7617
+ 1: 'Soft',
7618
+ 2: 'Hard'
7619
+ },
7620
+
7621
+ // GPS related
7622
+ 'GPSLatitudeRef': {
7623
+ N: 'North latitude',
7624
+ S: 'South latitude'
7625
+ },
7626
+
7627
+ 'GPSLongitudeRef': {
7628
+ E: 'East longitude',
7629
+ W: 'West longitude'
7630
+ }
7631
+ };
7632
+
7633
+ function extractTags(IFD_offset, tags2extract) {
7634
+ var length = data.SHORT(IFD_offset), i, ii,
7635
+ tag, type, count, tagOffset, offset, value, values = [], hash = {};
7636
+
7637
+ for (i = 0; i < length; i++) {
7638
+ // Set binary reader pointer to beginning of the next tag
7639
+ offset = tagOffset = IFD_offset + 12 * i + 2;
7640
+
7641
+ tag = tags2extract[data.SHORT(offset)];
7642
+
7643
+ if (tag === undefined) {
7644
+ continue; // Not the tag we requested
7645
+ }
7646
+
7647
+ type = data.SHORT(offset+=2);
7648
+ count = data.LONG(offset+=2);
7649
+
7650
+ offset += 4;
7651
+ values = [];
7652
+
7653
+ switch (type) {
7654
+ case 1: // BYTE
7655
+ case 7: // UNDEFINED
7656
+ if (count > 4) {
7657
+ offset = data.LONG(offset) + offsets.tiffHeader;
7658
+ }
7659
+
7660
+ for (ii = 0; ii < count; ii++) {
7661
+ values[ii] = data.BYTE(offset + ii);
7662
+ }
7663
+
7664
+ break;
7665
+
7666
+ case 2: // STRING
7667
+ if (count > 4) {
7668
+ offset = data.LONG(offset) + offsets.tiffHeader;
7669
+ }
7670
+
7671
+ hash[tag] = data.STRING(offset, count - 1);
7672
+
7673
+ continue;
7674
+
7675
+ case 3: // SHORT
7676
+ if (count > 2) {
7677
+ offset = data.LONG(offset) + offsets.tiffHeader;
7678
+ }
7679
+
7680
+ for (ii = 0; ii < count; ii++) {
7681
+ values[ii] = data.SHORT(offset + ii*2);
7682
+ }
7683
+
7684
+ break;
7685
+
7686
+ case 4: // LONG
7687
+ if (count > 1) {
7688
+ offset = data.LONG(offset) + offsets.tiffHeader;
7689
+ }
7690
+
7691
+ for (ii = 0; ii < count; ii++) {
7692
+ values[ii] = data.LONG(offset + ii*4);
7693
+ }
7694
+
7695
+ break;
7696
+
7697
+ case 5: // RATIONAL
7698
+ offset = data.LONG(offset) + offsets.tiffHeader;
7699
+
7700
+ for (ii = 0; ii < count; ii++) {
7701
+ values[ii] = data.LONG(offset + ii*4) / data.LONG(offset + ii*4 + 4);
7702
+ }
7703
+
7704
+ break;
7705
+
7706
+ case 9: // SLONG
7707
+ offset = data.LONG(offset) + offsets.tiffHeader;
7708
+
7709
+ for (ii = 0; ii < count; ii++) {
7710
+ values[ii] = data.SLONG(offset + ii*4);
7711
+ }
7712
+
7713
+ break;
7714
+
7715
+ case 10: // SRATIONAL
7716
+ offset = data.LONG(offset) + offsets.tiffHeader;
7717
+
7718
+ for (ii = 0; ii < count; ii++) {
7719
+ values[ii] = data.SLONG(offset + ii*4) / data.SLONG(offset + ii*4 + 4);
7720
+ }
7721
+
7722
+ break;
7723
+
7724
+ default:
7725
+ continue;
7726
+ }
7727
+
7728
+ value = (count == 1 ? values[0] : values);
7729
+
7730
+ if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') {
7731
+ hash[tag] = tagDescs[tag][value];
7732
+ } else {
7733
+ hash[tag] = value;
7734
+ }
7735
+ }
7736
+
7737
+ return hash;
7738
+ }
7739
+
7740
+ function getIFDOffsets() {
7741
+ var idx = offsets.tiffHeader;
7742
+
7743
+ // Set read order of multi-byte data
7744
+ data.II(data.SHORT(idx) == 0x4949);
7745
+
7746
+ // Check if always present bytes are indeed present
7747
+ if (data.SHORT(idx+=2) !== 0x002A) {
7748
+ return false;
7749
+ }
7750
+
7751
+ offsets.IFD0 = offsets.tiffHeader + data.LONG(idx += 2);
7752
+ Tiff = extractTags(offsets.IFD0, tags.tiff);
7753
+
7754
+ if ('ExifIFDPointer' in Tiff) {
7755
+ offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer;
7756
+ delete Tiff.ExifIFDPointer;
7757
+ }
7758
+
7759
+ if ('GPSInfoIFDPointer' in Tiff) {
7760
+ offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer;
7761
+ delete Tiff.GPSInfoIFDPointer;
7762
+ }
7763
+ return true;
7764
+ }
7765
+
7766
+ // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported
7767
+ function setTag(ifd, tag, value) {
7768
+ var offset, length, tagOffset, valueOffset = 0;
7769
+
7770
+ // If tag name passed translate into hex key
7771
+ if (typeof(tag) === 'string') {
7772
+ var tmpTags = tags[ifd.toLowerCase()];
7773
+ for (var hex in tmpTags) {
7774
+ if (tmpTags[hex] === tag) {
7775
+ tag = hex;
7776
+ break;
7777
+ }
7778
+ }
7779
+ }
7780
+ offset = offsets[ifd.toLowerCase() + 'IFD'];
7781
+ length = data.SHORT(offset);
7782
+
7783
+ for (var i = 0; i < length; i++) {
7784
+ tagOffset = offset + 12 * i + 2;
7785
+
7786
+ if (data.SHORT(tagOffset) == tag) {
7787
+ valueOffset = tagOffset + 8;
7788
+ break;
7789
+ }
7790
+ }
7791
+
7792
+ if (!valueOffset) {
7793
+ return false;
7794
+ }
7795
+
7796
+ data.LONG(valueOffset, value);
7797
+ return true;
7798
+ }
7799
+
7800
+
7801
+ // Public functions
7802
+ return {
7803
+ init: function(segment) {
7804
+ // Reset internal data
7805
+ offsets = {
7806
+ tiffHeader: 10
7807
+ };
7808
+
7809
+ if (segment === undefined || !segment.length) {
7810
+ return false;
7811
+ }
7812
+
7813
+ data.init(segment);
7814
+
7815
+ // Check if that's APP1 and that it has EXIF
7816
+ if (data.SHORT(0) === 0xFFE1 && data.STRING(4, 5).toUpperCase() === "EXIF\0") {
7817
+ return getIFDOffsets();
7818
+ }
7819
+ return false;
7820
+ },
7821
+
7822
+ TIFF: function() {
7823
+ return Tiff;
7824
+ },
7825
+
7826
+ EXIF: function() {
7827
+ var Exif;
7828
+
7829
+ // Populate EXIF hash
7830
+ Exif = extractTags(offsets.exifIFD, tags.exif);
7831
+
7832
+ // Fix formatting of some tags
7833
+ if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') {
7834
+ for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) {
7835
+ exifVersion += String.fromCharCode(Exif.ExifVersion[i]);
7836
+ }
7837
+ Exif.ExifVersion = exifVersion;
7838
+ }
7839
+
7840
+ return Exif;
7841
+ },
7842
+
7843
+ GPS: function() {
7844
+ var GPS;
7845
+
7846
+ GPS = extractTags(offsets.gpsIFD, tags.gps);
7847
+
7848
+ // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..)
7849
+ if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') {
7850
+ GPS.GPSVersionID = GPS.GPSVersionID.join('.');
7851
+ }
7852
+
7853
+ return GPS;
7854
+ },
7855
+
7856
+ setExif: function(tag, value) {
7857
+ // Right now only setting of width/height is possible
7858
+ if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') {return false;}
7859
+
7860
+ return setTag('exif', tag, value);
7861
+ },
7862
+
7863
+
7864
+ getBinary: function() {
7865
+ return data.SEGMENT();
7866
+ },
7867
+
7868
+ purge: function() {
7869
+ data.init(null);
7870
+ data = Tiff = null;
7871
+ offsets = {};
7872
+ }
7873
+ };
7874
+ };
7875
+ });
7876
+
7877
+ // Included from: src/javascript/runtime/html5/image/JPEG.js
7878
+
7879
+ /**
7880
+ * JPEG.js
7881
+ *
7882
+ * Copyright 2013, Moxiecode Systems AB
7883
+ * Released under GPL License.
7884
+ *
7885
+ * License: http://www.plupload.com/license
7886
+ * Contributing: http://www.plupload.com/contributing
7887
+ */
7888
+
7889
+ /**
7890
+ @class moxie/runtime/html5/image/JPEG
7891
+ @private
7892
+ */
7893
+ define("moxie/runtime/html5/image/JPEG", [
7894
+ "moxie/core/utils/Basic",
7895
+ "moxie/core/Exceptions",
7896
+ "moxie/runtime/html5/image/JPEGHeaders",
7897
+ "moxie/runtime/html5/utils/BinaryReader",
7898
+ "moxie/runtime/html5/image/ExifParser"
7899
+ ], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) {
7900
+
7901
+ function JPEG(binstr) {
7902
+ var _binstr, _br, _hm, _ep, _info, hasExif;
7903
+
7904
+ function _getDimensions() {
7905
+ var idx = 0, marker, length;
7906
+
7907
+ // examine all through the end, since some images might have very large APP segments
7908
+ while (idx <= _binstr.length) {
7909
+ marker = _br.SHORT(idx += 2);
7910
+
7911
+ if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn
7912
+ idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte)
7913
+ return {
7914
+ height: _br.SHORT(idx),
7915
+ width: _br.SHORT(idx += 2)
7916
+ };
7917
+ }
7918
+ length = _br.SHORT(idx += 2);
7919
+ idx += length - 2;
7920
+ }
7921
+ return null;
7922
+ }
7923
+
7924
+ _binstr = binstr;
7925
+
7926
+ _br = new BinaryReader();
7927
+ _br.init(_binstr);
7928
+
7929
+ // check if it is jpeg
7930
+ if (_br.SHORT(0) !== 0xFFD8) {
7931
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
7932
+ }
7933
+
7934
+ // backup headers
7935
+ _hm = new JPEGHeaders(binstr);
7936
+
7937
+ // extract exif info
7938
+ _ep = new ExifParser();
7939
+ hasExif = !!_ep.init(_hm.get('app1')[0]);
7940
+
7941
+ // get dimensions
7942
+ _info = _getDimensions.call(this);
7943
+
7944
+ Basic.extend(this, {
7945
+ type: 'image/jpeg',
7946
+
7947
+ size: _binstr.length,
7948
+
7949
+ width: _info && _info.width || 0,
7950
+
7951
+ height: _info && _info.height || 0,
7952
+
7953
+ setExif: function(tag, value) {
7954
+ if (!hasExif) {
7955
+ return false; // or throw an exception
7956
+ }
7957
+
7958
+ if (Basic.typeOf(tag) === 'object') {
7959
+ Basic.each(tag, function(value, tag) {
7960
+ _ep.setExif(tag, value);
7961
+ });
7962
+ } else {
7963
+ _ep.setExif(tag, value);
7964
+ }
7965
+
7966
+ // update internal headers
7967
+ _hm.set('app1', _ep.getBinary());
7968
+ },
7969
+
7970
+ writeHeaders: function() {
7971
+ if (!arguments.length) {
7972
+ // if no arguments passed, update headers internally
7973
+ return (_binstr = _hm.restore(_binstr));
7974
+ }
7975
+ return _hm.restore(arguments[0]);
7976
+ },
7977
+
7978
+ stripHeaders: function(binstr) {
7979
+ return _hm.strip(binstr);
7980
+ },
7981
+
7982
+ purge: function() {
7983
+ _purge.call(this);
7984
+ }
7985
+ });
7986
+
7987
+ if (hasExif) {
7988
+ this.meta = {
7989
+ tiff: _ep.TIFF(),
7990
+ exif: _ep.EXIF(),
7991
+ gps: _ep.GPS()
7992
+ };
7993
+ }
7994
+
7995
+ function _purge() {
7996
+ if (!_ep || !_hm || !_br) {
7997
+ return; // ignore any repeating purge requests
7998
+ }
7999
+ _ep.purge();
8000
+ _hm.purge();
8001
+ _br.init(null);
8002
+ _binstr = _info = _hm = _ep = _br = null;
8003
+ }
8004
+ }
8005
+
8006
+ return JPEG;
8007
+ });
8008
+
8009
+ // Included from: src/javascript/runtime/html5/image/PNG.js
8010
+
8011
+ /**
8012
+ * PNG.js
8013
+ *
8014
+ * Copyright 2013, Moxiecode Systems AB
8015
+ * Released under GPL License.
8016
+ *
8017
+ * License: http://www.plupload.com/license
8018
+ * Contributing: http://www.plupload.com/contributing
8019
+ */
8020
+
8021
+ /**
8022
+ @class moxie/runtime/html5/image/PNG
8023
+ @private
8024
+ */
8025
+ define("moxie/runtime/html5/image/PNG", [
8026
+ "moxie/core/Exceptions",
8027
+ "moxie/core/utils/Basic",
8028
+ "moxie/runtime/html5/utils/BinaryReader"
8029
+ ], function(x, Basic, BinaryReader) {
8030
+
8031
+ function PNG(binstr) {
8032
+ var _binstr, _br, _hm, _ep, _info;
8033
+
8034
+ _binstr = binstr;
8035
+
8036
+ _br = new BinaryReader();
8037
+ _br.init(_binstr);
8038
+
8039
+ // check if it's png
8040
+ (function() {
8041
+ var idx = 0, i = 0
8042
+ , signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A]
8043
+ ;
8044
+
8045
+ for (i = 0; i < signature.length; i++, idx += 2) {
8046
+ if (signature[i] != _br.SHORT(idx)) {
8047
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
8048
+ }
8049
+ }
8050
+ }());
8051
+
8052
+ function _getDimensions() {
8053
+ var chunk, idx;
8054
+
8055
+ chunk = _getChunkAt.call(this, 8);
8056
+
8057
+ if (chunk.type == 'IHDR') {
8058
+ idx = chunk.start;
8059
+ return {
8060
+ width: _br.LONG(idx),
8061
+ height: _br.LONG(idx += 4)
8062
+ };
8063
+ }
8064
+ return null;
8065
+ }
8066
+
8067
+ function _purge() {
8068
+ if (!_br) {
8069
+ return; // ignore any repeating purge requests
8070
+ }
8071
+ _br.init(null);
8072
+ _binstr = _info = _hm = _ep = _br = null;
8073
+ }
8074
+
8075
+ _info = _getDimensions.call(this);
8076
+
8077
+ Basic.extend(this, {
8078
+ type: 'image/png',
8079
+
8080
+ size: _binstr.length,
8081
+
8082
+ width: _info.width,
8083
+
8084
+ height: _info.height,
8085
+
8086
+ purge: function() {
8087
+ _purge.call(this);
8088
+ }
8089
+ });
8090
+
8091
+ // for PNG we can safely trigger purge automatically, as we do not keep any data for later
8092
+ _purge.call(this);
8093
+
8094
+ function _getChunkAt(idx) {
8095
+ var length, type, start, CRC;
8096
+
8097
+ length = _br.LONG(idx);
8098
+ type = _br.STRING(idx += 4, 4);
8099
+ start = idx += 4;
8100
+ CRC = _br.LONG(idx + length);
8101
+
8102
+ return {
8103
+ length: length,
8104
+ type: type,
8105
+ start: start,
8106
+ CRC: CRC
8107
+ };
8108
+ }
8109
+ }
8110
+
8111
+ return PNG;
8112
+ });
8113
+
8114
+ // Included from: src/javascript/runtime/html5/image/ImageInfo.js
8115
+
8116
+ /**
8117
+ * ImageInfo.js
8118
+ *
8119
+ * Copyright 2013, Moxiecode Systems AB
8120
+ * Released under GPL License.
8121
+ *
8122
+ * License: http://www.plupload.com/license
8123
+ * Contributing: http://www.plupload.com/contributing
8124
+ */
8125
+
8126
+ /**
8127
+ @class moxie/runtime/html5/image/ImageInfo
8128
+ @private
8129
+ */
8130
+ define("moxie/runtime/html5/image/ImageInfo", [
8131
+ "moxie/core/utils/Basic",
8132
+ "moxie/core/Exceptions",
8133
+ "moxie/runtime/html5/image/JPEG",
8134
+ "moxie/runtime/html5/image/PNG"
8135
+ ], function(Basic, x, JPEG, PNG) {
8136
+ /**
8137
+ Optional image investigation tool for HTML5 runtime. Provides the following features:
8138
+ - ability to distinguish image type (JPEG or PNG) by signature
8139
+ - ability to extract image width/height directly from it's internals, without preloading in memory (fast)
8140
+ - ability to extract APP headers from JPEGs (Exif, GPS, etc)
8141
+ - ability to replace width/height tags in extracted JPEG headers
8142
+ - ability to restore APP headers, that were for example stripped during image manipulation
8143
+
8144
+ @class ImageInfo
8145
+ @constructor
8146
+ @param {String} binstr Image source as binary string
8147
+ */
8148
+ return function(binstr) {
8149
+ var _cs = [JPEG, PNG], _img;
8150
+
8151
+ // figure out the format, throw: ImageError.WRONG_FORMAT if not supported
8152
+ _img = (function() {
8153
+ for (var i = 0; i < _cs.length; i++) {
8154
+ try {
8155
+ return new _cs[i](binstr);
8156
+ } catch (ex) {
8157
+ // console.info(ex);
8158
+ }
8159
+ }
8160
+ throw new x.ImageError(x.ImageError.WRONG_FORMAT);
8161
+ }());
8162
+
8163
+ Basic.extend(this, {
8164
+ /**
8165
+ Image Mime Type extracted from it's depths
8166
+
8167
+ @property type
8168
+ @type {String}
8169
+ @default ''
8170
+ */
8171
+ type: '',
8172
+
8173
+ /**
8174
+ Image size in bytes
8175
+
8176
+ @property size
8177
+ @type {Number}
8178
+ @default 0
8179
+ */
8180
+ size: 0,
8181
+
8182
+ /**
8183
+ Image width extracted from image source
8184
+
8185
+ @property width
8186
+ @type {Number}
8187
+ @default 0
8188
+ */
8189
+ width: 0,
8190
+
8191
+ /**
8192
+ Image height extracted from image source
8193
+
8194
+ @property height
8195
+ @type {Number}
8196
+ @default 0
8197
+ */
8198
+ height: 0,
8199
+
8200
+ /**
8201
+ Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs.
8202
+
8203
+ @method setExif
8204
+ @param {String} tag Tag to set
8205
+ @param {Mixed} value Value to assign to the tag
8206
+ */
8207
+ setExif: function() {},
8208
+
8209
+ /**
8210
+ Restores headers to the source.
8211
+
8212
+ @method writeHeaders
8213
+ @param {String} data Image source as binary string
8214
+ @return {String} Updated binary string
8215
+ */
8216
+ writeHeaders: function(data) {
8217
+ return data;
8218
+ },
8219
+
8220
+ /**
8221
+ Strip all headers from the source.
8222
+
8223
+ @method stripHeaders
8224
+ @param {String} data Image source as binary string
8225
+ @return {String} Updated binary string
8226
+ */
8227
+ stripHeaders: function(data) {
8228
+ return data;
8229
+ },
8230
+
8231
+ /**
8232
+ Dispose resources.
8233
+
8234
+ @method purge
8235
+ */
8236
+ purge: function() {}
8237
+ });
8238
+
8239
+ Basic.extend(this, _img);
8240
+
8241
+ this.purge = function() {
8242
+ _img.purge();
8243
+ _img = null;
8244
+ };
8245
+ };
8246
+ });
8247
+
8248
+ // Included from: src/javascript/runtime/html5/image/MegaPixel.js
8249
+
8250
+ /**
8251
+ (The MIT License)
8252
+
8253
+ Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>;
8254
+
8255
+ Permission is hereby granted, free of charge, to any person obtaining
8256
+ a copy of this software and associated documentation files (the
8257
+ 'Software'), to deal in the Software without restriction, including
8258
+ without limitation the rights to use, copy, modify, merge, publish,
8259
+ distribute, sublicense, and/or sell copies of the Software, and to
8260
+ permit persons to whom the Software is furnished to do so, subject to
8261
+ the following conditions:
8262
+
8263
+ The above copyright notice and this permission notice shall be
8264
+ included in all copies or substantial portions of the Software.
8265
+
8266
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
8267
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
8268
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
8269
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
8270
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
8271
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
8272
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8273
+ */
8274
+
8275
+ /**
8276
+ * Mega pixel image rendering library for iOS6 Safari
8277
+ *
8278
+ * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel),
8279
+ * which causes unexpected subsampling when drawing it in canvas.
8280
+ * By using this library, you can safely render the image with proper stretching.
8281
+ *
8282
+ * Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com>
8283
+ * Released under the MIT license
8284
+ */
8285
+
8286
+ /**
8287
+ @class moxie/runtime/html5/image/MegaPixel
8288
+ @private
8289
+ */
8290
+ define("moxie/runtime/html5/image/MegaPixel", [], function() {
8291
+
8292
+ /**
8293
+ * Rendering image element (with resizing) into the canvas element
8294
+ */
8295
+ function renderImageToCanvas(img, canvas, options) {
8296
+ var iw = img.naturalWidth, ih = img.naturalHeight;
8297
+ var width = options.width, height = options.height;
8298
+ var x = options.x || 0, y = options.y || 0;
8299
+ var ctx = canvas.getContext('2d');
8300
+ if (detectSubsampling(img)) {
8301
+ iw /= 2;
8302
+ ih /= 2;
8303
+ }
8304
+ var d = 1024; // size of tiling canvas
8305
+ var tmpCanvas = document.createElement('canvas');
8306
+ tmpCanvas.width = tmpCanvas.height = d;
8307
+ var tmpCtx = tmpCanvas.getContext('2d');
8308
+ var vertSquashRatio = detectVerticalSquash(img, iw, ih);
8309
+ var sy = 0;
8310
+ while (sy < ih) {
8311
+ var sh = sy + d > ih ? ih - sy : d;
8312
+ var sx = 0;
8313
+ while (sx < iw) {
8314
+ var sw = sx + d > iw ? iw - sx : d;
8315
+ tmpCtx.clearRect(0, 0, d, d);
8316
+ tmpCtx.drawImage(img, -sx, -sy);
8317
+ var dx = (sx * width / iw + x) << 0;
8318
+ var dw = Math.ceil(sw * width / iw);
8319
+ var dy = (sy * height / ih / vertSquashRatio + y) << 0;
8320
+ var dh = Math.ceil(sh * height / ih / vertSquashRatio);
8321
+ ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh);
8322
+ sx += d;
8323
+ }
8324
+ sy += d;
8325
+ }
8326
+ tmpCanvas = tmpCtx = null;
8327
+ }
8328
+
8329
+ /**
8330
+ * Detect subsampling in loaded image.
8331
+ * In iOS, larger images than 2M pixels may be subsampled in rendering.
8332
+ */
8333
+ function detectSubsampling(img) {
8334
+ var iw = img.naturalWidth, ih = img.naturalHeight;
8335
+ if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image
8336
+ var canvas = document.createElement('canvas');
8337
+ canvas.width = canvas.height = 1;
8338
+ var ctx = canvas.getContext('2d');
8339
+ ctx.drawImage(img, -iw + 1, 0);
8340
+ // subsampled image becomes half smaller in rendering size.
8341
+ // check alpha channel value to confirm image is covering edge pixel or not.
8342
+ // if alpha value is 0 image is not covering, hence subsampled.
8343
+ return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
8344
+ } else {
8345
+ return false;
8346
+ }
8347
+ }
8348
+
8349
+
8350
+ /**
8351
+ * Detecting vertical squash in loaded image.
8352
+ * Fixes a bug which squash image vertically while drawing into canvas for some images.
8353
+ */
8354
+ function detectVerticalSquash(img, iw, ih) {
8355
+ var canvas = document.createElement('canvas');
8356
+ canvas.width = 1;
8357
+ canvas.height = ih;
8358
+ var ctx = canvas.getContext('2d');
8359
+ ctx.drawImage(img, 0, 0);
8360
+ var data = ctx.getImageData(0, 0, 1, ih).data;
8361
+ // search image edge pixel position in case it is squashed vertically.
8362
+ var sy = 0;
8363
+ var ey = ih;
8364
+ var py = ih;
8365
+ while (py > sy) {
8366
+ var alpha = data[(py - 1) * 4 + 3];
8367
+ if (alpha === 0) {
8368
+ ey = py;
8369
+ } else {
8370
+ sy = py;
8371
+ }
8372
+ py = (ey + sy) >> 1;
8373
+ }
8374
+ canvas = null;
8375
+ var ratio = (py / ih);
8376
+ return (ratio === 0) ? 1 : ratio;
8377
+ }
8378
+
8379
+ return {
8380
+ isSubsampled: detectSubsampling,
8381
+ renderTo: renderImageToCanvas
8382
+ };
8383
+ });
8384
+
8385
+ // Included from: src/javascript/runtime/html5/image/Image.js
8386
+
8387
+ /**
8388
+ * Image.js
8389
+ *
8390
+ * Copyright 2013, Moxiecode Systems AB
8391
+ * Released under GPL License.
8392
+ *
8393
+ * License: http://www.plupload.com/license
8394
+ * Contributing: http://www.plupload.com/contributing
8395
+ */
8396
+
8397
+ /**
8398
+ @class moxie/runtime/html5/image/Image
8399
+ @private
8400
+ */
8401
+ define("moxie/runtime/html5/image/Image", [
8402
+ "moxie/runtime/html5/Runtime",
8403
+ "moxie/core/utils/Basic",
8404
+ "moxie/core/Exceptions",
8405
+ "moxie/core/utils/Encode",
8406
+ "moxie/file/File",
8407
+ "moxie/runtime/html5/image/ImageInfo",
8408
+ "moxie/runtime/html5/image/MegaPixel",
8409
+ "moxie/core/utils/Mime",
8410
+ "moxie/core/utils/Env"
8411
+ ], function(extensions, Basic, x, Encode, File, ImageInfo, MegaPixel, Mime, Env) {
8412
+
8413
+ function HTML5Image() {
8414
+ var me = this
8415
+ , _img, _imgInfo, _canvas, _binStr, _blob
8416
+ , _modified = false // is set true whenever image is modified
8417
+ , _preserveHeaders = true
8418
+ ;
8419
+
8420
+ Basic.extend(this, {
8421
+ loadFromBlob: function(blob) {
8422
+ var comp = this, I = comp.getRuntime()
8423
+ , asBinary = arguments.length > 1 ? arguments[1] : true
8424
+ ;
8425
+
8426
+ if (!I.can('access_binary')) {
8427
+ throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR);
8428
+ }
8429
+
8430
+ _blob = blob;
8431
+
8432
+ if (blob.isDetached()) {
8433
+ _binStr = blob.getSource();
8434
+ _preload.call(this, _binStr);
8435
+ return;
8436
+ } else {
8437
+ _readAsDataUrl.call(this, blob.getSource(), function(dataUrl) {
8438
+ if (asBinary) {
8439
+ _binStr = _toBinary(dataUrl);
8440
+ }
8441
+ _preload.call(comp, dataUrl);
8442
+ });
8443
+ }
8444
+ },
8445
+
8446
+ loadFromImage: function(img, exact) {
8447
+ this.meta = img.meta;
8448
+
8449
+ _blob = new File(null, {
8450
+ name: img.name,
8451
+ size: img.size,
8452
+ type: img.type
8453
+ });
8454
+
8455
+ _preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL());
8456
+ },
8457
+
8458
+ getInfo: function() {
8459
+ var I = this.getRuntime(), info;
8460
+
8461
+ if (!_imgInfo && _binStr && I.can('access_image_binary')) {
8462
+ _imgInfo = new ImageInfo(_binStr);
8463
+ }
8464
+
8465
+ info = {
8466
+ width: _getImg().width || 0,
8467
+ height: _getImg().height || 0,
8468
+ type: _blob.type || Mime.getFileMime(_blob.name),
8469
+ size: _binStr && _binStr.length || _blob.size || 0,
8470
+ name: _blob.name || '',
8471
+ meta: _imgInfo && _imgInfo.meta || this.meta || {}
8472
+ };
8473
+
8474
+ return info;
8475
+ },
8476
+
8477
+ downsize: function() {
8478
+ _downsize.apply(this, arguments);
8479
+ },
8480
+
8481
+ getAsCanvas: function() {
8482
+ if (_canvas) {
8483
+ _canvas.id = this.uid + '_canvas';
8484
+ }
8485
+ return _canvas;
8486
+ },
8487
+
8488
+ getAsBlob: function(type, quality) {
8489
+ if (type !== this.type) {
8490
+ // if different mime type requested prepare image for conversion
8491
+ _downsize.call(this, this.width, this.height, false);
8492
+ }
8493
+ return new File(null, {
8494
+ name: _blob.name || '',
8495
+ type: type,
8496
+ data: me.getAsBinaryString.call(this, type, quality)
8497
+ });
8498
+ },
8499
+
8500
+ getAsDataURL: function(type) {
8501
+ var quality = arguments[1] || 90;
8502
+
8503
+ // if image has not been modified, return the source right away
8504
+ if (!_modified) {
8505
+ return _img.src;
8506
+ }
8507
+
8508
+ if ('image/jpeg' !== type) {
8509
+ return _canvas.toDataURL('image/png');
8510
+ } else {
8511
+ try {
8512
+ // older Geckos used to result in an exception on quality argument
8513
+ return _canvas.toDataURL('image/jpeg', quality/100);
8514
+ } catch (ex) {
8515
+ return _canvas.toDataURL('image/jpeg');
8516
+ }
8517
+ }
8518
+ },
8519
+
8520
+ getAsBinaryString: function(type, quality) {
8521
+ // if image has not been modified, return the source right away
8522
+ if (!_modified) {
8523
+ // if image was not loaded from binary string
8524
+ if (!_binStr) {
8525
+ _binStr = _toBinary(me.getAsDataURL(type, quality));
8526
+ }
8527
+ return _binStr;
8528
+ }
8529
+
8530
+ if ('image/jpeg' !== type) {
8531
+ _binStr = _toBinary(me.getAsDataURL(type, quality));
8532
+ } else {
8533
+ var dataUrl;
8534
+
8535
+ // if jpeg
8536
+ if (!quality) {
8537
+ quality = 90;
8538
+ }
8539
+
8540
+ try {
8541
+ // older Geckos used to result in an exception on quality argument
8542
+ dataUrl = _canvas.toDataURL('image/jpeg', quality/100);
8543
+ } catch (ex) {
8544
+ dataUrl = _canvas.toDataURL('image/jpeg');
8545
+ }
8546
+
8547
+ _binStr = _toBinary(dataUrl);
8548
+
8549
+ if (_imgInfo) {
8550
+ _binStr = _imgInfo.stripHeaders(_binStr);
8551
+
8552
+ if (_preserveHeaders) {
8553
+ // update dimensions info in exif
8554
+ if (_imgInfo.meta && _imgInfo.meta.exif) {
8555
+ _imgInfo.setExif({
8556
+ PixelXDimension: this.width,
8557
+ PixelYDimension: this.height
8558
+ });
8559
+ }
8560
+
8561
+ // re-inject the headers
8562
+ _binStr = _imgInfo.writeHeaders(_binStr);
8563
+ }
8564
+
8565
+ // will be re-created from fresh on next getInfo call
8566
+ _imgInfo.purge();
8567
+ _imgInfo = null;
8568
+ }
8569
+ }
8570
+
8571
+ _modified = false;
8572
+
8573
+ return _binStr;
8574
+ },
8575
+
8576
+ destroy: function() {
8577
+ me = null;
8578
+ _purge.call(this);
8579
+ this.getRuntime().getShim().removeInstance(this.uid);
8580
+ }
8581
+ });
8582
+
8583
+
8584
+ function _getImg() {
8585
+ if (!_canvas && !_img) {
8586
+ throw new x.ImageError(x.DOMException.INVALID_STATE_ERR);
8587
+ }
8588
+ return _canvas || _img;
8589
+ }
8590
+
8591
+
8592
+ function _toBinary(str) {
8593
+ return Encode.atob(str.substring(str.indexOf('base64,') + 7));
8594
+ }
8595
+
8596
+
8597
+ function _toDataUrl(str, type) {
8598
+ return 'data:' + (type || '') + ';base64,' + Encode.btoa(str);
8599
+ }
8600
+
8601
+
8602
+ function _preload(str) {
8603
+ var comp = this;
8604
+
8605
+ _img = new Image();
8606
+ _img.onerror = function() {
8607
+ _purge.call(this);
8608
+ comp.trigger('error', new x.ImageError(x.ImageError.WRONG_FORMAT));
8609
+ };
8610
+ _img.onload = function() {
8611
+ comp.trigger('load');
8612
+ };
8613
+
8614
+ _img.src = /^data:[^;]*;base64,/.test(str) ? str : _toDataUrl(str, _blob.type);
8615
+ }
8616
+
8617
+
8618
+ function _readAsDataUrl(file, callback) {
8619
+ var comp = this, fr;
8620
+
8621
+ // use FileReader if it's available
8622
+ if (window.FileReader) {
8623
+ fr = new FileReader();
8624
+ fr.onload = function() {
8625
+ callback(this.result);
8626
+ };
8627
+ fr.onerror = function() {
8628
+ comp.trigger('error', new x.FileException(x.FileException.NOT_READABLE_ERR));
8629
+ };
8630
+ fr.readAsDataURL(file);
8631
+ } else {
8632
+ return callback(file.getAsDataURL());
8633
+ }
8634
+ }
8635
+
8636
+ function _downsize(width, height, crop, preserveHeaders) {
8637
+ var self = this
8638
+ , scale
8639
+ , mathFn
8640
+ , x = 0
8641
+ , y = 0
8642
+ , img
8643
+ , destWidth
8644
+ , destHeight
8645
+ , orientation
8646
+ ;
8647
+
8648
+ _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString())
8649
+
8650
+ // take into account orientation tag
8651
+ orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1;
8652
+
8653
+ if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation
8654
+ // swap dimensions
8655
+ var tmp = width;
8656
+ width = height;
8657
+ height = tmp;
8658
+ }
8659
+
8660
+ img = _getImg();
8661
+
8662
+ // unify dimensions
8663
+ mathFn = !crop ? Math.min : Math.max;
8664
+ scale = mathFn(width/img.width, height/img.height);
8665
+
8666
+ // we only downsize here
8667
+ if (scale > 1 && (!crop || preserveHeaders)) { // when cropping one of dimensions may still exceed max, so process it anyway
8668
+ this.trigger('Resize');
8669
+ return;
8670
+ }
8671
+
8672
+ // prepare canvas if necessary
8673
+ if (!_canvas) {
8674
+ _canvas = document.createElement("canvas");
8675
+ }
8676
+
8677
+ // calculate dimensions of proportionally resized image
8678
+ destWidth = Math.round(img.width * scale);
8679
+ destHeight = Math.round(img.height * scale);
8680
+
8681
+
8682
+ // scale image and canvas
8683
+ if (crop) {
8684
+ _canvas.width = width;
8685
+ _canvas.height = height;
8686
+
8687
+ // if dimensions of the resulting image still larger than canvas, center it
8688
+ if (destWidth > width) {
8689
+ x = Math.round((destWidth - width) / 2);
8690
+ }
8691
+
8692
+ if (destHeight > height) {
8693
+ y = Math.round((destHeight - height) / 2);
8694
+ }
8695
+ } else {
8696
+ _canvas.width = destWidth;
8697
+ _canvas.height = destHeight;
8698
+ }
8699
+
8700
+ // rotate if required, according to orientation tag
8701
+ if (!_preserveHeaders) {
8702
+ _rotateToOrientaion(_canvas.width, _canvas.height, orientation);
8703
+ }
8704
+
8705
+ _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight);
8706
+
8707
+ this.width = _canvas.width;
8708
+ this.height = _canvas.height;
8709
+
8710
+ _modified = true;
8711
+ self.trigger('Resize');
8712
+ }
8713
+
8714
+
8715
+ function _drawToCanvas(img, canvas, x, y, w, h) {
8716
+ if (Env.OS === 'iOS') {
8717
+ // avoid squish bug in iOS6
8718
+ MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y });
8719
+ } else {
8720
+ var ctx = canvas.getContext('2d');
8721
+ ctx.drawImage(img, x, y, w, h);
8722
+ }
8723
+ }
8724
+
8725
+
8726
+ /**
8727
+ * Transform canvas coordination according to specified frame size and orientation
8728
+ * Orientation value is from EXIF tag
8729
+ * @author Shinichi Tomita <shinichi.tomita@gmail.com>
8730
+ */
8731
+ function _rotateToOrientaion(width, height, orientation) {
8732
+ switch (orientation) {
8733
+ case 5:
8734
+ case 6:
8735
+ case 7:
8736
+ case 8:
8737
+ _canvas.width = height;
8738
+ _canvas.height = width;
8739
+ break;
8740
+ default:
8741
+ _canvas.width = width;
8742
+ _canvas.height = height;
8743
+ }
8744
+
8745
+ /**
8746
+ 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.
8747
+ 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.
8748
+ 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.
8749
+ 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.
8750
+ 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.
8751
+ 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.
8752
+ 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.
8753
+ 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.
8754
+ */
8755
+
8756
+ var ctx = _canvas.getContext('2d');
8757
+ switch (orientation) {
8758
+ case 2:
8759
+ // horizontal flip
8760
+ ctx.translate(width, 0);
8761
+ ctx.scale(-1, 1);
8762
+ break;
8763
+ case 3:
8764
+ // 180 rotate left
8765
+ ctx.translate(width, height);
8766
+ ctx.rotate(Math.PI);
8767
+ break;
8768
+ case 4:
8769
+ // vertical flip
8770
+ ctx.translate(0, height);
8771
+ ctx.scale(1, -1);
8772
+ break;
8773
+ case 5:
8774
+ // vertical flip + 90 rotate right
8775
+ ctx.rotate(0.5 * Math.PI);
8776
+ ctx.scale(1, -1);
8777
+ break;
8778
+ case 6:
8779
+ // 90 rotate right
8780
+ ctx.rotate(0.5 * Math.PI);
8781
+ ctx.translate(0, -height);
8782
+ break;
8783
+ case 7:
8784
+ // horizontal flip + 90 rotate right
8785
+ ctx.rotate(0.5 * Math.PI);
8786
+ ctx.translate(width, -height);
8787
+ ctx.scale(-1, 1);
8788
+ break;
8789
+ case 8:
8790
+ // 90 rotate left
8791
+ ctx.rotate(-0.5 * Math.PI);
8792
+ ctx.translate(-width, 0);
8793
+ break;
8794
+ }
8795
+ }
8796
+
8797
+
8798
+ function _purge() {
8799
+ if (_imgInfo) {
8800
+ _imgInfo.purge();
8801
+ _imgInfo = null;
8802
+ }
8803
+ _binStr = _img = _canvas = _blob = null;
8804
+ _modified = false;
8805
+ }
8806
+ }
8807
+
8808
+ return (extensions.Image = HTML5Image);
8809
+ });
8810
+
8811
+ // Included from: src/javascript/runtime/flash/Runtime.js
8812
+
8813
+ /**
8814
+ * Runtime.js
8815
+ *
8816
+ * Copyright 2013, Moxiecode Systems AB
8817
+ * Released under GPL License.
8818
+ *
8819
+ * License: http://www.plupload.com/license
8820
+ * Contributing: http://www.plupload.com/contributing
8821
+ */
8822
+
8823
+ /*global ActiveXObject:true */
8824
+
8825
+ /**
8826
+ Defines constructor for Flash runtime.
8827
+
8828
+ @class moxie/runtime/flash/Runtime
8829
+ @private
8830
+ */
8831
+ define("moxie/runtime/flash/Runtime", [
8832
+ "moxie/core/utils/Basic",
8833
+ "moxie/core/utils/Env",
8834
+ "moxie/core/utils/Dom",
8835
+ "moxie/core/Exceptions",
8836
+ "moxie/runtime/Runtime"
8837
+ ], function(Basic, Env, Dom, x, Runtime) {
8838
+
8839
+ var type = 'flash', extensions = {};
8840
+
8841
+ /**
8842
+ Get the version of the Flash Player
8843
+
8844
+ @method getShimVersion
8845
+ @private
8846
+ @return {Number} Flash Player version
8847
+ */
8848
+ function getShimVersion() {
8849
+ var version;
8850
+
8851
+ try {
8852
+ version = navigator.plugins['Shockwave Flash'];
8853
+ version = version.description;
8854
+ } catch (e1) {
8855
+ try {
8856
+ version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
8857
+ } catch (e2) {
8858
+ version = '0.0';
8859
+ }
8860
+ }
8861
+ version = version.match(/\d+/g);
8862
+ return parseFloat(version[0] + '.' + version[1]);
8863
+ }
8864
+
8865
+ /**
8866
+ Constructor for the Flash Runtime
8867
+
8868
+ @class FlashRuntime
8869
+ @extends Runtime
8870
+ */
8871
+ function FlashRuntime(options) {
8872
+ var I = this, initTimer;
8873
+
8874
+ options = Basic.extend({ swf_url: Env.swf_url }, options);
8875
+
8876
+ Runtime.call(this, options, type, {
8877
+ access_binary: function(value) {
8878
+ return value && I.mode === 'browser';
8879
+ },
8880
+ access_image_binary: function(value) {
8881
+ return value && I.mode === 'browser';
8882
+ },
8883
+ display_media: Runtime.capTrue,
8884
+ do_cors: Runtime.capTrue,
8885
+ drag_and_drop: false,
8886
+ report_upload_progress: function() {
8887
+ return I.mode === 'client';
8888
+ },
8889
+ resize_image: Runtime.capTrue,
8890
+ return_response_headers: false,
8891
+ return_response_type: function(responseType) {
8892
+ if (responseType === 'json' && !!window.JSON) {
8893
+ return true;
8894
+ }
8895
+ return !Basic.arrayDiff(responseType, ['', 'text', 'document']) || I.mode === 'browser';
8896
+ },
8897
+ return_status_code: function(code) {
8898
+ return I.mode === 'browser' || !Basic.arrayDiff(code, [200, 404]);
8899
+ },
8900
+ select_file: Runtime.capTrue,
8901
+ select_multiple: Runtime.capTrue,
8902
+ send_binary_string: function(value) {
8903
+ return value && I.mode === 'browser';
8904
+ },
8905
+ send_browser_cookies: function(value) {
8906
+ return value && I.mode === 'browser';
8907
+ },
8908
+ send_custom_headers: function(value) {
8909
+ return value && I.mode === 'browser';
8910
+ },
8911
+ send_multipart: Runtime.capTrue,
8912
+ slice_blob: Runtime.capTrue,
8913
+ stream_upload: function(value) {
8914
+ return value && I.mode === 'browser';
8915
+ },
8916
+ summon_file_dialog: false,
8917
+ upload_filesize: function(size) {
8918
+ return Basic.parseSizeStr(size) <= 2097152 || I.mode === 'client';
8919
+ },
8920
+ use_http_method: function(methods) {
8921
+ return !Basic.arrayDiff(methods, ['GET', 'POST']);
8922
+ }
8923
+ }, {
8924
+ // capabilities that require specific mode
8925
+ access_binary: function(value) {
8926
+ return value ? 'browser' : 'client';
8927
+ },
8928
+ access_image_binary: function(value) {
8929
+ return value ? 'browser' : 'client';
8930
+ },
8931
+ report_upload_progress: function(value) {
8932
+ return value ? 'browser' : 'client';
8933
+ },
8934
+ return_response_type: function(responseType) {
8935
+ return Basic.arrayDiff(responseType, ['', 'text', 'json', 'document']) ? 'browser' : ['client', 'browser'];
8936
+ },
8937
+ return_status_code: function(code) {
8938
+ return Basic.arrayDiff(code, [200, 404]) ? 'browser' : ['client', 'browser'];
8939
+ },
8940
+ send_binary_string: function(value) {
8941
+ return value ? 'browser' : 'client';
8942
+ },
8943
+ send_browser_cookies: function(value) {
8944
+ return value ? 'browser' : 'client';
8945
+ },
8946
+ send_custom_headers: function(value) {
8947
+ return value ? 'browser' : 'client';
8948
+ },
8949
+ stream_upload: function(value) {
8950
+ return value ? 'client' : 'browser';
8951
+ },
8952
+ upload_filesize: function(size) {
8953
+ return Basic.parseSizeStr(size) >= 2097152 ? 'client' : 'browser';
8954
+ }
8955
+ }, 'client');
8956
+
8957
+
8958
+ // minimal requirement for Flash Player version
8959
+ if (getShimVersion() < 10) {
8960
+ this.mode = false; // with falsy mode, runtime won't operable, no matter what the mode was before
8961
+ }
8962
+
8963
+
8964
+ Basic.extend(this, {
8965
+
8966
+ getShim: function() {
8967
+ return Dom.get(this.uid);
8968
+ },
8969
+
8970
+ shimExec: function(component, action) {
8971
+ var args = [].slice.call(arguments, 2);
8972
+ return I.getShim().exec(this.uid, component, action, args);
8973
+ },
8974
+
8975
+ init: function() {
8976
+ var html, el, container;
8977
+
8978
+ container = this.getShimContainer();
8979
+
8980
+ // if not the minimal height, shims are not initialized in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)
8981
+ Basic.extend(container.style, {
8982
+ position: 'absolute',
8983
+ top: '-8px',
8984
+ left: '-8px',
8985
+ width: '9px',
8986
+ height: '9px',
8987
+ overflow: 'hidden'
8988
+ });
8989
+
8990
+ // insert flash object
8991
+ html = '<object id="' + this.uid + '" type="application/x-shockwave-flash" data="' + options.swf_url + '" ';
8992
+
8993
+ if (Env.browser === 'IE') {
8994
+ html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
8995
+ }
8996
+
8997
+ html += 'width="100%" height="100%" style="outline:0">' +
8998
+ '<param name="movie" value="' + options.swf_url + '" />' +
8999
+ '<param name="flashvars" value="uid=' + escape(this.uid) + '&target=' + Env.global_event_dispatcher + '" />' +
9000
+ '<param name="wmode" value="transparent" />' +
9001
+ '<param name="allowscriptaccess" value="always" />' +
9002
+ '</object>';
9003
+
9004
+ if (Env.browser === 'IE') {
9005
+ el = document.createElement('div');
9006
+ container.appendChild(el);
9007
+ el.outerHTML = html;
9008
+ el = container = null; // just in case
9009
+ } else {
9010
+ container.innerHTML = html;
9011
+ }
9012
+
9013
+ // Init is dispatched by the shim
9014
+ initTimer = setTimeout(function() {
9015
+ if (I && !I.initialized) { // runtime might be already destroyed by this moment
9016
+ I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
9017
+ }
9018
+ }, 5000);
9019
+ },
9020
+
9021
+ destroy: (function(destroy) { // extend default destroy method
9022
+ return function() {
9023
+ destroy.call(I);
9024
+ clearTimeout(initTimer); // initialization check might be still onwait
9025
+ options = initTimer = destroy = I = null;
9026
+ };
9027
+ }(this.destroy))
9028
+
9029
+ }, extensions);
9030
+ }
9031
+
9032
+ Runtime.addConstructor(type, FlashRuntime);
9033
+
9034
+ return extensions;
9035
+ });
9036
+
9037
+ // Included from: src/javascript/runtime/flash/file/Blob.js
9038
+
9039
+ /**
9040
+ * Blob.js
9041
+ *
9042
+ * Copyright 2013, Moxiecode Systems AB
9043
+ * Released under GPL License.
9044
+ *
9045
+ * License: http://www.plupload.com/license
9046
+ * Contributing: http://www.plupload.com/contributing
9047
+ */
9048
+
9049
+ /**
9050
+ @class moxie/runtime/flash/file/Blob
9051
+ @private
9052
+ */
9053
+ define("moxie/runtime/flash/file/Blob", [
9054
+ "moxie/runtime/flash/Runtime",
9055
+ "moxie/file/Blob"
9056
+ ], function(extensions, Blob) {
9057
+
9058
+ var FlashBlob = {
9059
+ slice: function(blob, start, end, type) {
9060
+ var self = this.getRuntime();
9061
+
9062
+ if (start < 0) {
9063
+ start = Math.max(blob.size + start, 0);
9064
+ } else if (start > 0) {
9065
+ start = Math.min(start, blob.size);
9066
+ }
9067
+
9068
+ if (end < 0) {
9069
+ end = Math.max(blob.size + end, 0);
9070
+ } else if (end > 0) {
9071
+ end = Math.min(end, blob.size);
9072
+ }
9073
+
9074
+ blob = self.shimExec.call(this, 'Blob', 'slice', start, end, type || '');
9075
+
9076
+ if (blob) {
9077
+ blob = new Blob(self.uid, blob);
9078
+ }
9079
+ return blob;
9080
+ }
9081
+ };
9082
+
9083
+ return (extensions.Blob = FlashBlob);
9084
+ });
9085
+
9086
+ // Included from: src/javascript/runtime/flash/file/FileInput.js
9087
+
9088
+ /**
9089
+ * FileInput.js
9090
+ *
9091
+ * Copyright 2013, Moxiecode Systems AB
9092
+ * Released under GPL License.
9093
+ *
9094
+ * License: http://www.plupload.com/license
9095
+ * Contributing: http://www.plupload.com/contributing
9096
+ */
9097
+
9098
+ /**
9099
+ @class moxie/runtime/flash/file/FileInput
9100
+ @private
9101
+ */
9102
+ define("moxie/runtime/flash/file/FileInput", [
9103
+ "moxie/runtime/flash/Runtime"
9104
+ ], function(extensions) {
9105
+
9106
+ var FileInput = {
9107
+ init: function(options) {
9108
+ this.getRuntime().shimExec.call(this, 'FileInput', 'init', {
9109
+ name: options.name,
9110
+ accept: options.accept,
9111
+ multiple: options.multiple
9112
+ });
9113
+ this.trigger('ready');
9114
+ }
9115
+ };
9116
+
9117
+ return (extensions.FileInput = FileInput);
9118
+ });
9119
+
9120
+ // Included from: src/javascript/runtime/flash/file/FileReader.js
9121
+
9122
+ /**
9123
+ * FileReader.js
9124
+ *
9125
+ * Copyright 2013, Moxiecode Systems AB
9126
+ * Released under GPL License.
9127
+ *
9128
+ * License: http://www.plupload.com/license
9129
+ * Contributing: http://www.plupload.com/contributing
9130
+ */
9131
+
9132
+ /**
9133
+ @class moxie/runtime/flash/file/FileReader
9134
+ @private
9135
+ */
9136
+ define("moxie/runtime/flash/file/FileReader", [
9137
+ "moxie/runtime/flash/Runtime",
9138
+ "moxie/core/utils/Encode"
9139
+ ], function(extensions, Encode) {
9140
+
9141
+ var _result = '';
9142
+
9143
+ function _formatData(data, op) {
9144
+ switch (op) {
9145
+ case 'readAsText':
9146
+ return Encode.atob(data, 'utf8');
9147
+ case 'readAsBinaryString':
9148
+ return Encode.atob(data);
9149
+ case 'readAsDataURL':
9150
+ return data;
9151
+ }
9152
+ return null;
9153
+ }
9154
+
9155
+ var FileReader = {
9156
+ read: function(op, blob) {
9157
+ var target = this, self = target.getRuntime();
9158
+
9159
+ // special prefix for DataURL read mode
9160
+ if (op === 'readAsDataURL') {
9161
+ _result = 'data:' + (blob.type || '') + ';base64,';
9162
+ }
9163
+
9164
+ target.bind('Progress', function(e, data) {
9165
+ if (data) {
9166
+ _result += _formatData(data, op);
9167
+ }
9168
+ });
9169
+
9170
+ return self.shimExec.call(this, 'FileReader', 'readAsBase64', blob.uid);
9171
+ },
9172
+
9173
+ getResult: function() {
9174
+ return _result;
9175
+ },
9176
+
9177
+ destroy: function() {
9178
+ _result = null;
9179
+ }
9180
+ };
9181
+
9182
+ return (extensions.FileReader = FileReader);
9183
+ });
9184
+
9185
+ // Included from: src/javascript/runtime/flash/file/FileReaderSync.js
9186
+
9187
+ /**
9188
+ * FileReaderSync.js
9189
+ *
9190
+ * Copyright 2013, Moxiecode Systems AB
9191
+ * Released under GPL License.
9192
+ *
9193
+ * License: http://www.plupload.com/license
9194
+ * Contributing: http://www.plupload.com/contributing
9195
+ */
9196
+
9197
+ /**
9198
+ @class moxie/runtime/flash/file/FileReaderSync
9199
+ @private
9200
+ */
9201
+ define("moxie/runtime/flash/file/FileReaderSync", [
9202
+ "moxie/runtime/flash/Runtime",
9203
+ "moxie/core/utils/Encode"
9204
+ ], function(extensions, Encode) {
9205
+
9206
+ function _formatData(data, op) {
9207
+ switch (op) {
9208
+ case 'readAsText':
9209
+ return Encode.atob(data, 'utf8');
9210
+ case 'readAsBinaryString':
9211
+ return Encode.atob(data);
9212
+ case 'readAsDataURL':
9213
+ return data;
9214
+ }
9215
+ return null;
9216
+ }
9217
+
9218
+ var FileReaderSync = {
9219
+ read: function(op, blob) {
9220
+ var result, self = this.getRuntime();
9221
+
9222
+ result = self.shimExec.call(this, 'FileReaderSync', 'readAsBase64', blob.uid);
9223
+ if (!result) {
9224
+ return null; // or throw ex
9225
+ }
9226
+
9227
+ // special prefix for DataURL read mode
9228
+ if (op === 'readAsDataURL') {
9229
+ result = 'data:' + (blob.type || '') + ';base64,' + result;
9230
+ }
9231
+
9232
+ return _formatData(result, op, blob.type);
9233
+ }
9234
+ };
9235
+
9236
+ return (extensions.FileReaderSync = FileReaderSync);
9237
+ });
9238
+
9239
+ // Included from: src/javascript/runtime/flash/xhr/XMLHttpRequest.js
9240
+
9241
+ /**
9242
+ * XMLHttpRequest.js
9243
+ *
9244
+ * Copyright 2013, Moxiecode Systems AB
9245
+ * Released under GPL License.
9246
+ *
9247
+ * License: http://www.plupload.com/license
9248
+ * Contributing: http://www.plupload.com/contributing
9249
+ */
9250
+
9251
+ /**
9252
+ @class moxie/runtime/flash/xhr/XMLHttpRequest
9253
+ @private
9254
+ */
9255
+ define("moxie/runtime/flash/xhr/XMLHttpRequest", [
9256
+ "moxie/runtime/flash/Runtime",
9257
+ "moxie/core/utils/Basic",
9258
+ "moxie/file/Blob",
9259
+ "moxie/file/File",
9260
+ "moxie/file/FileReaderSync",
9261
+ "moxie/xhr/FormData",
9262
+ "moxie/runtime/Transporter"
9263
+ ], function(extensions, Basic, Blob, File, FileReaderSync, FormData, Transporter) {
9264
+
9265
+ var XMLHttpRequest = {
9266
+
9267
+ send: function(meta, data) {
9268
+ var target = this, self = target.getRuntime();
9269
+
9270
+ function send() {
9271
+ meta.transport = self.mode;
9272
+ self.shimExec.call(target, 'XMLHttpRequest', 'send', meta, data);
9273
+ }
9274
+
9275
+
9276
+ function appendBlob(name, blob) {
9277
+ self.shimExec.call(target, 'XMLHttpRequest', 'appendBlob', name, blob.uid);
9278
+ data = null;
9279
+ send();
9280
+ }
9281
+
9282
+
9283
+ function attachBlob(blob, cb) {
9284
+ var tr = new Transporter();
9285
+
9286
+ tr.bind("TransportingComplete", function() {
9287
+ cb(this.result);
9288
+ });
9289
+
9290
+ tr.transport(blob.getSource(), blob.type, {
9291
+ ruid: self.uid
9292
+ });
9293
+ }
9294
+
9295
+ // copy over the headers if any
9296
+ if (!Basic.isEmptyObj(meta.headers)) {
9297
+ Basic.each(meta.headers, function(value, header) {
9298
+ self.shimExec.call(target, 'XMLHttpRequest', 'setRequestHeader', header, value.toString()); // Silverlight doesn't accept integers into the arguments of type object
9299
+ });
9300
+ }
9301
+
9302
+ // transfer over multipart params and blob itself
9303
+ if (data instanceof FormData) {
9304
+ var blobField;
9305
+ data.each(function(value, name) {
9306
+ if (value instanceof Blob) {
9307
+ blobField = name;
9308
+ } else {
9309
+ self.shimExec.call(target, 'XMLHttpRequest', 'append', name, value);
9310
+ }
9311
+ });
9312
+
9313
+ if (!data.hasBlob()) {
9314
+ data = null;
9315
+ send();
9316
+ } else {
9317
+ var blob = data.getBlob();
9318
+ if (blob.isDetached()) {
9319
+ attachBlob(blob, function(attachedBlob) {
9320
+ blob.destroy();
9321
+ appendBlob(blobField, attachedBlob);
9322
+ });
9323
+ } else {
9324
+ appendBlob(blobField, blob);
9325
+ }
9326
+ }
9327
+ } else if (data instanceof Blob) {
9328
+ if (data.isDetached()) {
9329
+ attachBlob(data, function(attachedBlob) {
9330
+ data.destroy();
9331
+ data = attachedBlob.uid;
9332
+ send();
9333
+ });
9334
+ } else {
9335
+ data = data.uid;
9336
+ send();
9337
+ }
9338
+ } else {
9339
+ send();
9340
+ }
9341
+ },
9342
+
9343
+ getResponse: function(responseType) {
9344
+ var frs, blob, self = this.getRuntime();
9345
+
9346
+ blob = self.shimExec.call(this, 'XMLHttpRequest', 'getResponseAsBlob');
9347
+
9348
+ if (blob) {
9349
+ blob = new File(self.uid, blob);
9350
+
9351
+ if ('blob' === responseType) {
9352
+ return blob;
9353
+ }
9354
+
9355
+ try {
9356
+ frs = new FileReaderSync();
9357
+
9358
+ if (!!~Basic.inArray(responseType, ["", "text"])) {
9359
+ return frs.readAsText(blob);
9360
+ } else if ('json' === responseType && !!window.JSON) {
9361
+ return JSON.parse(frs.readAsText(blob));
9362
+ }
9363
+ } finally {
9364
+ blob.destroy();
9365
+ }
9366
+ }
9367
+ return null;
9368
+ },
9369
+
9370
+ abort: function(upload_complete_flag) {
9371
+ var self = this.getRuntime();
9372
+
9373
+ self.shimExec.call(this, 'XMLHttpRequest', 'abort');
9374
+
9375
+ this.dispatchEvent('readystatechange');
9376
+ // this.dispatchEvent('progress');
9377
+ this.dispatchEvent('abort');
9378
+
9379
+ //if (!upload_complete_flag) {
9380
+ // this.dispatchEvent('uploadprogress');
9381
+ //}
9382
+ }
9383
+ };
9384
+
9385
+ return (extensions.XMLHttpRequest = XMLHttpRequest);
9386
+ });
9387
+
9388
+ // Included from: src/javascript/runtime/flash/runtime/Transporter.js
9389
+
9390
+ /**
9391
+ * Transporter.js
9392
+ *
9393
+ * Copyright 2013, Moxiecode Systems AB
9394
+ * Released under GPL License.
9395
+ *
9396
+ * License: http://www.plupload.com/license
9397
+ * Contributing: http://www.plupload.com/contributing
9398
+ */
9399
+
9400
+ /**
9401
+ @class moxie/runtime/flash/runtime/Transporter
9402
+ @private
9403
+ */
9404
+ define("moxie/runtime/flash/runtime/Transporter", [
9405
+ "moxie/runtime/flash/Runtime",
9406
+ "moxie/file/Blob"
9407
+ ], function(extensions, Blob) {
9408
+
9409
+ var Transporter = {
9410
+ getAsBlob: function(type) {
9411
+ var self = this.getRuntime()
9412
+ , blob = self.shimExec.call(this, 'Transporter', 'getAsBlob', type)
9413
+ ;
9414
+ if (blob) {
9415
+ return new Blob(self.uid, blob);
9416
+ }
9417
+ return null;
9418
+ }
9419
+ };
9420
+
9421
+ return (extensions.Transporter = Transporter);
9422
+ });
9423
+
9424
+ // Included from: src/javascript/runtime/flash/image/Image.js
9425
+
9426
+ /**
9427
+ * Image.js
9428
+ *
9429
+ * Copyright 2013, Moxiecode Systems AB
9430
+ * Released under GPL License.
9431
+ *
9432
+ * License: http://www.plupload.com/license
9433
+ * Contributing: http://www.plupload.com/contributing
9434
+ */
9435
+
9436
+ /**
9437
+ @class moxie/runtime/flash/image/Image
9438
+ @private
9439
+ */
9440
+ define("moxie/runtime/flash/image/Image", [
9441
+ "moxie/runtime/flash/Runtime",
9442
+ "moxie/core/utils/Basic",
9443
+ "moxie/runtime/Transporter",
9444
+ "moxie/file/Blob",
9445
+ "moxie/file/FileReaderSync"
9446
+ ], function(extensions, Basic, Transporter, Blob, FileReaderSync) {
9447
+
9448
+ var Image = {
9449
+ loadFromBlob: function(blob) {
9450
+ var comp = this, self = comp.getRuntime();
9451
+
9452
+ function exec(srcBlob) {
9453
+ self.shimExec.call(comp, 'Image', 'loadFromBlob', srcBlob.uid);
9454
+ comp = self = null;
9455
+ }
9456
+
9457
+ if (blob.isDetached()) { // binary string
9458
+ var tr = new Transporter();
9459
+ tr.bind("TransportingComplete", function() {
9460
+ exec(tr.result.getSource());
9461
+ });
9462
+ tr.transport(blob.getSource(), blob.type, { ruid: self.uid });
9463
+ } else {
9464
+ exec(blob.getSource());
9465
+ }
9466
+ },
9467
+
9468
+ loadFromImage: function(img) {
9469
+ var self = this.getRuntime();
9470
+ return self.shimExec.call(this, 'Image', 'loadFromImage', img.uid);
9471
+ },
9472
+
9473
+ getAsBlob: function(type, quality) {
9474
+ var self = this.getRuntime()
9475
+ , blob = self.shimExec.call(this, 'Image', 'getAsBlob', type, quality)
9476
+ ;
9477
+ if (blob) {
9478
+ return new Blob(self.uid, blob);
9479
+ }
9480
+ return null;
9481
+ },
9482
+
9483
+ getAsDataURL: function() {
9484
+ var self = this.getRuntime()
9485
+ , blob = self.Image.getAsBlob.apply(this, arguments)
9486
+ , frs
9487
+ ;
9488
+ if (!blob) {
9489
+ return null;
9490
+ }
9491
+ frs = new FileReaderSync();
9492
+ return frs.readAsDataURL(blob);
9493
+ }
9494
+ };
9495
+
9496
+ return (extensions.Image = Image);
9497
+ });
9498
+
9499
+ // Included from: src/javascript/runtime/silverlight/Runtime.js
9500
+
9501
+ /**
9502
+ * RunTime.js
9503
+ *
9504
+ * Copyright 2013, Moxiecode Systems AB
9505
+ * Released under GPL License.
9506
+ *
9507
+ * License: http://www.plupload.com/license
9508
+ * Contributing: http://www.plupload.com/contributing
9509
+ */
9510
+
9511
+ /*global ActiveXObject:true */
9512
+
9513
+ /**
9514
+ Defines constructor for Silverlight runtime.
9515
+
9516
+ @class moxie/runtime/silverlight/Runtime
9517
+ @private
9518
+ */
9519
+ define("moxie/runtime/silverlight/Runtime", [
9520
+ "moxie/core/utils/Basic",
9521
+ "moxie/core/utils/Env",
9522
+ "moxie/core/utils/Dom",
9523
+ "moxie/core/Exceptions",
9524
+ "moxie/runtime/Runtime"
9525
+ ], function(Basic, Env, Dom, x, Runtime) {
9526
+
9527
+ var type = "silverlight", extensions = {};
9528
+
9529
+ function isInstalled(version) {
9530
+ var isVersionSupported = false, control = null, actualVer,
9531
+ actualVerArray, reqVerArray, requiredVersionPart, actualVersionPart, index = 0;
9532
+
9533
+ try {
9534
+ try {
9535
+ control = new ActiveXObject('AgControl.AgControl');
9536
+
9537
+ if (control.IsVersionSupported(version)) {
9538
+ isVersionSupported = true;
9539
+ }
9540
+
9541
+ control = null;
9542
+ } catch (e) {
9543
+ var plugin = navigator.plugins["Silverlight Plug-In"];
9544
+
9545
+ if (plugin) {
9546
+ actualVer = plugin.description;
9547
+
9548
+ if (actualVer === "1.0.30226.2") {
9549
+ actualVer = "2.0.30226.2";
9550
+ }
9551
+
9552
+ actualVerArray = actualVer.split(".");
9553
+
9554
+ while (actualVerArray.length > 3) {
9555
+ actualVerArray.pop();
9556
+ }
9557
+
9558
+ while ( actualVerArray.length < 4) {
9559
+ actualVerArray.push(0);
9560
+ }
9561
+
9562
+ reqVerArray = version.split(".");
9563
+
9564
+ while (reqVerArray.length > 4) {
9565
+ reqVerArray.pop();
9566
+ }
9567
+
9568
+ do {
9569
+ requiredVersionPart = parseInt(reqVerArray[index], 10);
9570
+ actualVersionPart = parseInt(actualVerArray[index], 10);
9571
+ index++;
9572
+ } while (index < reqVerArray.length && requiredVersionPart === actualVersionPart);
9573
+
9574
+ if (requiredVersionPart <= actualVersionPart && !isNaN(requiredVersionPart)) {
9575
+ isVersionSupported = true;
9576
+ }
9577
+ }
9578
+ }
9579
+ } catch (e2) {
9580
+ isVersionSupported = false;
9581
+ }
9582
+
9583
+ return isVersionSupported;
9584
+ }
9585
+
9586
+ /**
9587
+ Constructor for the Silverlight Runtime
9588
+
9589
+ @class SilverlightRuntime
9590
+ @extends Runtime
9591
+ */
9592
+ function SilverlightRuntime(options) {
9593
+ var I = this, initTimer;
9594
+
9595
+ options = Basic.extend({ xap_url: Env.xap_url }, options);
9596
+
9597
+ Runtime.call(this, options, type, {
9598
+ access_binary: Runtime.capTrue,
9599
+ access_image_binary: Runtime.capTrue,
9600
+ display_media: Runtime.capTrue,
9601
+ do_cors: Runtime.capTrue,
9602
+ drag_and_drop: false,
9603
+ report_upload_progress: Runtime.capTrue,
9604
+ resize_image: Runtime.capTrue,
9605
+ return_response_headers: function(value) {
9606
+ return value && I.mode === 'client';
9607
+ },
9608
+ return_response_type: function(responseType) {
9609
+ if (responseType !== 'json') {
9610
+ return true;
9611
+ } else {
9612
+ return !!window.JSON;
9613
+ }
9614
+ },
9615
+ return_status_code: function(code) {
9616
+ return I.mode === 'client' || !Basic.arrayDiff(code, [200, 404]);
9617
+ },
9618
+ select_file: Runtime.capTrue,
9619
+ select_multiple: Runtime.capTrue,
9620
+ send_binary_string: Runtime.capTrue,
9621
+ send_browser_cookies: function(value) {
9622
+ return value && I.mode === 'browser';
9623
+ },
9624
+ send_custom_headers: function(value) {
9625
+ return value && I.mode === 'client';
9626
+ },
9627
+ send_multipart: Runtime.capTrue,
9628
+ slice_blob: Runtime.capTrue,
9629
+ stream_upload: true,
9630
+ summon_file_dialog: false,
9631
+ upload_filesize: Runtime.capTrue,
9632
+ use_http_method: function(methods) {
9633
+ return I.mode === 'client' || !Basic.arrayDiff(methods, ['GET', 'POST']);
9634
+ }
9635
+ }, {
9636
+ // capabilities that require specific mode
9637
+ return_response_headers: function(value) {
9638
+ return value ? 'client' : 'browser';
9639
+ },
9640
+ return_status_code: function(code) {
9641
+ return Basic.arrayDiff(code, [200, 404]) ? 'client' : ['client', 'browser'];
9642
+ },
9643
+ send_browser_cookies: function(value) {
9644
+ return value ? 'browser' : 'client';
9645
+ },
9646
+ send_custom_headers: function(value) {
9647
+ return value ? 'client' : 'browser';
9648
+ },
9649
+ use_http_method: function(methods) {
9650
+ return Basic.arrayDiff(methods, ['GET', 'POST']) ? 'client' : ['client', 'browser'];
9651
+ }
9652
+ });
9653
+
9654
+
9655
+ // minimal requirement
9656
+ if (!isInstalled('2.0.31005.0') || Env.browser === 'Opera') {
9657
+ this.mode = false;
9658
+ }
9659
+
9660
+
9661
+ Basic.extend(this, {
9662
+ getShim: function() {
9663
+ return Dom.get(this.uid).content.Moxie;
9664
+ },
9665
+
9666
+ shimExec: function(component, action) {
9667
+ var args = [].slice.call(arguments, 2);
9668
+ return I.getShim().exec(this.uid, component, action, args);
9669
+ },
9670
+
9671
+ init : function() {
9672
+ var container;
9673
+
9674
+ container = this.getShimContainer();
9675
+
9676
+ container.innerHTML = '<object id="' + this.uid + '" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">' +
9677
+ '<param name="source" value="' + options.xap_url + '"/>' +
9678
+ '<param name="background" value="Transparent"/>' +
9679
+ '<param name="windowless" value="true"/>' +
9680
+ '<param name="enablehtmlaccess" value="true"/>' +
9681
+ '<param name="initParams" value="uid=' + this.uid + ',target=' + Env.global_event_dispatcher + '"/>' +
9682
+ '</object>';
9683
+
9684
+ // Init is dispatched by the shim
9685
+ initTimer = setTimeout(function() {
9686
+ if (I && !I.initialized) { // runtime might be already destroyed by this moment
9687
+ I.trigger("Error", new x.RuntimeError(x.RuntimeError.NOT_INIT_ERR));
9688
+ }
9689
+ }, Env.OS !== 'Windows'? 10000 : 5000); // give it more time to initialize in non Windows OS (like Mac)
9690
+ },
9691
+
9692
+ destroy: (function(destroy) { // extend default destroy method
9693
+ return function() {
9694
+ destroy.call(I);
9695
+ clearTimeout(initTimer); // initialization check might be still onwait
9696
+ options = initTimer = destroy = I = null;
9697
+ };
9698
+ }(this.destroy))
9699
+
9700
+ }, extensions);
9701
+ }
9702
+
9703
+ Runtime.addConstructor(type, SilverlightRuntime);
9704
+
9705
+ return extensions;
9706
+ });
9707
+
9708
+ // Included from: src/javascript/runtime/silverlight/file/Blob.js
9709
+
9710
+ /**
9711
+ * Blob.js
9712
+ *
9713
+ * Copyright 2013, Moxiecode Systems AB
9714
+ * Released under GPL License.
9715
+ *
9716
+ * License: http://www.plupload.com/license
9717
+ * Contributing: http://www.plupload.com/contributing
9718
+ */
9719
+
9720
+ /**
9721
+ @class moxie/runtime/silverlight/file/Blob
9722
+ @private
9723
+ */
9724
+ define("moxie/runtime/silverlight/file/Blob", [
9725
+ "moxie/runtime/silverlight/Runtime",
9726
+ "moxie/core/utils/Basic",
9727
+ "moxie/runtime/flash/file/Blob"
9728
+ ], function(extensions, Basic, Blob) {
9729
+ return (extensions.Blob = Basic.extend({}, Blob));
9730
+ });
9731
+
9732
+ // Included from: src/javascript/runtime/silverlight/file/FileInput.js
9733
+
9734
+ /**
9735
+ * FileInput.js
9736
+ *
9737
+ * Copyright 2013, Moxiecode Systems AB
9738
+ * Released under GPL License.
9739
+ *
9740
+ * License: http://www.plupload.com/license
9741
+ * Contributing: http://www.plupload.com/contributing
9742
+ */
9743
+
9744
+ /**
9745
+ @class moxie/runtime/silverlight/file/FileInput
9746
+ @private
9747
+ */
9748
+ define("moxie/runtime/silverlight/file/FileInput", [
9749
+ "moxie/runtime/silverlight/Runtime"
9750
+ ], function(extensions) {
9751
+
9752
+ var FileInput = {
9753
+ init: function(options) {
9754
+
9755
+ function toFilters(accept) {
9756
+ var filter = '';
9757
+ for (var i = 0; i < accept.length; i++) {
9758
+ filter += (filter !== '' ? '|' : '') + accept[i].title + " | *." + accept[i].extensions.replace(/,/g, ';*.');
9759
+ }
9760
+ return filter;
9761
+ }
9762
+
9763
+ this.getRuntime().shimExec.call(this, 'FileInput', 'init', toFilters(options.accept), options.name, options.multiple);
9764
+ this.trigger('ready');
9765
+ }
9766
+ };
9767
+
9768
+ return (extensions.FileInput = FileInput);
9769
+ });
9770
+
9771
+ // Included from: src/javascript/runtime/silverlight/file/FileDrop.js
9772
+
9773
+ /**
9774
+ * FileDrop.js
9775
+ *
9776
+ * Copyright 2013, Moxiecode Systems AB
9777
+ * Released under GPL License.
9778
+ *
9779
+ * License: http://www.plupload.com/license
9780
+ * Contributing: http://www.plupload.com/contributing
9781
+ */
9782
+
9783
+ /**
9784
+ @class moxie/runtime/silverlight/file/FileDrop
9785
+ @private
9786
+ */
9787
+ define("moxie/runtime/silverlight/file/FileDrop", [
9788
+ "moxie/runtime/silverlight/Runtime",
9789
+ "moxie/core/utils/Dom",
9790
+ "moxie/core/utils/Events"
9791
+ ], function(extensions, Dom, Events) {
9792
+
9793
+ // not exactly useful, since works only in safari (...crickets...)
9794
+ var FileDrop = {
9795
+ init: function() {
9796
+ var comp = this, self = comp.getRuntime(), dropZone;
9797
+
9798
+ dropZone = self.getShimContainer();
9799
+
9800
+ Events.addEvent(dropZone, 'dragover', function(e) {
9801
+ e.preventDefault();
9802
+ e.stopPropagation();
9803
+ e.dataTransfer.dropEffect = 'copy';
9804
+ }, comp.uid);
9805
+
9806
+ Events.addEvent(dropZone, 'dragenter', function(e) {
9807
+ e.preventDefault();
9808
+ var flag = Dom.get(self.uid).dragEnter(e);
9809
+ // If handled, then stop propagation of event in DOM
9810
+ if (flag) {
9811
+ e.stopPropagation();
9812
+ }
9813
+ }, comp.uid);
9814
+
9815
+ Events.addEvent(dropZone, 'drop', function(e) {
9816
+ e.preventDefault();
9817
+ var flag = Dom.get(self.uid).dragDrop(e);
9818
+ // If handled, then stop propagation of event in DOM
9819
+ if (flag) {
9820
+ e.stopPropagation();
9821
+ }
9822
+ }, comp.uid);
9823
+
9824
+ return self.shimExec.call(this, 'FileDrop', 'init');
9825
+ }
9826
+ };
9827
+
9828
+ return (extensions.FileDrop = FileDrop);
9829
+ });
9830
+
9831
+ // Included from: src/javascript/runtime/silverlight/file/FileReader.js
9832
+
9833
+ /**
9834
+ * FileReader.js
9835
+ *
9836
+ * Copyright 2013, Moxiecode Systems AB
9837
+ * Released under GPL License.
9838
+ *
9839
+ * License: http://www.plupload.com/license
9840
+ * Contributing: http://www.plupload.com/contributing
9841
+ */
9842
+
9843
+ /**
9844
+ @class moxie/runtime/silverlight/file/FileReader
9845
+ @private
9846
+ */
9847
+ define("moxie/runtime/silverlight/file/FileReader", [
9848
+ "moxie/runtime/silverlight/Runtime",
9849
+ "moxie/core/utils/Basic",
9850
+ "moxie/runtime/flash/file/FileReader"
9851
+ ], function(extensions, Basic, FileReader) {
9852
+ return (extensions.FileReader = Basic.extend({}, FileReader));
9853
+ });
9854
+
9855
+ // Included from: src/javascript/runtime/silverlight/file/FileReaderSync.js
9856
+
9857
+ /**
9858
+ * FileReaderSync.js
9859
+ *
9860
+ * Copyright 2013, Moxiecode Systems AB
9861
+ * Released under GPL License.
9862
+ *
9863
+ * License: http://www.plupload.com/license
9864
+ * Contributing: http://www.plupload.com/contributing
9865
+ */
9866
+
9867
+ /**
9868
+ @class moxie/runtime/silverlight/file/FileReaderSync
9869
+ @private
9870
+ */
9871
+ define("moxie/runtime/silverlight/file/FileReaderSync", [
9872
+ "moxie/runtime/silverlight/Runtime",
9873
+ "moxie/core/utils/Basic",
9874
+ "moxie/runtime/flash/file/FileReaderSync"
9875
+ ], function(extensions, Basic, FileReaderSync) {
9876
+ return (extensions.FileReaderSync = Basic.extend({}, FileReaderSync));
9877
+ });
9878
+
9879
+ // Included from: src/javascript/runtime/silverlight/xhr/XMLHttpRequest.js
9880
+
9881
+ /**
9882
+ * XMLHttpRequest.js
9883
+ *
9884
+ * Copyright 2013, Moxiecode Systems AB
9885
+ * Released under GPL License.
9886
+ *
9887
+ * License: http://www.plupload.com/license
9888
+ * Contributing: http://www.plupload.com/contributing
9889
+ */
9890
+
9891
+ /**
9892
+ @class moxie/runtime/silverlight/xhr/XMLHttpRequest
9893
+ @private
9894
+ */
9895
+ define("moxie/runtime/silverlight/xhr/XMLHttpRequest", [
9896
+ "moxie/runtime/silverlight/Runtime",
9897
+ "moxie/core/utils/Basic",
9898
+ "moxie/runtime/flash/xhr/XMLHttpRequest"
9899
+ ], function(extensions, Basic, XMLHttpRequest) {
9900
+ return (extensions.XMLHttpRequest = Basic.extend({}, XMLHttpRequest));
9901
+ });
9902
+
9903
+ // Included from: src/javascript/runtime/silverlight/runtime/Transporter.js
9904
+
9905
+ /**
9906
+ * Transporter.js
9907
+ *
9908
+ * Copyright 2013, Moxiecode Systems AB
9909
+ * Released under GPL License.
9910
+ *
9911
+ * License: http://www.plupload.com/license
9912
+ * Contributing: http://www.plupload.com/contributing
9913
+ */
9914
+
9915
+ /**
9916
+ @class moxie/runtime/silverlight/runtime/Transporter
9917
+ @private
9918
+ */
9919
+ define("moxie/runtime/silverlight/runtime/Transporter", [
9920
+ "moxie/runtime/silverlight/Runtime",
9921
+ "moxie/core/utils/Basic",
9922
+ "moxie/runtime/flash/runtime/Transporter"
9923
+ ], function(extensions, Basic, Transporter) {
9924
+ return (extensions.Transporter = Basic.extend({}, Transporter));
9925
+ });
9926
+
9927
+ // Included from: src/javascript/runtime/silverlight/image/Image.js
9928
+
9929
+ /**
9930
+ * Image.js
9931
+ *
9932
+ * Copyright 2013, Moxiecode Systems AB
9933
+ * Released under GPL License.
9934
+ *
9935
+ * License: http://www.plupload.com/license
9936
+ * Contributing: http://www.plupload.com/contributing
9937
+ */
9938
+
9939
+ /**
9940
+ @class moxie/runtime/silverlight/image/Image
9941
+ @private
9942
+ */
9943
+ define("moxie/runtime/silverlight/image/Image", [
9944
+ "moxie/runtime/silverlight/Runtime",
9945
+ "moxie/core/utils/Basic",
9946
+ "moxie/runtime/flash/image/Image"
9947
+ ], function(extensions, Basic, Image) {
9948
+ return (extensions.Image = Basic.extend({}, Image, {
9949
+
9950
+ getInfo: function() {
9951
+ var self = this.getRuntime()
9952
+ , grps = ['tiff', 'exif', 'gps']
9953
+ , info = { meta: {} }
9954
+ , rawInfo = self.shimExec.call(this, 'Image', 'getInfo')
9955
+ ;
9956
+
9957
+ if (rawInfo.meta) {
9958
+ Basic.each(grps, function(grp) {
9959
+ var meta = rawInfo.meta[grp]
9960
+ , tag
9961
+ , i
9962
+ , length
9963
+ , value
9964
+ ;
9965
+ if (meta && meta.keys) {
9966
+ info.meta[grp] = {};
9967
+ for (i = 0, length = meta.keys.length; i < length; i++) {
9968
+ tag = meta.keys[i];
9969
+ value = meta[tag];
9970
+ if (value) {
9971
+ // convert numbers
9972
+ if (/^(\d|[1-9]\d+)$/.test(value)) { // integer (make sure doesn't start with zero)
9973
+ value = parseInt(value, 10);
9974
+ } else if (/^\d*\.\d+$/.test(value)) { // double
9975
+ value = parseFloat(value);
9976
+ }
9977
+ info.meta[grp][tag] = value;
9978
+ }
9979
+ }
9980
+ }
9981
+ });
9982
+ }
9983
+
9984
+ info.width = parseInt(rawInfo.width, 10);
9985
+ info.height = parseInt(rawInfo.height, 10);
9986
+ info.size = parseInt(rawInfo.size, 10);
9987
+ info.type = rawInfo.type;
9988
+ info.name = rawInfo.name;
9989
+
9990
+ return info;
9991
+ }
9992
+ }));
9993
+ });
9994
+
9995
+ // Included from: src/javascript/runtime/html4/Runtime.js
9996
+
9997
+ /**
9998
+ * Runtime.js
9999
+ *
10000
+ * Copyright 2013, Moxiecode Systems AB
10001
+ * Released under GPL License.
10002
+ *
10003
+ * License: http://www.plupload.com/license
10004
+ * Contributing: http://www.plupload.com/contributing
10005
+ */
10006
+
10007
+ /*global File:true */
10008
+
10009
+ /**
10010
+ Defines constructor for HTML4 runtime.
10011
+
10012
+ @class moxie/runtime/html4/Runtime
10013
+ @private
10014
+ */
10015
+ define("moxie/runtime/html4/Runtime", [
10016
+ "moxie/core/utils/Basic",
10017
+ "moxie/core/Exceptions",
10018
+ "moxie/runtime/Runtime",
10019
+ "moxie/core/utils/Env"
10020
+ ], function(Basic, x, Runtime, Env) {
10021
+
10022
+ var type = 'html4', extensions = {};
10023
+
10024
+ function Html4Runtime(options) {
10025
+ var I = this
10026
+ , Test = Runtime.capTest
10027
+ , True = Runtime.capTrue
10028
+ ;
10029
+
10030
+ Runtime.call(this, options, type, {
10031
+ access_binary: Test(window.FileReader || window.File && File.getAsDataURL),
10032
+ access_image_binary: false,
10033
+ display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))),
10034
+ do_cors: false,
10035
+ drag_and_drop: false,
10036
+ filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest
10037
+ return (Env.browser === 'Chrome' && Env.version >= 28) || (Env.browser === 'IE' && Env.version >= 10);
10038
+ }()),
10039
+ resize_image: function() {
10040
+ return extensions.Image && I.can('access_binary') && Env.can('create_canvas');
10041
+ },
10042
+ report_upload_progress: false,
10043
+ return_response_headers: false,
10044
+ return_response_type: function(responseType) {
10045
+ if (responseType === 'json' && !!window.JSON) {
10046
+ return true;
10047
+ }
10048
+ return !!~Basic.inArray(responseType, ['text', 'document', '']);
10049
+ },
10050
+ return_status_code: function(code) {
10051
+ return !Basic.arrayDiff(code, [200, 404]);
10052
+ },
10053
+ select_file: function() {
10054
+ return Env.can('use_fileinput');
10055
+ },
10056
+ select_multiple: false,
10057
+ send_binary_string: false,
10058
+ send_custom_headers: false,
10059
+ send_multipart: true,
10060
+ slice_blob: false,
10061
+ stream_upload: function() {
10062
+ return I.can('select_file');
10063
+ },
10064
+ summon_file_dialog: Test(function() { // yeah... some dirty sniffing here...
10065
+ return (Env.browser === 'Firefox' && Env.version >= 4) ||
10066
+ (Env.browser === 'Opera' && Env.version >= 12) ||
10067
+ !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']);
10068
+ }()),
10069
+ upload_filesize: True,
10070
+ use_http_method: function(methods) {
10071
+ return !Basic.arrayDiff(methods, ['GET', 'POST']);
10072
+ }
10073
+ });
10074
+
10075
+
10076
+ Basic.extend(this, {
10077
+ init : function() {
10078
+ this.trigger("Init");
10079
+ },
10080
+
10081
+ destroy: (function(destroy) { // extend default destroy method
10082
+ return function() {
10083
+ destroy.call(I);
10084
+ destroy = I = null;
10085
+ };
10086
+ }(this.destroy))
10087
+ });
10088
+
10089
+ Basic.extend(this.getShim(), extensions);
10090
+ }
10091
+
10092
+ Runtime.addConstructor(type, Html4Runtime);
10093
+
10094
+ return extensions;
10095
+ });
10096
+
10097
+ // Included from: src/javascript/runtime/html4/file/FileInput.js
10098
+
10099
+ /**
10100
+ * FileInput.js
10101
+ *
10102
+ * Copyright 2013, Moxiecode Systems AB
10103
+ * Released under GPL License.
10104
+ *
10105
+ * License: http://www.plupload.com/license
10106
+ * Contributing: http://www.plupload.com/contributing
10107
+ */
10108
+
10109
+ /**
10110
+ @class moxie/runtime/html4/file/FileInput
10111
+ @private
10112
+ */
10113
+ define("moxie/runtime/html4/file/FileInput", [
10114
+ "moxie/runtime/html4/Runtime",
10115
+ "moxie/core/utils/Basic",
10116
+ "moxie/core/utils/Dom",
10117
+ "moxie/core/utils/Events",
10118
+ "moxie/core/utils/Mime",
10119
+ "moxie/core/utils/Env"
10120
+ ], function(extensions, Basic, Dom, Events, Mime, Env) {
10121
+
10122
+ function FileInput() {
10123
+ var _uid, _files = [], _mimes = [], _options;
10124
+
10125
+ function addInput() {
10126
+ var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid;
10127
+
10128
+ uid = Basic.guid('uid_');
10129
+
10130
+ shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE
10131
+
10132
+ if (_uid) { // move previous form out of the view
10133
+ currForm = Dom.get(_uid + '_form');
10134
+ if (currForm) {
10135
+ Basic.extend(currForm.style, { top: '100%' });
10136
+ }
10137
+ }
10138
+
10139
+ // build form in DOM, since innerHTML version not able to submit file for some reason
10140
+ form = document.createElement('form');
10141
+ form.setAttribute('id', uid + '_form');
10142
+ form.setAttribute('method', 'post');
10143
+ form.setAttribute('enctype', 'multipart/form-data');
10144
+ form.setAttribute('encoding', 'multipart/form-data');
10145
+
10146
+ Basic.extend(form.style, {
10147
+ overflow: 'hidden',
10148
+ position: 'absolute',
10149
+ top: 0,
10150
+ left: 0,
10151
+ width: '100%',
10152
+ height: '100%'
10153
+ });
10154
+
10155
+ input = document.createElement('input');
10156
+ input.setAttribute('id', uid);
10157
+ input.setAttribute('type', 'file');
10158
+ input.setAttribute('name', _options.name || 'Filedata');
10159
+ input.setAttribute('accept', _mimes.join(','));
10160
+
10161
+ Basic.extend(input.style, {
10162
+ fontSize: '999px',
10163
+ opacity: 0
10164
+ });
10165
+
10166
+ form.appendChild(input);
10167
+ shimContainer.appendChild(form);
10168
+
10169
+ // prepare file input to be placed underneath the browse_button element
10170
+ Basic.extend(input.style, {
10171
+ position: 'absolute',
10172
+ top: 0,
10173
+ left: 0,
10174
+ width: '100%',
10175
+ height: '100%'
10176
+ });
10177
+
10178
+ if (Env.browser === 'IE' && Env.version < 10) {
10179
+ Basic.extend(input.style, {
10180
+ filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)"
10181
+ });
10182
+ }
10183
+
10184
+ input.onchange = function() { // there should be only one handler for this
10185
+ var file;
10186
+
10187
+ if (!this.value) {
10188
+ return;
10189
+ }
10190
+
10191
+ if (this.files) {
10192
+ file = this.files[0];
10193
+ } else {
10194
+ file = {
10195
+ name: this.value
10196
+ };
10197
+ }
10198
+
10199
+ _files = [file];
10200
+
10201
+ this.onchange = function() {}; // clear event handler
10202
+ addInput.call(comp);
10203
+
10204
+ // after file is initialized as o.File, we need to update form and input ids
10205
+ comp.bind('change', function onChange() {
10206
+ var input = Dom.get(uid), form = Dom.get(uid + '_form'), file;
10207
+
10208
+ comp.unbind('change', onChange);
10209
+
10210
+ if (comp.files.length && input && form) {
10211
+ file = comp.files[0];
10212
+
10213
+ input.setAttribute('id', file.uid);
10214
+ form.setAttribute('id', file.uid + '_form');
10215
+
10216
+ // set upload target
10217
+ form.setAttribute('target', file.uid + '_iframe');
10218
+ }
10219
+ input = form = null;
10220
+ }, 998);
10221
+
10222
+ input = form = null;
10223
+ comp.trigger('change');
10224
+ };
10225
+
10226
+
10227
+ // route click event to the input
10228
+ if (I.can('summon_file_dialog')) {
10229
+ browseButton = Dom.get(_options.browse_button);
10230
+ Events.removeEvent(browseButton, 'click', comp.uid);
10231
+ Events.addEvent(browseButton, 'click', function(e) {
10232
+ if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file]
10233
+ input.click();
10234
+ }
10235
+ e.preventDefault();
10236
+ }, comp.uid);
10237
+ }
10238
+
10239
+ _uid = uid;
10240
+
10241
+ shimContainer = currForm = browseButton = null;
10242
+ }
10243
+
10244
+ Basic.extend(this, {
10245
+ init: function(options) {
10246
+ var comp = this, I = comp.getRuntime(), shimContainer;
10247
+
10248
+ // figure out accept string
10249
+ _options = options;
10250
+ _mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension'));
10251
+
10252
+ shimContainer = I.getShimContainer();
10253
+
10254
+ (function() {
10255
+ var browseButton, zIndex, top;
10256
+
10257
+ browseButton = Dom.get(options.browse_button);
10258
+
10259
+ // Route click event to the input[type=file] element for browsers that support such behavior
10260
+ if (I.can('summon_file_dialog')) {
10261
+ if (Dom.getStyle(browseButton, 'position') === 'static') {
10262
+ browseButton.style.position = 'relative';
10263
+ }
10264
+
10265
+ zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1;
10266
+
10267
+ browseButton.style.zIndex = zIndex;
10268
+ shimContainer.style.zIndex = zIndex - 1;
10269
+ }
10270
+
10271
+ /* Since we have to place input[type=file] on top of the browse_button for some browsers,
10272
+ browse_button loses interactivity, so we restore it here */
10273
+ top = I.can('summon_file_dialog') ? browseButton : shimContainer;
10274
+
10275
+ Events.addEvent(top, 'mouseover', function() {
10276
+ comp.trigger('mouseenter');
10277
+ }, comp.uid);
10278
+
10279
+ Events.addEvent(top, 'mouseout', function() {
10280
+ comp.trigger('mouseleave');
10281
+ }, comp.uid);
10282
+
10283
+ Events.addEvent(top, 'mousedown', function() {
10284
+ comp.trigger('mousedown');
10285
+ }, comp.uid);
10286
+
10287
+ Events.addEvent(Dom.get(options.container), 'mouseup', function() {
10288
+ comp.trigger('mouseup');
10289
+ }, comp.uid);
10290
+
10291
+ browseButton = null;
10292
+ }());
10293
+
10294
+ addInput.call(this);
10295
+
10296
+ shimContainer = null;
10297
+
10298
+ // trigger ready event asynchronously
10299
+ comp.trigger({
10300
+ type: 'ready',
10301
+ async: true
10302
+ });
10303
+ },
10304
+
10305
+ getFiles: function() {
10306
+ return _files;
10307
+ },
10308
+
10309
+ disable: function(state) {
10310
+ var input;
10311
+
10312
+ if ((input = Dom.get(_uid))) {
10313
+ input.disabled = !!state;
10314
+ }
10315
+ },
10316
+
10317
+ destroy: function() {
10318
+ var I = this.getRuntime()
10319
+ , shim = I.getShim()
10320
+ , shimContainer = I.getShimContainer()
10321
+ ;
10322
+
10323
+ Events.removeAllEvents(shimContainer, this.uid);
10324
+ Events.removeAllEvents(_options && Dom.get(_options.container), this.uid);
10325
+ Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid);
10326
+
10327
+ if (shimContainer) {
10328
+ shimContainer.innerHTML = '';
10329
+ }
10330
+
10331
+ shim.removeInstance(this.uid);
10332
+
10333
+ _uid = _files = _mimes = _options = shimContainer = shim = null;
10334
+ }
10335
+ });
10336
+ }
10337
+
10338
+ return (extensions.FileInput = FileInput);
10339
+ });
10340
+
10341
+ // Included from: src/javascript/runtime/html4/file/FileReader.js
10342
+
10343
+ /**
10344
+ * FileReader.js
10345
+ *
10346
+ * Copyright 2013, Moxiecode Systems AB
10347
+ * Released under GPL License.
10348
+ *
10349
+ * License: http://www.plupload.com/license
10350
+ * Contributing: http://www.plupload.com/contributing
10351
+ */
10352
+
10353
+ /**
10354
+ @class moxie/runtime/html4/file/FileReader
10355
+ @private
10356
+ */
10357
+ define("moxie/runtime/html4/file/FileReader", [
10358
+ "moxie/runtime/html4/Runtime",
10359
+ "moxie/runtime/html5/file/FileReader"
10360
+ ], function(extensions, FileReader) {
10361
+ return (extensions.FileReader = FileReader);
10362
+ });
10363
+
10364
+ // Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js
10365
+
10366
+ /**
10367
+ * XMLHttpRequest.js
10368
+ *
10369
+ * Copyright 2013, Moxiecode Systems AB
10370
+ * Released under GPL License.
10371
+ *
10372
+ * License: http://www.plupload.com/license
10373
+ * Contributing: http://www.plupload.com/contributing
10374
+ */
10375
+
10376
+ /**
10377
+ @class moxie/runtime/html4/xhr/XMLHttpRequest
10378
+ @private
10379
+ */
10380
+ define("moxie/runtime/html4/xhr/XMLHttpRequest", [
10381
+ "moxie/runtime/html4/Runtime",
10382
+ "moxie/core/utils/Basic",
10383
+ "moxie/core/utils/Dom",
10384
+ "moxie/core/utils/Url",
10385
+ "moxie/core/Exceptions",
10386
+ "moxie/core/utils/Events",
10387
+ "moxie/file/Blob",
10388
+ "moxie/xhr/FormData"
10389
+ ], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) {
10390
+
10391
+ function XMLHttpRequest() {
10392
+ var _status, _response, _iframe;
10393
+
10394
+ function cleanup(cb) {
10395
+ var target = this, uid, form, inputs, i, hasFile = false;
10396
+
10397
+ if (!_iframe) {
10398
+ return;
10399
+ }
10400
+
10401
+ uid = _iframe.id.replace(/_iframe$/, '');
10402
+
10403
+ form = Dom.get(uid + '_form');
10404
+ if (form) {
10405
+ inputs = form.getElementsByTagName('input');
10406
+ i = inputs.length;
10407
+
10408
+ while (i--) {
10409
+ switch (inputs[i].getAttribute('type')) {
10410
+ case 'hidden':
10411
+ inputs[i].parentNode.removeChild(inputs[i]);
10412
+ break;
10413
+ case 'file':
10414
+ hasFile = true; // flag the case for later
10415
+ break;
10416
+ }
10417
+ }
10418
+ inputs = [];
10419
+
10420
+ if (!hasFile) { // we need to keep the form for sake of possible retries
10421
+ form.parentNode.removeChild(form);
10422
+ }
10423
+ form = null;
10424
+ }
10425
+
10426
+ // without timeout, request is marked as canceled (in console)
10427
+ setTimeout(function() {
10428
+ Events.removeEvent(_iframe, 'load', target.uid);
10429
+ if (_iframe.parentNode) { // #382
10430
+ _iframe.parentNode.removeChild(_iframe);
10431
+ }
10432
+
10433
+ // check if shim container has any other children, if - not, remove it as well
10434
+ var shimContainer = target.getRuntime().getShimContainer();
10435
+ if (!shimContainer.children.length) {
10436
+ shimContainer.parentNode.removeChild(shimContainer);
10437
+ }
10438
+
10439
+ shimContainer = _iframe = null;
10440
+ cb();
10441
+ }, 1);
10442
+ }
10443
+
10444
+ Basic.extend(this, {
10445
+ send: function(meta, data) {
10446
+ var target = this, I = target.getRuntime(), uid, form, input, blob;
10447
+
10448
+ _status = _response = null;
10449
+
10450
+ function createIframe() {
10451
+ var container = I.getShimContainer() || document.body
10452
+ , temp = document.createElement('div')
10453
+ ;
10454
+
10455
+ // IE 6 won't be able to set the name using setAttribute or iframe.name
10456
+ temp.innerHTML = '<iframe id="' + uid + '_iframe" name="' + uid + '_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>';
10457
+ _iframe = temp.firstChild;
10458
+ container.appendChild(_iframe);
10459
+
10460
+ /* _iframe.onreadystatechange = function() {
10461
+ console.info(_iframe.readyState);
10462
+ };*/
10463
+
10464
+ Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8
10465
+ var el;
10466
+
10467
+ try {
10468
+ el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document;
10469
+
10470
+ // try to detect some standard error pages
10471
+ if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error
10472
+ _status = el.title.replace(/^(\d+).*$/, '$1');
10473
+ } else {
10474
+ _status = 200;
10475
+ // get result
10476
+ _response = Basic.trim(el.body.innerHTML);
10477
+
10478
+ // we need to fire these at least once
10479
+ target.trigger({
10480
+ type: 'progress',
10481
+ loaded: _response.length,
10482
+ total: _response.length
10483
+ });
10484
+
10485
+ if (blob) { // if we were uploading a file
10486
+ target.trigger({
10487
+ type: 'uploadprogress',
10488
+ loaded: blob.size || 1025,
10489
+ total: blob.size || 1025
10490
+ });
10491
+ }
10492
+ }
10493
+ } catch (ex) {
10494
+ if (Url.hasSameOrigin(meta.url)) {
10495
+ // if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm
10496
+ // which obviously results to cross domain error (wtf?)
10497
+ _status = 404;
10498
+ } else {
10499
+ cleanup.call(target, function() {
10500
+ target.trigger('error');
10501
+ });
10502
+ return;
10503
+ }
10504
+ }
10505
+
10506
+ cleanup.call(target, function() {
10507
+ target.trigger('load');
10508
+ });
10509
+ }, target.uid);
10510
+ } // end createIframe
10511
+
10512
+ // prepare data to be sent and convert if required
10513
+ if (data instanceof FormData && data.hasBlob()) {
10514
+ blob = data.getBlob();
10515
+ uid = blob.uid;
10516
+ input = Dom.get(uid);
10517
+ form = Dom.get(uid + '_form');
10518
+ if (!form) {
10519
+ throw new x.DOMException(x.DOMException.NOT_FOUND_ERR);
10520
+ }
10521
+ } else {
10522
+ uid = Basic.guid('uid_');
10523
+
10524
+ form = document.createElement('form');
10525
+ form.setAttribute('id', uid + '_form');
10526
+ form.setAttribute('method', meta.method);
10527
+ form.setAttribute('enctype', 'multipart/form-data');
10528
+ form.setAttribute('encoding', 'multipart/form-data');
10529
+ form.setAttribute('target', uid + '_iframe');
10530
+
10531
+ I.getShimContainer().appendChild(form);
10532
+ }
10533
+
10534
+ if (data instanceof FormData) {
10535
+ data.each(function(value, name) {
10536
+ if (value instanceof Blob) {
10537
+ if (input) {
10538
+ input.setAttribute('name', name);
10539
+ }
10540
+ } else {
10541
+ var hidden = document.createElement('input');
10542
+
10543
+ Basic.extend(hidden, {
10544
+ type : 'hidden',
10545
+ name : name,
10546
+ value : value
10547
+ });
10548
+
10549
+ // make sure that input[type="file"], if it's there, comes last
10550
+ if (input) {
10551
+ form.insertBefore(hidden, input);
10552
+ } else {
10553
+ form.appendChild(hidden);
10554
+ }
10555
+ }
10556
+ });
10557
+ }
10558
+
10559
+ // set destination url
10560
+ form.setAttribute("action", meta.url);
10561
+
10562
+ createIframe();
10563
+ form.submit();
10564
+ target.trigger('loadstart');
10565
+ },
10566
+
10567
+ getStatus: function() {
10568
+ return _status;
10569
+ },
10570
+
10571
+ getResponse: function(responseType) {
10572
+ if ('json' === responseType) {
10573
+ // strip off <pre>..</pre> tags that might be enclosing the response
10574
+ if (Basic.typeOf(_response) === 'string' && !!window.JSON) {
10575
+ try {
10576
+ return JSON.parse(_response.replace(/^\s*<pre[^>]*>/, '').replace(/<\/pre>\s*$/, ''));
10577
+ } catch (ex) {
10578
+ return null;
10579
+ }
10580
+ }
10581
+ } else if ('document' === responseType) {
10582
+
10583
+ }
10584
+ return _response;
10585
+ },
10586
+
10587
+ abort: function() {
10588
+ var target = this;
10589
+
10590
+ if (_iframe && _iframe.contentWindow) {
10591
+ if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome
10592
+ _iframe.contentWindow.stop();
10593
+ } else if (_iframe.contentWindow.document.execCommand) { // IE
10594
+ _iframe.contentWindow.document.execCommand('Stop');
10595
+ } else {
10596
+ _iframe.src = "about:blank";
10597
+ }
10598
+ }
10599
+
10600
+ cleanup.call(this, function() {
10601
+ // target.dispatchEvent('readystatechange');
10602
+ target.dispatchEvent('abort');
10603
+ });
10604
+ }
10605
+ });
10606
+ }
10607
+
10608
+ return (extensions.XMLHttpRequest = XMLHttpRequest);
10609
+ });
10610
+
10611
+ // Included from: src/javascript/runtime/html4/image/Image.js
10612
+
10613
+ /**
10614
+ * Image.js
10615
+ *
10616
+ * Copyright 2013, Moxiecode Systems AB
10617
+ * Released under GPL License.
10618
+ *
10619
+ * License: http://www.plupload.com/license
10620
+ * Contributing: http://www.plupload.com/contributing
10621
+ */
10622
+
10623
+ /**
10624
+ @class moxie/runtime/html4/image/Image
10625
+ @private
10626
+ */
10627
+ define("moxie/runtime/html4/image/Image", [
10628
+ "moxie/runtime/html4/Runtime",
10629
+ "moxie/runtime/html5/image/Image"
10630
+ ], function(extensions, Image) {
10631
+ return (extensions.Image = Image);
10632
+ });
10633
+
10634
+ expose(["moxie/core/utils/Basic","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Env","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/Blob","moxie/file/File","moxie/file/FileInput","moxie/file/FileDrop","moxie/runtime/RuntimeTarget","moxie/file/FileReader","moxie/core/utils/Url","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]);
10635
+ })(this);/**
10636
+ * o.js
10637
+ *
10638
+ * Copyright 2013, Moxiecode Systems AB
10639
+ * Released under GPL License.
10640
+ *
10641
+ * License: http://www.plupload.com/license
10642
+ * Contributing: http://www.plupload.com/contributing
10643
+ */
10644
+
10645
+ /*global moxie:true */
10646
+
10647
+ /**
10648
+ Globally exposed namespace with the most frequently used public classes and handy methods.
10649
+
10650
+ @class o
10651
+ @static
10652
+ @private
10653
+ */
10654
+ (function() {
10655
+ "use strict";
10656
+
10657
+ var o = {}, inArray = moxie.core.utils.Basic.inArray;
10658
+
10659
+ // directly add some public classes
10660
+ // (we do it dynamically here, since for custom builds we cannot know beforehand what modules were included)
10661
+ (function addAlias(ns) {
10662
+ var name, itemType;
10663
+ for (name in ns) {
10664
+ itemType = typeof(ns[name]);
10665
+ if (itemType === 'object' && !~inArray(name, ['Exceptions', 'Env', 'Mime'])) {
10666
+ addAlias(ns[name]);
10667
+ } else if (itemType === 'function') {
10668
+ o[name] = ns[name];
10669
+ }
10670
+ }
10671
+ })(window.moxie);
10672
+
10673
+ // add some manually
10674
+ o.Env = window.moxie.core.utils.Env;
10675
+ o.Mime = window.moxie.core.utils.Mime;
10676
+ o.Exceptions = window.moxie.core.Exceptions;
10677
+
10678
+ // expose globally
10679
+ window.mOxie = o;
10680
+ if (!window.o) {
10681
+ window.o = o;
10682
+ }
10683
+ return o;
10684
+ })();
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/moxie.min.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
3
+ * v1.2.0
4
+ *
5
+ * Copyright 2013, Moxiecode Systems AB
6
+ * Released under GPL License.
7
+ *
8
+ * License: http://www.plupload.com/license
9
+ * Contributing: http://www.plupload.com/contributing
10
+ *
11
+ * Date: 2014-01-16
12
+ */
13
+ !function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r<e.length;++r){if(n=s[e[r]]||o(e[r]),!n)throw"module definition dependecy not found: "+e[r];i.push(n)}t.apply(null,i)}function i(e,i,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(i===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";n(i,function(){s[e]=r.apply(null,arguments)})}function r(e){return!!s[e]}function o(t){for(var n=e,i=t.split(/[.\/]/),r=0;r<i.length;++r){if(!n[i[r]])return;n=n[i[r]]}return n}function a(n){for(var i=0;i<n.length;i++){for(var r=e,o=n[i],a=o.split(/[.\/]/),u=0;u<a.length-1;++u)r[a[u]]===t&&(r[a[u]]={}),r=r[a[u]];r[a[a.length-1]]=s[o]}}var s={},u="moxie/core/utils/Basic",c="moxie/core/I18n",l="moxie/core/utils/Mime",d="moxie/core/utils/Env",f="moxie/core/utils/Dom",p="moxie/core/Exceptions",h="moxie/core/EventTarget",m="moxie/core/utils/Encode",g="moxie/runtime/Runtime",v="moxie/runtime/RuntimeClient",y="moxie/file/Blob",w="moxie/file/File",E="moxie/file/FileInput",_="moxie/file/FileDrop",x="moxie/runtime/RuntimeTarget",R="moxie/file/FileReader",b="moxie/core/utils/Url",T="moxie/file/FileReaderSync",S="moxie/xhr/FormData",A="moxie/xhr/XMLHttpRequest",O="moxie/runtime/Transporter",I="moxie/image/Image",D="moxie/runtime/html5/Runtime",N="moxie/runtime/html5/file/Blob",L="moxie/core/utils/Events",M="moxie/runtime/html5/file/FileInput",C="moxie/runtime/html5/file/FileDrop",F="moxie/runtime/html5/file/FileReader",H="moxie/runtime/html5/xhr/XMLHttpRequest",P="moxie/runtime/html5/utils/BinaryReader",k="moxie/runtime/html5/image/JPEGHeaders",U="moxie/runtime/html5/image/ExifParser",B="moxie/runtime/html5/image/JPEG",z="moxie/runtime/html5/image/PNG",G="moxie/runtime/html5/image/ImageInfo",q="moxie/runtime/html5/image/MegaPixel",X="moxie/runtime/html5/image/Image",j="moxie/runtime/flash/Runtime",V="moxie/runtime/flash/file/Blob",W="moxie/runtime/flash/file/FileInput",Y="moxie/runtime/flash/file/FileReader",$="moxie/runtime/flash/file/FileReaderSync",J="moxie/runtime/flash/xhr/XMLHttpRequest",Z="moxie/runtime/flash/runtime/Transporter",K="moxie/runtime/flash/image/Image",Q="moxie/runtime/silverlight/Runtime",et="moxie/runtime/silverlight/file/Blob",tt="moxie/runtime/silverlight/file/FileInput",nt="moxie/runtime/silverlight/file/FileDrop",it="moxie/runtime/silverlight/file/FileReader",rt="moxie/runtime/silverlight/file/FileReaderSync",ot="moxie/runtime/silverlight/xhr/XMLHttpRequest",at="moxie/runtime/silverlight/runtime/Transporter",st="moxie/runtime/silverlight/image/Image",ut="moxie/runtime/html4/Runtime",ct="moxie/runtime/html4/file/FileInput",lt="moxie/runtime/html4/file/FileReader",dt="moxie/runtime/html4/xhr/XMLHttpRequest",ft="moxie/runtime/html4/image/Image";i(u,[],function(){var e=function(e){var t;return e===t?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()},t=function(i){var r;return n(arguments,function(o,s){s>0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(e,t){var n,i,r,o;if(e){try{n=e.length}catch(a){n=o}if(n===o){for(i in e)if(e.hasOwnProperty(i)&&t(e[i],i)===!1)return}else for(r=0;n>r;r++)if(t(e[r],r)===!1)return}},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++r<o&&!e?i(r):n(e)})}var r=0,o=t.length;"function"!==e(n)&&(n=function(){}),t&&t.length||n(),i(r)},o=function(e,t){var i=0,r=e.length,o=new Array(r);n(e,function(e,n){e(function(e){if(e)return t(e);var a=[].slice.call(arguments);a.shift(),o[n]=a,i++,i===r&&(o.unshift(null),t.apply(this,o))})})},a=function(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var n=0,i=t.length;i>n;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;t<e.length;t++)n[t]=e[t];return n},l=function(){var e=0;return function(t){var n=(new Date).getTime().toString(32),i;for(i=0;5>i;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},f=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9]+)([mgk]?)$/.exec(e.toLowerCase().replace(/[^0-9mkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),e};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,parseSizeStr:f}}),i(c,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(l,[u,c],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;n<t.length;n+=2){for(r=t[n+1].split(/ /),i=0;i<r.length;i++)this.mimes[r[i]]=t[n];this.extensions[t[n]]=r}},extList2mimes:function(t,n){var i=this,r,o,a,s,u=[];for(o=0;o<t.length;o++)for(r=t[o].extensions.split(/\s*,\s*/),a=0;a<r.length;a++){if("*"===r[a])return[];if(s=i.mimes[r[a]])-1===e.inArray(s,u)&&u.push(s);else{if(!n||!/^\w+$/.test(r[a]))return[];u.push("."+r[a])}}return u},mimes2exts:function(t){var n=this,i=[];return e.each(t,function(t){if("*"===t)return i=[],!1;var r=t.match(/^(\w+)\/(\*|\w+)$/);r&&("*"===r[2]?e.each(n.extensions,function(e,t){new RegExp("^"+r[1]+"/").test(t)&&[].push.apply(i,n.extensions[t])}):n.extensions[t]&&[].push.apply(i,n.extensions[t]))}),i},mimes2extList:function(n){var i=[],r=[];return"string"===e.typeOf(n)&&(n=e.trim(n).split(/\s*,\s*/)),r=this.mimes2exts(n),i.push({title:t.translate("Files"),extensions:r.length?r.join(","):"*"}),i.mimes=n,i},getFileExtension:function(e){var t=e&&e.match(/\.([^.]+)$/);return t?t[1].toLowerCase():""},getFileMime:function(e){return this.mimes[this.getFileExtension(e)]||""}};return i.addMimeType(n),i}),i(d,[u],function(e){function t(e,t,n){var i=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),i=0;r>i;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]<t[i]){o=-1;break}if(e[i]>t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",f="architecture",p="console",h="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,f=arguments;n<f.length;n+=2){var p=f[n],h=f[n+1];if(typeof t===r){t={};for(u in h)c=h[u],typeof c===o?t[c[0]]=e:t[c]=e}for(a=s=0;a<p.length;a++)if(l=p[a].exec(this.getUA())){for(u=0;u<h.length;u++)d=l[++s],c=h[u],typeof c===o&&c.length>0?2==c.length?t[c[0]]=typeof c[1]==i?c[1].call(this,d):c[1]:3==c.length?t[c[0]]=typeof c[1]!==i||c[1].exec&&c[1].test?d?d.replace(c[1],c[2]):e:d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a<i[r].length;a++)if(g.has(i[r][a],t))return r===n?e:r}else if(g.has(i[r],t))return r===n?e:r;return t}},y={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},w={browser:[[/(opera\smini)\/((\d+)?[\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i,/(opera).+version\/((\d+)?[\w\.]+)/i,/(opera)[\/\s]+((\d+)?[\w\.]+)/i],[u,d,a],[/\s(opr)\/((\d+)?[\w\.]+)/i],[[u,"Opera"],d,a],[/(kindle)\/((\d+)?[\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i,/(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i,/(rekonq)((?:\/)[\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i],[u,d,a],[/(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i],[[u,"IE"],d,a],[/(yabrowser)\/((\d+)?[\w\.]+)/i],[[u,"Yandex"],d,a],[/(comodo_dragon)\/((\d+)?[\w\.]+)/i],[[u,/_/g," "],d,a],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i],[u,d,a],[/(dolfin)\/((\d+)?[\w\.]+)/i],[[u,"Dolphin"],d,a],[/((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i],[[u,"Chrome"],d,a],[/((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i],[[u,"Android Browser"],d,a],[/version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i],[d,a,[u,"Mobile Safari"]],[/version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i],[d,a,u],[/webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i],[u,[a,v.str,y.browser.oldsafari.major],[d,v.str,y.browser.oldsafari.version]],[/(konqueror)\/((\d+)?[\w\.]+)/i,/(webkit|khtml)\/((\d+)?[\w\.]+)/i],[u,d,a],[/(navigator|netscape)\/((\d+)?[\w\.-]+)/i],[[u,"Netscape"],d,a],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i,/(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i,/(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i,/(links)\s\(((\d+)?[\w\.]+)/i,/(gobrowser)\/?((\d+)?[\w\.]+)*/i,/(ice\s?browser)\/v?((\d+)?[\w\._]+)/i,/(mosaic)[\/\s]((\d+)?[\w\.]+)/i],[u,d,a]],engine:[[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[u,d],[/rv\:([\w\.]+).*(gecko)/i],[d,u]],os:[[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[u,[d,v.str,y.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[u,"Windows"],[d,v.str,y.os.windows.version]],[/\((bb)(10);/i],[[u,"BlackBerry"],d],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)\/([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i],[u,d],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[u,"Symbian"],d],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[u,"Firefox OS"],d],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[u,d],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[u,"Chromium OS"],d],[/(sunos)\s?([\w\.]+\d)*/i],[[u,"Solaris"],d],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[u,d],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[u,"iOS"],[d,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i],[u,[d,/_/g,"."]],[/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i,/(unix)\s?([\w\.]+)*/i],[u,d]]},E=function(e){var n=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:t);this.getBrowser=function(){return v.rgx.apply(this,w.browser)},this.getEngine=function(){return v.rgx.apply(this,w.engine)},this.getOS=function(){return v.rgx.apply(this,w.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return n},this.setUA=function(e){return n=e,this},this.setUA(n)};return(new E).getResult()}(),i=function(){var t={define_property:function(){return!1}(),create_canvas:function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))}(),return_response_type:function(t){try{if(-1!==e.inArray(t,["","text","document"]))return!0;if(window.XMLHttpRequest){var n=new XMLHttpRequest;if(n.open("get","/"),"responseType"in n)return n.responseType=t,n.responseType!==t?!1:!0}}catch(i){}return!1},use_data_uri:function(){var e=new Image;return e.onload=function(){t.use_data_uri=1===e.width&&1===e.height},setTimeout(function(){e.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return t.use_data_uri&&("IE"!==r.browser||r.version>=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r={can:i,browser:n.browser.name,version:parseFloat(n.browser.major),os:n.os.name,osVersion:n.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return r.OS=r.os,r}),i(f,[d],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},n=function(e,t){if(!e.className)return!1;var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return n.test(e.className)},i=function(e,t){n(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(n,function(e,t,n){return" "===t&&" "===n?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,n){function i(e){var t,n,i=0,r=0;return e&&(n=e.getBoundingClientRect(),t="CSS1Compat"===s.compatMode?s.documentElement:s.body,i=n.left+t.scrollLeft,r=n.top+t.scrollTop),{x:i,y:r}}var r=0,o=0,a,s=document,u,c;if(t=t,n=n||s.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!s.documentMode||s.documentMode<8))return u=i(t),c=i(n),{x:u.x-c.x,y:u.y-c.y};for(a=t;a&&a!=n&&a.nodeType;)r+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=t.parentNode;a&&a!=n&&a.nodeType;)r-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode;return{x:r,y:o}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:n,addClass:i,removeClass:r,getStyle:o,getPos:a,getSize:s}}),i(p,[u],function(e){function t(e,t){var n;for(n in e)if(e[n]===t)return n;return null}return{RuntimeError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": RuntimeError "+this.code}var i={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(n,i),n.prototype=Error.prototype,n}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": ImageError "+this.code}var i={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2};return e.extend(n,i),n.prototype=Error.prototype,n}(),FileException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": FileException "+this.code}var i={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(n,i),n.prototype=Error.prototype,n}(),DOMException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": DOMException "+this.code}var i={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(n,i),n.prototype=Error.prototype,n}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),i(h,[p,u],function(e,t){function n(){var n={};t.extend(this,{uid:null,init:function(){this.uid||(this.uid=t.guid("uid_"))},addEventListener:function(e,i,r,o){var a=this,s;return e=t.trim(e),/\s/.test(e)?(t.each(e.split(/\s+/),function(e){a.addEventListener(e,i,r,o)}),void 0):(e=e.toLowerCase(),r=parseInt(r,10)||0,s=n[this.uid]&&n[this.uid][e]||[],s.push({fn:i,priority:r,scope:o||this}),n[this.uid]||(n[this.uid]={}),n[this.uid][e]=s,void 0)},hasEventListener:function(e){return e?!(!n[this.uid]||!n[this.uid][e]):!!n[this.uid]},removeEventListener:function(e,i){e=e.toLowerCase();var r=n[this.uid]&&n[this.uid][e],o;if(r){if(i){for(o=r.length-1;o>=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete n[this.uid][e],t.isEmptyObj(n[this.uid])&&delete n[this.uid])}},removeAllEventListeners:function(){n[this.uid]&&delete n[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==t.typeOf(i)){if(s=i,"string"!==t.typeOf(s.type))throw new e.EventException(e.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=n[r]&&n[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];t.each(o,function(e){a[0].target=e.scope,u.async?d.push(function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}):d.push(function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&t.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},convertEventPropsToHandlers:function(e){var n;"array"!==t.typeOf(e)&&(e=[e]);for(var i=0;i<e.length;i++)n="on"+e[i],"function"===t.typeOf(this[n])?this.addEventListener(e[i],this[n]):"undefined"===t.typeOf(this[n])&&(this[n]=null)}})}return n.instance=new n,n}),i(m,[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},n=function(e,n){if("function"==typeof window.atob)return n?t(window.atob(e)):window.atob(e);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,p=0,h="",m=[];if(!e)return e;e+="";do s=i.indexOf(e.charAt(f++)),u=i.indexOf(e.charAt(f++)),c=i.indexOf(e.charAt(f++)),l=i.indexOf(e.charAt(f++)),d=s<<18|u<<12|c<<6|l,r=255&d>>16,o=255&d>>8,a=255&d,m[p++]=64==c?String.fromCharCode(r):64==l?String.fromCharCode(r,o):String.fromCharCode(r,o,a);while(f<e.length);return h=m.join(""),n?t(h):h},i=function(t,n){if(n&&e(t),"function"==typeof window.btoa)return window.btoa(t);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,p=0,h="",m=[];if(!t)return t;do r=t.charCodeAt(f++),o=t.charCodeAt(f++),a=t.charCodeAt(f++),d=r<<16|o<<8|a,s=63&d>>18,u=63&d>>12,c=63&d>>6,l=63&d,m[p++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(f<t.length);h=m.join("");var g=t.length%3;return(g?h.slice(0,g-3):h)+"===".slice(g||3)};return{utf8_encode:e,utf8_decode:t,atob:n,btoa:i}}),i(g,[u,f,h],function(e,t,n){function i(n,r,a,s,u){var c=this,l,d=e.guid(r+"_"),f=u||"browser";n=n||{},o[d]=this,a=e.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},a),n.preferred_caps&&(f=i.getMode(s,n.preferred_caps,f)),l=function(){var t={};return{exec:function(e,n,i,r){return l[n]&&(t[e]||(t[e]={context:this,instance:new l[n]}),t[e].instance[i])?t[e].instance[i].apply(this,r):void 0},removeInstance:function(e){delete t[e]},removeAllInstances:function(){var n=this;e.each(t,function(t,i){"function"===e.typeOf(t.instance.destroy)&&t.instance.destroy.call(t.context),n.removeInstance(i)})}}}(),e.extend(this,{initialized:!1,uid:d,type:r,mode:i.getMode(s,n.required_caps,f),shimid:d+"_container",clients:0,options:n,can:function(t,n){var r=arguments[2]||a;if("string"===e.typeOf(t)&&"undefined"===e.typeOf(n)&&(t=i.parseCaps(t)),"object"===e.typeOf(t)){for(var o in t)if(!this.can(o,t[o],r))return!1;return!0}return"function"===e.typeOf(r[t])?r[t].call(this,n):n===r[t]},getShimContainer:function(){var n,i=t.get(this.shimid);return i||(n=this.options.container?t.get(this.options.container):document.body,i=document.createElement("div"),i.id=this.shimid,i.className="moxie-shim moxie-shim-"+this.type,e.extend(i.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),n.appendChild(i),n=null),i},getShim:function(){return l},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec.call(this,this.uid,e,t,n)},exec:function(e,t){var n=[].slice.call(arguments,2);return c[e]&&c[e][t]?c[e][t].apply(this,n):c.shimExec.apply(this,arguments)},destroy:function(){if(c){var e=t.get(this.shimid);e&&e.parentNode.removeChild(e),l&&l.removeAllInstances(),this.unbindAll(),delete o[this.uid],this.uid=null,d=c=l=e=null}}}),this.mode&&n.required_caps&&!this.can(n.required_caps)&&(this.mode=!1)}var r={},o={};return i.order="html5,flash,silverlight,html4",i.getRuntime=function(e){return o[e]?o[e]:!1},i.addConstructor=function(e,t){t.prototype=n.instance,r[e]=t},i.getConstructor=function(e){return r[e]||null},i.getInfo=function(e){var t=i.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},i.parseCaps=function(t){var n={};return"string"!==e.typeOf(t)?t||{}:(e.each(t.split(","),function(e){n[e]=!0}),n)},i.can=function(e,t){var n,r=i.getConstructor(e),o;return r?(n=new r({required_caps:t}),o=n.mode,n.destroy(),!!o):!1},i.thatCan=function(e,t){var n=(t||i.order).split(/\s*,\s*/);for(var r in n)if(i.can(n[r],e))return n[r];return null},i.getMode=function(t,n,i){var r=null;if("undefined"===e.typeOf(i)&&(i="browser"),n&&!e.isEmptyObj(t)){if(e.each(n,function(n,i){if(t.hasOwnProperty(i)){var o=t[i](n);if("string"==typeof o&&(o=[o]),r){if(!(r=e.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==e.inArray(i,r)?i:r[0];if(r===!1)return!1}return i},i.capTrue=function(){return!0},i.capFalse=function(){return!1},i.capTest=function(e){return function(){return!!e}},i}),i(v,[p,u,g],function(e,t,n){return function i(){var i;t.extend(this,{connectRuntime:function(r){function o(t){var s,u;return t.length?(s=t.shift(),(u=n.getConstructor(s))?(i=new u(r),i.bind("Init",function(){i.initialized=!0,setTimeout(function(){i.clients++,a.trigger("RuntimeInit",i)},1)}),i.bind("Error",function(){i.destroy(),o(t)}),i.mode?(i.init(),void 0):(i.trigger("Error"),void 0)):(o(t),void 0)):(a.trigger("RuntimeError",new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)),i=null,void 0)}var a=this,s;if("string"===t.typeOf(r)?s=r:"string"===t.typeOf(r.ruid)&&(s=r.ruid),s){if(i=n.getRuntime(s))return i.clients++,i;throw new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||n.order).split(/\s*,\s*/))},getRuntime:function(){return i&&i.uid?i:(i=null,null)},disconnectRuntime:function(){i&&--i.clients<=0&&(i.destroy(),i=null)}})}}),i(y,[u,m,v],function(e,t,n){function i(o,a){function s(t,n,o){var a,s=r[this.uid];return"string"===e.typeOf(s)&&s.length?(a=new i(null,{type:o,size:n-t}),a.detach(s.substr(t,a.size)),a):null}n.call(this),o&&this.connectRuntime(o),a?"string"===e.typeOf(a)&&(a={data:a}):a={},e.extend(this,{uid:a.uid||e.guid("uid_"),ruid:o,size:a.size||0,type:a.type||"",slice:function(e,t,n){return this.isDetached()?s.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,n)},getSource:function(){return r[this.uid]?r[this.uid]:null},detach:function(e){this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy",r[this.uid]),this.disconnectRuntime(),this.ruid=null),e=e||"";var n=e.match(/^data:([^;]*);base64,/);n&&(this.type=n[1],e=t.atob(e.substring(e.indexOf("base64,")+7))),this.size=e.length,r[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===e.typeOf(r[this.uid])},destroy:function(){this.detach(),delete r[this.uid]}}),a.data?this.detach(a.data):r[this.uid]=a}var r={};return i}),i(w,[u,l,y],function(e,t,n){function i(i,r){var o,a;if(r||(r={}),a=r.type&&""!==r.type?r.type:t.getFileMime(r.name),r.name)o=r.name.replace(/\\/g,"/"),o=o.substr(o.lastIndexOf("/")+1);else{var s=a.split("/")[0];o=e.guid((""!==s?s:"file")+"_"),t.extensions[a]&&(o+="."+t.extensions[a][0])}n.apply(this,arguments),e.extend(this,{type:a||"",name:o||e.guid("file_"),lastModifiedDate:r.lastModifiedDate||(new Date).toLocaleString()})}return i.prototype=n.prototype,i}),i(E,[u,l,f,p,h,c,w,g,v],function(e,t,n,i,r,o,a,s,u){function c(r){var c=this,d,f,p;if(-1!==e.inArray(e.typeOf(r),["string","node"])&&(r={browse_button:r}),f=n.get(r.browse_button),!f)throw new i.DOMException(i.DOMException.NOT_FOUND_ERR);p={accept:[{title:o.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:f.parentNode||document.body},r=e.extend({},p,r),"string"==typeof r.required_caps&&(r.required_caps=s.parseCaps(r.required_caps)),"string"==typeof r.accept&&(r.accept=t.mimes2extList(r.accept)),d=n.get(r.container),d||(d=document.body),"static"===n.getStyle(d,"position")&&(d.style.position="relative"),d=f=null,u.call(c),e.extend(c,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){c.convertEventPropsToHandlers(l),c.bind("RuntimeInit",function(t,i){c.ruid=i.uid,c.shimid=i.shimid,c.bind("Ready",function(){c.trigger("Refresh")},999),c.bind("Change",function(){var t=i.exec.call(c,"FileInput","getFiles");c.files=[],e.each(t,function(e){return 0===e.size?!0:(c.files.push(new a(c.ruid,e)),void 0)})},999),c.bind("Refresh",function(){var t,o,a,s;a=n.get(r.browse_button),s=n.get(i.shimid),a&&(t=n.getPos(a,n.get(r.container)),o=n.getSize(a),s&&e.extend(s.style,{top:t.y+"px",left:t.x+"px",width:o.w+"px",height:o.h+"px"})),s=a=null}),i.exec.call(c,"FileInput","init",r)}),c.connectRuntime(e.extend({},r,{required_caps:{select_file:!0}}))},disable:function(t){var n=this.getRuntime();n&&n.exec.call(this,"FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){c.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null}})}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=r.instance,c}),i(_,[c,f,p,u,w,v,h,l],function(e,t,n,i,r,o,a,s){function u(n){var a=this,u;"string"==typeof n&&(n={drop_zone:n}),u={accept:[{title:e.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},n="object"==typeof n?i.extend({},u,n):u,n.container=t.get(n.drop_zone)||document.body,"static"===t.getStyle(n.container,"position")&&(n.container.style.position="relative"),"string"==typeof n.accept&&(n.accept=s.mimes2extList(n.accept)),o.call(a),i.extend(a,{uid:i.guid("uid_"),ruid:null,files:null,init:function(){a.convertEventPropsToHandlers(c),a.bind("RuntimeInit",function(e,t){a.ruid=t.uid,a.bind("Drop",function(){var e=t.exec.call(a,"FileDrop","getFiles");a.files=[],i.each(e,function(e){a.files.push(new r(a.ruid,e))})},999),t.exec.call(a,"FileDrop","init",n),a.dispatchEvent("ready")}),a.connectRuntime(n)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null}})}var c=["ready","dragenter","dragleave","drop","error"];return u.prototype=a.instance,u}),i(x,[u,v,h],function(e,t,n){function i(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return i.prototype=n.instance,i}),i(R,[u,m,p,h,y,w,x],function(e,t,n,i,r,o,a){function s(){function i(e,i){function l(e){o.readyState=s.DONE,o.error=e,o.trigger("error"),d()}function d(){c.destroy(),c=null,o.trigger("loadend")}function f(t){c.bind("Error",function(e,t){l(t)}),c.bind("Progress",function(e){o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e)}),c.bind("Load",function(e){o.readyState=s.DONE,o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e),d()}),t.exec.call(c,"FileReader","read",e,i)}if(c=new a,this.convertEventPropsToHandlers(u),this.readyState===s.LOADING)return l(new n.DOMException(n.DOMException.INVALID_STATE_ERR));if(this.readyState=s.LOADING,this.trigger("loadstart"),i instanceof r)if(i.isDetached()){var p=i.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=p;break;case"readAsDataURL":this.result="data:"+i.type+";base64,"+t.btoa(p)}this.readyState=s.DONE,this.trigger("load"),d()}else f(c.connectRuntime(i.ruid));else l(new n.DOMException(n.DOMException.NOT_FOUND_ERR))}var o=this,c;e.extend(this,{uid:e.guid("uid_"),readyState:s.EMPTY,result:null,error:null,readAsBinaryString:function(e){i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){i.call(this,"readAsDataURL",e)},readAsText:function(e){i.call(this,"readAsText",e)
14
+ },abort:function(){this.result=null,-1===e.inArray(this.readyState,[s.EMPTY,s.DONE])&&(this.readyState===s.LOADING&&(this.readyState=s.DONE),c&&c.getRuntime().exec.call(this,"FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))},destroy:function(){this.abort(),c&&(c.getRuntime().exec.call(this,"FileReader","destroy"),c.disconnectRuntime()),o=c=null}})}var u=["loadstart","progress","load","abort","error","loadend"];return s.EMPTY=0,s.LOADING=1,s.DONE=2,s.prototype=i.instance,s}),i(b,[],function(){var e=function(t,n){for(var i=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],r=i.length,o={http:80,https:443},a={},s=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,u=s.exec(t||"");r--;)u[r]&&(a[i[r]]=u[r]);if(!a.scheme){n&&"string"!=typeof n||(n=e(n||document.location.href)),a.scheme=n.scheme,a.host=n.host,a.port=n.port;var c="";/^[^\/]/.test(a.path)&&(c=n.path,/(\/|\/[^\.]+)$/.test(c)?c+="/":c=c.replace(/\/[^\/]+$/,"/")),a.path=c+(a.path||"")}return a.port||(a.port=o[a.scheme]||80),a.port=parseInt(a.port,10),a.path||(a.path="/"),delete a.source,a},t=function(t){var n={http:80,https:443},i=e(t);return i.scheme+"://"+i.host+(i.port!==n[i.scheme]?":"+i.port:"")+i.path+(i.query?i.query:"")},n=function(t){function n(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof t&&(t=e(t)),n(e())===n(t)};return{parseUrl:e,resolveUrl:t,hasSameOrigin:n}}),i(T,[u,v,m],function(e,t,n){return function(){function i(e,t){if(!t.isDetached()){var i=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t);return this.disconnectRuntime(),i}var r=t.getSource();switch(e){case"readAsBinaryString":return r;case"readAsDataURL":return"data:"+t.type+";base64,"+n.btoa(r);case"readAsText":for(var o="",a=0,s=r.length;s>a;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(S,[p,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(A,[u,p,h,m,b,g,x,y,T,S,d,l],function(e,t,n,i,r,o,a,s,u,c,l,d){function f(){this.uid=e.guid("uid_")}function p(){function n(e,t){return y.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?y[e]:v[e]:(l.can("define_property")?y[e]=t:v[e]=t,void 0):void 0}function u(t){function i(){k.destroy(),k=null,s.dispatchEvent("loadend"),s=null}function r(r){k.bind("LoadStart",function(e){n("readyState",p.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),I&&s.upload.dispatchEvent(e)}),k.bind("Progress",function(e){n("readyState")!==p.LOADING&&(n("readyState",p.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),k.bind("UploadProgress",function(e){I&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),k.bind("Load",function(t){n("readyState",p.DONE),n("status",Number(r.exec.call(k,"XMLHttpRequest","getStatus")||0)),n("statusText",h[n("status")]||""),n("response",r.exec.call(k,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),U=r.exec.call(k,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(I&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),k.bind("Abort",function(e){s.dispatchEvent(e),i()}),k.bind("Error",function(e){N=!0,n("readyState",p.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(k,"XMLHttpRequest","send",{url:E,method:_,async:w,user:R,password:b,headers:x,mimeType:S,encoding:T,responseType:s.responseType,withCredentials:s.withCredentials,options:P},t)}var s=this;M=(new Date).getTime(),k=new a,"string"==typeof P.required_caps&&(P.required_caps=o.parseCaps(P.required_caps)),P.required_caps=e.extend({},P.required_caps,{return_response_type:s.responseType}),t instanceof c&&(P.required_caps.send_multipart=!0),L||(P.required_caps.do_cors=!0),P.ruid?r(k.connectRuntime(P)):(k.bind("RuntimeInit",function(e,t){r(t)}),k.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),k.connectRuntime(P))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),M=C=null}var v=this,y={timeout:0,readyState:p.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},w=!0,E,_,x={},R,b,T=null,S=null,A=!1,O=!1,I=!1,D=!1,N=!1,L=!1,M,C,F=null,H=null,P={},k,U="",B;e.extend(this,y,{uid:e.guid("uid_"),upload:new f,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(R=u||l.user,b=c||l.pass,w=s||!0,w===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);A=!w,O=!1,x={},g.call(this),n("readyState",p.OPENED),this.convertEventPropsToHandlers(["readystatechange"]),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==p.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(x[r]?x[r]+=", "+o:x[r]=o,!0)},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(B||(B={},e.each(U.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),B[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),B.hasOwnProperty(t))?B[t].header+": "+B[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[p.LOADING,p.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,H=o},send:function(n,r){if(P="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.convertEventPropsToHandlers(m),this.upload.convertEventPropsToHandlers(m),this.readyState!==p.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)P.ruid=n.ruid,S=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();P.ruid=o.ruid,S=o.type||"application/octet-stream"}}else"string"==typeof n&&(T="UTF-8",S="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=P.required_caps&&P.required_caps.send_browser_cookies&&!L),I=!A&&this.upload.hasEventListener(),N=!1,D=!n,A||(O=!0),u.call(this,n)},abort:function(){if(N=!0,A=!1,~e.inArray(n("readyState"),[p.UNSENT,p.OPENED,p.DONE]))n("readyState",p.UNSENT);else{if(n("readyState",p.DONE),O=!1,!k)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);k.getRuntime().exec.call(k,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){k&&("function"===e.typeOf(k.destroy)&&k.destroy(),k=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}})}var h={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};f.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return p.UNSENT=0,p.OPENED=1,p.HEADERS_RECEIVED=2,p.LOADING=3,p.DONE=4,p.prototype=n.instance,p}),i(O,[u,m,v,h],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;f>i&&(f=i),n=t.btoa(c.substr(d,f)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,f;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),f=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(I,[u,f,p,T,A,g,v,O,d,h,y,w,m],function(e,t,n,i,r,o,a,s,u,c,l,d,f){function p(){function i(e){e||(e=this.getRuntime().exec.call(this,"Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof p){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)/^data:[^;]*;base64,/.test(t)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){this.bind("Load Resize",function(){i.call(this)},999),this.convertEventPropsToHandlers(h),c.apply(this,arguments)},downsize:function(t,i,r,o){try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>p.MAX_RESIZE_WIDTH||this.height>p.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);(!t&&!i||"undefined"===e.typeOf(r))&&(r=!1),t=t||this.width,i=i||this.height,o="undefined"===e.typeOf(o)?!0:!!o,this.getRuntime().exec.call(this,"Image","downsize",t,i,r,o)}catch(a){this.trigger("error",a)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return e||(e="image/jpeg"),"image/jpeg"!==e||t||(t=90),this.getRuntime().exec.call(this,"Image","getAsBlob",e,t)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.getRuntime().exec.call(this,"Image","getAsDataURL",e,t)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return f.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i){function r(){if(u.can("create_canvas")){var t=a.getAsCanvas();if(t)return i.appendChild(t),t=null,a.destroy(),o.trigger("embedded"),void 0}var r=a.getAsDataURL(c,l);if(!r)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",r.length))i.innerHTML='<img src="'+r+'" width="'+a.width+'" height="'+a.height+'" />',a.destroy(),o.trigger("embedded");else{var d=new s;d.bind("TransportingComplete",function(){v=o.connectRuntime(this.result.ruid),o.bind("Embedded",function(){e.extend(v.getShimContainer().style,{top:"0px",left:"0px",width:a.width+"px",height:a.height+"px"}),v=null},999),v.exec.call(o,"ImageView","display",this.result.uid,m,g),a.destroy()}),d.transport(f.atob(r.substring(r.indexOf("base64,")+7)),c,e.extend({},h,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i}))}}var o=this,a,c,l,d,h=arguments[1]||{},m=this.width,g=this.height,v;try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>p.MAX_RESIZE_WIDTH||this.height>p.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);if(c=h.type||this.type||"image/jpeg",l=h.quality||90,d="undefined"!==e.typeOf(h.crop)?h.crop:!1,h.width)m=h.width,g=h.height||m;else{var y=t.getSize(i);y.w&&y.h&&(m=y.w,g=y.h)}return a=new p,a.bind("Resize",function(){r.call(o)}),a.bind("Load",function(){a.downsize(m,g,d,!1)}),a.clone(this,!1),a}catch(w){this.trigger("error",w)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}})}var h=["progress","load","error","resize","embedded"];return p.MAX_RESIZE_WIDTH=6500,p.MAX_RESIZE_HEIGHT=6500,p.prototype=c.instance,p}),i(D,[u,p,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.version>9)}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.version>=21},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.4","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||"IE"===i.browser&&i.version>=10||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(L,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(M,[D,u,f,L,l,d],function(e,t,n,i,r,o){function a(){var e=[],a;t.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,f,p,h,m;a=s,e=[],f=a.accept.mimes||r.extList2mimes(a.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='<input id="'+c.uid+'" type="file" style="font-size:999px;opacity:0;"'+(a.multiple&&c.can("select_multiple")?"multiple":"")+(a.directory&&c.can("select_folder")?"webkitdirectory directory":"")+(f?' accept="'+f.join(",")+'"':"")+" />",l=n.get(c.uid),t.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),p=n.get(a.browse_button),c.can("summon_file_dialog")&&("static"===n.getStyle(p,"position")&&(p.style.position="relative"),h=parseInt(n.getStyle(p,"z-index"),10)||1,p.style.zIndex=h,d.style.zIndex=h-1,i.addEvent(p,"click",function(e){var t=n.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?p:d,i.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),i.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),i.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),i.addEvent(n.get(a.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(){if(e=[],a.directory?t.each(this.files,function(t){"."!==t.name&&e.push(t)}):e=[].slice.call(this.files),"IE"!==o.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=g}u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},getFiles:function(){return e},disable:function(e){var t=this.getRuntime(),i;(i=n.get(t.uid))&&(i.disabled=!!e)},destroy:function(){var t=this.getRuntime(),r=t.getShim(),o=t.getShimContainer();i.removeAllEvents(o,this.uid),i.removeAllEvents(a&&n.get(a.container),this.uid),i.removeAllEvents(a&&n.get(a.browse_button),this.uid),o&&(o.innerHTML=""),r.removeInstance(this.uid),e=a=o=r=null}})}return e.FileInput=a}),i(C,[D,u,f,L,l],function(e,t,n,i,r){function o(){function e(e){for(var n=[],i=0;i<e.length;i++)[].push.apply(n,e[i].extensions.split(/\s*,\s*/));return-1===t.inArray("*",n)?n:[]}function o(e){var n=r.getFileExtension(e.name);return!n||!d.length||-1!==t.inArray(n,d)}function a(e,n){var i=[];t.each(e,function(e){var t=e.webkitGetAsEntry();if(t)if(t.isFile){var n=e.getAsFile();o(n)&&l.push(n)}else i.push(t)}),i.length?s(i,n):n()}function s(e,n){var i=[];t.each(e,function(e){i.push(function(t){u(e,t)})}),t.inSeries(i,function(){n()})}function u(e,t){e.isFile?e.file(function(e){o(e)&&l.push(e),t()},function(){t()}):e.isDirectory?c(e,t):t()}function c(e,t){function n(e){r.readEntries(function(t){t.length?([].push.apply(i,t),n(e)):e()},e)}var i=[],r=e.createReader();n(function(){s(i,t)})}var l=[],d=[],f;t.extend(this,{init:function(n){var r=this,s;f=n,d=e(f.accept),s=f.container,i.addEvent(s,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},r.uid),i.addEvent(s,"drop",function(e){e.preventDefault(),e.stopPropagation(),l=[],e.dataTransfer.items&&e.dataTransfer.items[0].webkitGetAsEntry?a(e.dataTransfer.items,function(){r.trigger("drop")}):(t.each(e.dataTransfer.files,function(e){o(e)&&l.push(e)}),r.trigger("drop"))},r.uid),i.addEvent(s,"dragenter",function(e){e.preventDefault(),e.stopPropagation(),r.trigger("dragenter")},r.uid),i.addEvent(s,"dragleave",function(e){e.preventDefault(),e.stopPropagation(),r.trigger("dragleave")},r.uid)},getFiles:function(){return l},destroy:function(){i.removeAllEvents(f&&n.get(f.container),this.uid),l=d=f=null}})}return e.FileDrop=o}),i(F,[D,m,u],function(e,t,n){function i(){function e(e){return t.atob(e.substring(e.indexOf("base64,")+7))}var i,r=!1;n.extend(this,{read:function(e,t){var o=this;i=new window.FileReader,i.addEventListener("progress",function(e){o.trigger(e)}),i.addEventListener("load",function(e){o.trigger(e)}),i.addEventListener("error",function(e){o.trigger(e,i.error)}),i.addEventListener("loadend",function(){i=null}),"function"===n.typeOf(i[e])?(r=!1,i[e](t.getSource())):"readAsBinaryString"===e&&(r=!0,i.readAsDataURL(t.getSource()))},getResult:function(){return i&&i.result?r?e(i.result):i.result:null},abort:function(){i&&i.abort()},destroy:function(){i=null}})}return e.FileReader=i}),i(H,[D,u,l,b,w,y,S,p,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(e,t){var n=this,i,r;i=t.getBlob().getSource(),r=new window.FileReader,r.onload=function(){t.append(t.getBlobName(),new o(null,{type:i.type,data:r.result})),f.send.call(n,e,t)},r.readAsBinaryString(i)}function c(){return!window.XMLHttpRequest||"IE"===u.browser&&u.version<8?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(n){}}():new window.XMLHttpRequest}function l(e){var t=e.responseXML,n=e.responseText;return"IE"===u.browser&&n&&t&&!t.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(e.getResponseHeader("Content-Type"))&&(t=new window.ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.validateOnParse=!1,t.loadXML(n)),t&&("IE"===u.browser&&0!==t.parseError||!t.documentElement||"parsererror"===t.documentElement.tagName)?null:t}function d(e){var t="----moxieboundary"+(new Date).getTime(),n="--",i="\r\n",r="",a=this.getRuntime();if(!a.can("send_binary_string"))throw new s.RuntimeError(s.RuntimeError.NOT_SUPPORTED_ERR);return p.setRequestHeader("Content-Type","multipart/form-data; boundary="+t),e.each(function(e,a){r+=e instanceof o?n+t+i+'Content-Disposition: form-data; name="'+a+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'"'+i+"Content-Type: "+(e.type||"application/octet-stream")+i+i+e.getSource()+i:n+t+i+'Content-Disposition: form-data; name="'+a+'"'+i+i+unescape(encodeURIComponent(e))+i}),r+=n+t+n+i}var f=this,p,h;t.extend(this,{send:function(n,r){var s=this,l="Mozilla"===u.browser&&u.version>=4&&u.version<7,f="Android Browser"===u.browser,m=!1;if(h=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),p=c(),p.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return e.call(s,n,r),void 0;if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}p.upload?(n.withCredentials&&(p.withCredentials=!0),p.addEventListener("load",function(e){s.trigger(e)}),p.addEventListener("error",function(e){s.trigger(e)}),p.addEventListener("progress",function(e){s.trigger(e)}),p.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):p.onreadystatechange=function v(){switch(p.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=p.getResponseHeader("Content-Length")||0),p.responseText&&(t=p.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:p.onreadystatechange=function(){},0===p.status?s.trigger("error"):s.trigger("load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){p.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in p&&(p.responseType="json"!==n.responseType||u.can("return_response_type","json")?n.responseType:"text"),m?p.sendAsBinary?p.sendAsBinary(r):function(){for(var e=new Uint8Array(r.length),t=0;t<r.length;t++)e[t]=255&r.charCodeAt(t);p.send(e.buffer)}():p.send(r),s.trigger("loadstart")},getStatus:function(){try{if(p)return p.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var i=new r(t.uid,p.response),o=p.getResponseHeader("Content-Disposition");if(o){var a=o.match(/filename=([\'\"'])([^\1]+)\1/);a&&(h=a[2])}return i.name=h,i.type||(i.type=n.getFileMime(h)),i;case"json":return u.can("return_response_type","json")?p.response:200===p.status&&window.JSON?JSON.parse(p.responseText):null;case"document":return l(p);default:return""!==p.responseText?p.responseText:null}}catch(s){return null}},getAllResponseHeaders:function(){try{return p.getAllResponseHeaders()}catch(e){}return""},abort:function(){p&&p.abort()},destroy:function(){f=h=null}})}return e.XMLHttpRequest=c}),i(P,[],function(){return function(){function e(e,t){var n=r?0:-8*(t-1),i=0,a;for(a=0;t>a;a++)i|=o.charCodeAt(e+a)<<Math.abs(n+8*a);return i}function n(e,t,n){n=3===arguments.length?n:o.length-t-1,o=o.substr(0,t)+e+o.substr(n+t)}function i(e,t,i){var o="",a=r?0:-8*(i-1),s;for(s=0;i>s;s++)o+=String.fromCharCode(255&t>>Math.abs(a+8*s));n(o,e,i)}var r=!1,o;return{II:function(e){return e===t?r:(r=e,void 0)},init:function(e){r=!1,o=e},SEGMENT:function(e,t,i){switch(arguments.length){case 1:return o.substr(e,o.length-e-1);case 2:return o.substr(e,t);case 3:n(i,e,t);break;default:return o}},BYTE:function(t){return e(t,1)},SHORT:function(t){return e(t,2)},LONG:function(n,r){return r===t?e(n,4):(i(n,r,4),void 0)},SLONG:function(t){var n=e(t,4);return n>2147483647?n-4294967296:n},STRING:function(t,n){var i="";for(n+=t;n>t;t++)i+=String.fromCharCode(e(t,1));return i}}}}),i(k,[P],function(e){return function t(n){var i=[],r,o,a,s=0;if(r=new e,r.init(n),65496===r.SHORT(0)){for(o=2;o<=n.length;)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;s=r.SHORT(o+2)+2,a>=65505&&65519>=a&&i.push({hex:a,name:"APP"+(15&a),start:o,length:s,segment:r.SEGMENT(o,s)}),o+=s}return r.init(null),{headers:i,restore:function(e){var t,n;for(r.init(e),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,t=i.length;t>n;n++)r.SEGMENT(o,0,i[n].segment),o+=i[n].length;return e=r.SEGMENT(),r.init(null),e},strip:function(e){var n,i,o;for(i=new t(e),n=i.headers,i.purge(),r.init(e),o=n.length;o--;)r.SEGMENT(n[o].start,n[o].length,"");return e=r.SEGMENT(),r.init(null),e},get:function(e){for(var t=[],n=0,r=i.length;r>n;n++)i[n].name===e.toUpperCase()&&t.push(i[n].segment);return t},set:function(e,t){var n=[],r,o,a;for("string"==typeof t?n.push(t):n=t,r=o=0,a=i.length;a>r&&(i[r].name===e.toUpperCase()&&(i[r].segment=n[o],i[r].length=n[o].length,o++),!(o>=n.length));r++);},purge:function(){i=[],r.init(null),r=null}}}}}),i(U,[u,P],function(e,n){return function i(){function i(e,n){var i=a.SHORT(e),r,o,s,u,d,f,p,h,m=[],g={};for(r=0;i>r;r++)if(p=f=e+12*r+2,s=n[a.SHORT(p)],s!==t){switch(u=a.SHORT(p+=2),d=a.LONG(p+=2),p+=4,m=[],u){case 1:case 7:for(d>4&&(p=a.LONG(p)+c.tiffHeader),o=0;d>o;o++)m[o]=a.BYTE(p+o);break;case 2:d>4&&(p=a.LONG(p)+c.tiffHeader),g[s]=a.STRING(p,d-1);continue;case 3:for(d>2&&(p=a.LONG(p)+c.tiffHeader),o=0;d>o;o++)m[o]=a.SHORT(p+2*o);break;case 4:for(d>1&&(p=a.LONG(p)+c.tiffHeader),o=0;d>o;o++)m[o]=a.LONG(p+4*o);break;case 5:for(p=a.LONG(p)+c.tiffHeader,o=0;d>o;o++)m[o]=a.LONG(p+4*o)/a.LONG(p+4*o+4);break;case 9:for(p=a.LONG(p)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(p+4*o);break;case 10:for(p=a.LONG(p)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(p+4*o)/a.SLONG(p+4*o+4);break;default:continue}h=1==d?m[0]:m,g[s]=l.hasOwnProperty(s)&&"object"!=typeof h?l[s][h]:h}return g}function r(){var e=c.tiffHeader;return a.II(18761==a.SHORT(e)),42!==a.SHORT(e+=2)?!1:(c.IFD0=c.tiffHeader+a.LONG(e+=2),u=i(c.IFD0,s.tiff),"ExifIFDPointer"in u&&(c.exifIFD=c.tiffHeader+u.ExifIFDPointer,delete u.ExifIFDPointer),"GPSInfoIFDPointer"in u&&(c.gpsIFD=c.tiffHeader+u.GPSInfoIFDPointer,delete u.GPSInfoIFDPointer),!0)}function o(e,t,n){var i,r,o,u=0;if("string"==typeof t){var l=s[e.toLowerCase()];for(var d in l)if(l[d]===t){t=d;break}}i=c[e.toLowerCase()+"IFD"],r=a.SHORT(i);for(var f=0;r>f;f++)if(o=i+12*f+2,a.SHORT(o)==t){u=o+8;break}return u?(a.LONG(u,n),!0):!1}var a,s,u,c={},l;return a=new n,s={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire.",1:"Flash fired.",5:"Strobe return light not detected.",7:"Strobe return light detected.",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},{init:function(e){return c={tiffHeader:10},e!==t&&e.length?(a.init(e),65505===a.SHORT(0)&&"EXIF\0"===a.STRING(4,5).toUpperCase()?r():!1):!1
15
+ },TIFF:function(){return u},EXIF:function(){var t;if(t=i(c.exifIFD,s.exif),t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n<t.ExifVersion.length;n++)r+=String.fromCharCode(t.ExifVersion[n]);t.ExifVersion=r}return t},GPS:function(){var t;return t=i(c.gpsIFD,s.gps),t.GPSVersionID&&"array"===e.typeOf(t.GPSVersionID)&&(t.GPSVersionID=t.GPSVersionID.join(".")),t},setExif:function(e,t){return"PixelXDimension"!==e&&"PixelYDimension"!==e?!1:o("exif",e,t)},getBinary:function(){return a.SEGMENT()},purge:function(){a.init(null),a=u=null,c={}}}}}),i(B,[u,p,k,P,U],function(e,t,n,i,r){function o(o){function a(){for(var e=0,t,n;e<=u.length;){if(t=c.SHORT(e+=2),t>=65472&&65475>=t)return e+=5,{height:c.SHORT(e),width:c.SHORT(e+=2)};n=c.SHORT(e+=2),e+=n-2}return null}function s(){d&&l&&c&&(d.purge(),l.purge(),c.init(null),u=f=l=d=c=null)}var u,c,l,d,f,p;if(u=o,c=new i,c.init(u),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o),d=new r,p=!!d.init(l.get("app1")[0]),f=a.call(this),e.extend(this,{type:"image/jpeg",size:u.length,width:f&&f.width||0,height:f&&f.height||0,setExif:function(t,n){return p?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),l.set("app1",d.getBinary()),void 0):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):u=l.restore(u)},stripHeaders:function(e){return l.strip(e)},purge:function(){s.call(this)}}),p&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS()})}return o}),i(z,[p,u,P],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:u.LONG(t),height:u.LONG(t+=4)}):null}function o(){u&&(u.init(null),s=d=c=l=u=null)}function a(e){var t,n,i,r;return t=u.LONG(e),n=u.STRING(e+=4,4),i=e+=4,r=u.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l,d;s=i,u=new n,u.init(s),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;n<i.length;n++,t+=2)if(i[n]!=u.SHORT(t))throw new e.ImageError(e.ImageError.WRONG_FORMAT)}(),d=r.call(this),t.extend(this,{type:"image/png",size:s.length,width:d.width,height:d.height,purge:function(){o.call(this)}}),o.call(this)}return i}),i(G,[u,p,B,z],function(e,t,n,i){return function(r){var o=[n,i],a;a=function(){for(var e=0;e<o.length;e++)try{return new o[e](r)}catch(n){}throw new t.ImageError(t.ImageError.WRONG_FORMAT)}(),e.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){}}),e.extend(this,a),this.purge=function(){a.purge(),a=null}}}),i(q,[],function(){function e(e,i,r){var o=e.naturalWidth,a=e.naturalHeight,s=r.width,u=r.height,c=r.x||0,l=r.y||0,d=i.getContext("2d");t(e)&&(o/=2,a/=2);var f=1024,p=document.createElement("canvas");p.width=p.height=f;for(var h=p.getContext("2d"),m=n(e,o,a),g=0;a>g;){for(var v=g+f>a?a-g:f,y=0;o>y;){var w=y+f>o?o-y:f;h.clearRect(0,0,f,f),h.drawImage(e,-y,-g);var E=y*s/o+c<<0,_=Math.ceil(w*s/o),x=g*u/a/m+l<<0,R=Math.ceil(v*u/a/m);d.drawImage(p,0,0,w,v,E,x,_,R),y+=f}g+=f}p=h=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(X,[D,u,p,m,w,G,q,l,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(){if(!E&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return E||y}function c(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function l(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function d(e){var t=this;y=new Image,y.onerror=function(){g.call(this),t.trigger("error",new n.ImageError(n.ImageError.WRONG_FORMAT))},y.onload=function(){t.trigger("load")},y.src=/^data:[^;]*;base64,/.test(e)?e:l(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",new n.FileException(n.FileException.NOT_READABLE_ERR))},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function p(n,i,r,o){var a=this,s,u,c=0,l=0,d,f,p,g;if(b=o,g=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(g,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),u=r?Math.max:Math.min,s=u(n/d.width,i/d.height),s>1&&(!r||o)?(this.trigger("Resize"),void 0):(E||(E=document.createElement("canvas")),f=Math.round(d.width*s),p=Math.round(d.height*s),r?(E.width=n,E.height=i,f>n&&(c=Math.round((f-n)/2)),p>i&&(l=Math.round((p-i)/2))):(E.width=f,E.height=p),b||m(E.width,E.height,g),h.call(this,d,E,-c,-l,f,p),this.width=E.width,this.height=E.height,R=!0,a.trigger("Resize"),void 0)}function h(e,t,n,i,r,o){if("iOS"===u.OS)a.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var s=t.getContext("2d");s.drawImage(e,n,i,r,o)}}function m(e,t,n){switch(n){case 5:case 6:case 7:case 8:E.width=t,E.height=e;break;default:E.width=e,E.height=t}var i=E.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function g(){w&&(w.purge(),w=null),_=y=E=x=null,R=!1}var v=this,y,w,E,_,x,R=!1,b=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(_=e.getSource(),d.call(this,_),void 0):(f.call(this,e.getSource(),function(e){r&&(_=c(e)),d.call(t,e)}),void 0)},loadFromImage:function(e,t){this.meta=e.meta,x=new r(null,{name:e.name,size:e.size,type:e.type}),d.call(this,t?_=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!w&&_&&t.can("access_image_binary")&&(w=new o(_)),n={width:e().width||0,height:e().height||0,type:x.type||s.getFileMime(x.name),size:_&&_.length||x.size||0,name:x.name||"",meta:w&&w.meta||this.meta||{}}},downsize:function(){p.apply(this,arguments)},getAsCanvas:function(){return E&&(E.id=this.uid+"_canvas"),E},getAsBlob:function(e,t){return e!==this.type&&p.call(this,this.width,this.height,!1),new r(null,{name:x.name||"",type:e,data:v.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!R)return y.src;if("image/jpeg"!==e)return E.toDataURL("image/png");try{return E.toDataURL("image/jpeg",t/100)}catch(n){return E.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!R)return _||(_=c(v.getAsDataURL(e,t))),_;if("image/jpeg"!==e)_=c(v.getAsDataURL(e,t));else{var n;t||(t=90);try{n=E.toDataURL("image/jpeg",t/100)}catch(i){n=E.toDataURL("image/jpeg")}_=c(n),w&&(_=w.stripHeaders(_),b&&(w.meta&&w.meta.exif&&w.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),_=w.writeHeaders(_)),w.purge(),w=null)}return R=!1,_},destroy:function(){v=null,g.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=c}),i(j,[u,d,f,p,g],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(a){var c=this,l;a=e.extend({swf_url:t.swf_url},a),r.call(this,a,s,{access_binary:function(e){return e&&"browser"===c.mode},access_image_binary:function(e){return e&&"browser"===c.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===c.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===c.mode},return_status_code:function(t){return"browser"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===c.mode},send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"browser"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:function(e){return e&&"browser"===c.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===c.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='<object id="'+this.uid+'" type="application/x-shockwave-flash" data="'+a.swf_url+'" ',"IE"===t.browser&&(n+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),n+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+a.swf_url+'" />'+'<param name="flashvars" value="uid='+escape(this.uid)+"&target="+t.global_event_dispatcher+'" />'+'<param name="wmode" value="transparent" />'+'<param name="allowscriptaccess" value="always" />'+"</object>","IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="flash",u={};return r.addConstructor(s,a),u}),i(V,[j,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(W,[j],function(e){var t={init:function(e){this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=t}),i(Y,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i="",r={read:function(e,t){var r=this,o=r.getRuntime();return"readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"),r.bind("Progress",function(t,r){r&&(i+=n(r,e))}),o.shimExec.call(this,"FileReader","readAsBase64",t.uid)},getResult:function(){return i},destroy:function(){i=null}};return e.FileReader=r}),i($,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[j,u,y,w,T,S,O],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var f=i.getBlob();f.isDetached()?u(f,function(e){f.destroy(),s(d,e)}):s(d,f)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[j,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[j,u,O,y,T],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,d,f,p,g],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u<o.length&&a===s);s>=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='<object id="'+this.uid+'" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">'+'<param name="source" value="'+a.xap_url+'"/>'+'<param name="background" value="Transparent"/>'+'<param name="windowless" value="true"/>'+'<param name="enablehtmlaccess" value="true"/>'+'<param name="initParams" value="uid='+this.uid+",target="+t.global_event_dispatcher+'"/>'+"</object>",l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(et,[Q,u,V],function(e,t,n){return e.Blob=t.extend({},n)}),i(tt,[Q],function(e){var t={init:function(e){function t(e){for(var t="",n=0;n<e.length;n++)t+=(""!==t?"|":"")+e[n].title+" | *."+e[n].extensions.replace(/,/g,";*.");return t}this.getRuntime().shimExec.call(this,"FileInput","init",t(e.accept),e.name,e.multiple),this.trigger("ready")}};return e.FileInput=t}),i(nt,[Q,f,L],function(e,t,n){var i={init:function(){var e=this,i=e.getRuntime(),r;return r=i.getShimContainer(),n.addEvent(r,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},e.uid),n.addEvent(r,"dragenter",function(e){e.preventDefault();var n=t.get(i.uid).dragEnter(e);n&&e.stopPropagation()},e.uid),n.addEvent(r,"drop",function(e){e.preventDefault();var n=t.get(i.uid).dragDrop(e);n&&e.stopPropagation()},e.uid),i.shimExec.call(this,"FileDrop","init")}};return e.FileDrop=i}),i(it,[Q,u,Y],function(e,t,n){return e.FileReader=t.extend({},n)}),i(rt,[Q,u,$],function(e,t,n){return e.FileReaderSync=t.extend({},n)}),i(ot,[Q,u,J],function(e,t,n){return e.XMLHttpRequest=t.extend({},n)}),i(at,[Q,u,Z],function(e,t,n){return e.Transporter=t.extend({},n)}),i(st,[Q,u,K],function(e,t,n){return e.Image=t.extend({},n,{getInfo:function(){var e=this.getRuntime(),n=["tiff","exif","gps"],i={meta:{}},r=e.shimExec.call(this,"Image","getInfo");return r.meta&&t.each(n,function(e){var t=r.meta[e],n,o,a,s;if(t&&t.keys)for(i.meta[e]={},o=0,a=t.keys.length;a>o;o++)n=t.keys[o],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),i.meta[e][n]=s)}),i.width=parseInt(r.width,10),i.height=parseInt(r.height,10),i.size=parseInt(r.size,10),i.type=r.type,i.name=r.name,i}})}),i(ut,[u,p,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ct,[ut,u,f,L,l,d],function(e,t,n,i,r,o){function a(){function e(){var r=this,l=r.getRuntime(),d,f,p,h,m,g;g=t.guid("uid_"),d=l.getShimContainer(),a&&(p=n.get(a+"_form"),p&&t.extend(p.style,{top:"100%"})),h=document.createElement("form"),h.setAttribute("id",g+"_form"),h.setAttribute("method","post"),h.setAttribute("enctype","multipart/form-data"),h.setAttribute("encoding","multipart/form-data"),t.extend(h.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),t.extend(m.style,{fontSize:"999px",opacity:0}),h.appendChild(m),d.appendChild(h),t.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===o.browser&&o.version<10&&t.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var t;this.value&&(t=this.files?this.files[0]:{name:this.value},s=[t],this.onchange=function(){},e.call(r),r.bind("change",function i(){var e=n.get(g),t=n.get(g+"_form"),o;r.unbind("change",i),r.files.length&&e&&t&&(o=r.files[0],e.setAttribute("id",o.uid),t.setAttribute("id",o.uid+"_form"),t.setAttribute("target",o.uid+"_iframe")),e=t=null},998),m=h=null,r.trigger("change"))},l.can("summon_file_dialog")&&(f=n.get(c.browse_button),i.removeEvent(f,"click",r.uid),i.addEvent(f,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},r.uid)),a=g,d=p=f=null}var a,s=[],u=[],c;t.extend(this,{init:function(t){var o=this,a=o.getRuntime(),s;c=t,u=t.accept.mimes||r.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,r,u;e=n.get(t.browse_button),a.can("summon_file_dialog")&&("static"===n.getStyle(e,"position")&&(e.style.position="relative"),r=parseInt(n.getStyle(e,"z-index"),10)||1,e.style.zIndex=r,s.style.zIndex=r-1),u=a.can("summon_file_dialog")?e:s,i.addEvent(u,"mouseover",function(){o.trigger("mouseenter")},o.uid),i.addEvent(u,"mouseout",function(){o.trigger("mouseleave")},o.uid),i.addEvent(u,"mousedown",function(){o.trigger("mousedown")},o.uid),i.addEvent(n.get(t.container),"mouseup",function(){o.trigger("mouseup")},o.uid),e=null}(),e.call(this),s=null,o.trigger({type:"ready",async:!0})},getFiles:function(){return s},disable:function(e){var t;(t=n.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),r=e.getShimContainer();i.removeAllEvents(r,this.uid),i.removeAllEvents(c&&n.get(c.container),this.uid),i.removeAllEvents(c&&n.get(c.browse_button),this.uid),r&&(r.innerHTML=""),t.removeInstance(this.uid),a=s=u=c=r=t=null}})}return e.FileInput=a}),i(lt,[ut,F],function(e,t){return e.FileReader=t}),i(dt,[ut,u,f,b,p,L,y,S],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,f){function p(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='<iframe id="'+g+'_iframe" name="'+g+'_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),h.trigger({type:"progress",loaded:c.length,total:c.length}),w&&h.trigger({type:"uploadprogress",loaded:w.size||1025,total:w.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return e.call(h,function(){h.trigger("error")}),void 0;u=404}e.call(h,function(){h.trigger("load")})},h.uid)}var h=this,m=h.getRuntime(),g,v,y,w;if(u=c=null,f instanceof s&&f.hasBlob()){if(w=f.getBlob(),g=w.uid,y=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),v.setAttribute("target",g+"_iframe"),m.getShimContainer().appendChild(v);f instanceof s&&f.each(function(e,n){if(e instanceof a)y&&y.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),y?v.insertBefore(i,y):v.appendChild(i)}}),v.setAttribute("action",d.url),p(),v.submit(),h.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(ft,[ut,X],function(e,t){return e.Image=t}),a([u,c,l,d,f,p,h,m,g,v,y,w,E,_,x,R,b,T,S,A,O,I,L])}(this);;(function(){"use strict";var e={},t=moxie.core.utils.Basic.inArray;return function n(r){var i,s;for(i in r)s=typeof r[i],s==="object"&&!~t(i,["Exceptions","Env","Mime"])?n(r[i]):s==="function"&&(e[i]=r[i])}(window.moxie),e.Env=window.moxie.core.utils.Env,e.Mime=window.moxie.core.utils.Mime,e.Exceptions=window.moxie.core.Exceptions,window.mOxie=e,window.o||(window.o=e),e})();
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/plupload.dev.js ADDED
@@ -0,0 +1,2273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Plupload - multi-runtime File Uploader
3
+ * v2.1.1
4
+ *
5
+ * Copyright 2013, Moxiecode Systems AB
6
+ * Released under GPL License.
7
+ *
8
+ * License: http://www.plupload.com/license
9
+ * Contributing: http://www.plupload.com/contributing
10
+ *
11
+ * Date: 2014-01-16
12
+ */
13
+ /**
14
+ * Plupload.js
15
+ *
16
+ * Copyright 2013, Moxiecode Systems AB
17
+ * Released under GPL License.
18
+ *
19
+ * License: http://www.plupload.com/license
20
+ * Contributing: http://www.plupload.com/contributing
21
+ */
22
+
23
+ /*global mOxie:true */
24
+
25
+ ;(function(window, o, undef) {
26
+
27
+ var delay = window.setTimeout
28
+ , fileFilters = {}
29
+ ;
30
+
31
+ // convert plupload features to caps acceptable by mOxie
32
+ function normalizeCaps(settings) {
33
+ var features = settings.required_features, caps = {};
34
+
35
+ function resolve(feature, value, strict) {
36
+ // Feature notation is deprecated, use caps (this thing here is required for backward compatibility)
37
+ var map = {
38
+ chunks: 'slice_blob',
39
+ jpgresize: 'send_binary_string',
40
+ pngresize: 'send_binary_string',
41
+ progress: 'report_upload_progress',
42
+ multi_selection: 'select_multiple',
43
+ dragdrop: 'drag_and_drop',
44
+ drop_element: 'drag_and_drop',
45
+ headers: 'send_custom_headers',
46
+ canSendBinary: 'send_binary',
47
+ triggerDialog: 'summon_file_dialog'
48
+ };
49
+
50
+ if (map[feature]) {
51
+ caps[map[feature]] = value;
52
+ } else if (!strict) {
53
+ caps[feature] = value;
54
+ }
55
+ }
56
+
57
+ if (typeof(features) === 'string') {
58
+ plupload.each(features.split(/\s*,\s*/), function(feature) {
59
+ resolve(feature, true);
60
+ });
61
+ } else if (typeof(features) === 'object') {
62
+ plupload.each(features, function(value, feature) {
63
+ resolve(feature, value);
64
+ });
65
+ } else if (features === true) {
66
+ // check settings for required features
67
+ if (!settings.multipart) { // special care for multipart: false
68
+ caps.send_binary_string = true;
69
+ }
70
+
71
+ if (settings.chunk_size > 0) {
72
+ caps.slice_blob = true;
73
+ }
74
+
75
+ if (settings.resize.enabled) {
76
+ caps.send_binary_string = true;
77
+ }
78
+
79
+ plupload.each(settings, function(value, feature) {
80
+ resolve(feature, !!value, true); // strict check
81
+ });
82
+ }
83
+
84
+ return caps;
85
+ }
86
+
87
+ /**
88
+ * @module plupload
89
+ * @static
90
+ */
91
+ var plupload = {
92
+ /**
93
+ * Plupload version will be replaced on build.
94
+ *
95
+ * @property VERSION
96
+ * @for Plupload
97
+ * @static
98
+ * @final
99
+ */
100
+ VERSION : '2.1.1',
101
+
102
+ /**
103
+ * Inital state of the queue and also the state ones it's finished all it's uploads.
104
+ *
105
+ * @property STOPPED
106
+ * @static
107
+ * @final
108
+ */
109
+ STOPPED : 1,
110
+
111
+ /**
112
+ * Upload process is running
113
+ *
114
+ * @property STARTED
115
+ * @static
116
+ * @final
117
+ */
118
+ STARTED : 2,
119
+
120
+ /**
121
+ * File is queued for upload
122
+ *
123
+ * @property QUEUED
124
+ * @static
125
+ * @final
126
+ */
127
+ QUEUED : 1,
128
+
129
+ /**
130
+ * File is being uploaded
131
+ *
132
+ * @property UPLOADING
133
+ * @static
134
+ * @final
135
+ */
136
+ UPLOADING : 2,
137
+
138
+ /**
139
+ * File has failed to be uploaded
140
+ *
141
+ * @property FAILED
142
+ * @static
143
+ * @final
144
+ */
145
+ FAILED : 4,
146
+
147
+ /**
148
+ * File has been uploaded successfully
149
+ *
150
+ * @property DONE
151
+ * @static
152
+ * @final
153
+ */
154
+ DONE : 5,
155
+
156
+ // Error constants used by the Error event
157
+
158
+ /**
159
+ * Generic error for example if an exception is thrown inside Silverlight.
160
+ *
161
+ * @property GENERIC_ERROR
162
+ * @static
163
+ * @final
164
+ */
165
+ GENERIC_ERROR : -100,
166
+
167
+ /**
168
+ * HTTP transport error. For example if the server produces a HTTP status other than 200.
169
+ *
170
+ * @property HTTP_ERROR
171
+ * @static
172
+ * @final
173
+ */
174
+ HTTP_ERROR : -200,
175
+
176
+ /**
177
+ * Generic I/O error. For exampe if it wasn't possible to open the file stream on local machine.
178
+ *
179
+ * @property IO_ERROR
180
+ * @static
181
+ * @final
182
+ */
183
+ IO_ERROR : -300,
184
+
185
+ /**
186
+ * Generic I/O error. For exampe if it wasn't possible to open the file stream on local machine.
187
+ *
188
+ * @property SECURITY_ERROR
189
+ * @static
190
+ * @final
191
+ */
192
+ SECURITY_ERROR : -400,
193
+
194
+ /**
195
+ * Initialization error. Will be triggered if no runtime was initialized.
196
+ *
197
+ * @property INIT_ERROR
198
+ * @static
199
+ * @final
200
+ */
201
+ INIT_ERROR : -500,
202
+
203
+ /**
204
+ * File size error. If the user selects a file that is too large it will be blocked and an error of this type will be triggered.
205
+ *
206
+ * @property FILE_SIZE_ERROR
207
+ * @static
208
+ * @final
209
+ */
210
+ FILE_SIZE_ERROR : -600,
211
+
212
+ /**
213
+ * File extension error. If the user selects a file that isn't valid according to the filters setting.
214
+ *
215
+ * @property FILE_EXTENSION_ERROR
216
+ * @static
217
+ * @final
218
+ */
219
+ FILE_EXTENSION_ERROR : -601,
220
+
221
+ /**
222
+ * Duplicate file error. If prevent_duplicates is set to true and user selects the same file again.
223
+ *
224
+ * @property FILE_DUPLICATE_ERROR
225
+ * @static
226
+ * @final
227
+ */
228
+ FILE_DUPLICATE_ERROR : -602,
229
+
230
+ /**
231
+ * Runtime will try to detect if image is proper one. Otherwise will throw this error.
232
+ *
233
+ * @property IMAGE_FORMAT_ERROR
234
+ * @static
235
+ * @final
236
+ */
237
+ IMAGE_FORMAT_ERROR : -700,
238
+
239
+ /**
240
+ * While working on the image runtime will try to detect if the operation may potentially run out of memeory and will throw this error.
241
+ *
242
+ * @property IMAGE_MEMORY_ERROR
243
+ * @static
244
+ * @final
245
+ */
246
+ IMAGE_MEMORY_ERROR : -701,
247
+
248
+ /**
249
+ * Each runtime has an upper limit on a dimension of the image it can handle. If bigger, will throw this error.
250
+ *
251
+ * @property IMAGE_DIMENSIONS_ERROR
252
+ * @static
253
+ * @final
254
+ */
255
+ IMAGE_DIMENSIONS_ERROR : -702,
256
+
257
+ /**
258
+ * Mime type lookup table.
259
+ *
260
+ * @property mimeTypes
261
+ * @type Object
262
+ * @final
263
+ */
264
+ mimeTypes : o.mimes,
265
+
266
+ /**
267
+ * In some cases sniffing is the only way around :(
268
+ */
269
+ ua: o.ua,
270
+
271
+ /**
272
+ * Gets the true type of the built-in object (better version of typeof).
273
+ * @credits Angus Croll (http://javascriptweblog.wordpress.com/)
274
+ *
275
+ * @method typeOf
276
+ * @static
277
+ * @param {Object} o Object to check.
278
+ * @return {String} Object [[Class]]
279
+ */
280
+ typeOf: o.typeOf,
281
+
282
+ /**
283
+ * Extends the specified object with another object.
284
+ *
285
+ * @method extend
286
+ * @static
287
+ * @param {Object} target Object to extend.
288
+ * @param {Object..} obj Multiple objects to extend with.
289
+ * @return {Object} Same as target, the extended object.
290
+ */
291
+ extend : o.extend,
292
+
293
+ /**
294
+ * Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers.
295
+ * The only way a user would be able to get the same ID is if the two persons at the same exact milisecond manages
296
+ * to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique.
297
+ * It's more probable for the earth to be hit with an ansteriod. You can also if you want to be 100% sure set the plupload.guidPrefix property
298
+ * to an user unique key.
299
+ *
300
+ * @method guid
301
+ * @static
302
+ * @return {String} Virtually unique id.
303
+ */
304
+ guid : o.guid,
305
+
306
+ /**
307
+ * Get array of DOM Elements by their ids.
308
+ *
309
+ * @method get
310
+ * @for Utils
311
+ * @param {String} id Identifier of the DOM Element
312
+ * @return {Array}
313
+ */
314
+ get : function get(ids) {
315
+ var els = [], el;
316
+
317
+ if (o.typeOf(ids) !== 'array') {
318
+ ids = [ids];
319
+ }
320
+
321
+ var i = ids.length;
322
+ while (i--) {
323
+ el = o.get(ids[i]);
324
+ if (el) {
325
+ els.push(el);
326
+ }
327
+ }
328
+
329
+ return els.length ? els : null;
330
+ },
331
+
332
+ /**
333
+ * Executes the callback function for each item in array/object. If you return false in the
334
+ * callback it will break the loop.
335
+ *
336
+ * @method each
337
+ * @static
338
+ * @param {Object} obj Object to iterate.
339
+ * @param {function} callback Callback function to execute for each item.
340
+ */
341
+ each : o.each,
342
+
343
+ /**
344
+ * Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields.
345
+ *
346
+ * @method getPos
347
+ * @static
348
+ * @param {Element} node HTML element or element id to get x, y position from.
349
+ * @param {Element} root Optional root element to stop calculations at.
350
+ * @return {object} Absolute position of the specified element object with x, y fields.
351
+ */
352
+ getPos : o.getPos,
353
+
354
+ /**
355
+ * Returns the size of the specified node in pixels.
356
+ *
357
+ * @method getSize
358
+ * @static
359
+ * @param {Node} node Node to get the size of.
360
+ * @return {Object} Object with a w and h property.
361
+ */
362
+ getSize : o.getSize,
363
+
364
+ /**
365
+ * Encodes the specified string.
366
+ *
367
+ * @method xmlEncode
368
+ * @static
369
+ * @param {String} s String to encode.
370
+ * @return {String} Encoded string.
371
+ */
372
+ xmlEncode : function(str) {
373
+ var xmlEncodeChars = {'<' : 'lt', '>' : 'gt', '&' : 'amp', '"' : 'quot', '\'' : '#39'}, xmlEncodeRegExp = /[<>&\"\']/g;
374
+
375
+ return str ? ('' + str).replace(xmlEncodeRegExp, function(chr) {
376
+ return xmlEncodeChars[chr] ? '&' + xmlEncodeChars[chr] + ';' : chr;
377
+ }) : str;
378
+ },
379
+
380
+ /**
381
+ * Forces anything into an array.
382
+ *
383
+ * @method toArray
384
+ * @static
385
+ * @param {Object} obj Object with length field.
386
+ * @return {Array} Array object containing all items.
387
+ */
388
+ toArray : o.toArray,
389
+
390
+ /**
391
+ * Find an element in array and return it's index if present, otherwise return -1.
392
+ *
393
+ * @method inArray
394
+ * @static
395
+ * @param {mixed} needle Element to find
396
+ * @param {Array} array
397
+ * @return {Int} Index of the element, or -1 if not found
398
+ */
399
+ inArray : o.inArray,
400
+
401
+ /**
402
+ * Extends the language pack object with new items.
403
+ *
404
+ * @method addI18n
405
+ * @static
406
+ * @param {Object} pack Language pack items to add.
407
+ * @return {Object} Extended language pack object.
408
+ */
409
+ addI18n : o.addI18n,
410
+
411
+ /**
412
+ * Translates the specified string by checking for the english string in the language pack lookup.
413
+ *
414
+ * @method translate
415
+ * @static
416
+ * @param {String} str String to look for.
417
+ * @return {String} Translated string or the input string if it wasn't found.
418
+ */
419
+ translate : o.translate,
420
+
421
+ /**
422
+ * Checks if object is empty.
423
+ *
424
+ * @method isEmptyObj
425
+ * @static
426
+ * @param {Object} obj Object to check.
427
+ * @return {Boolean}
428
+ */
429
+ isEmptyObj : o.isEmptyObj,
430
+
431
+ /**
432
+ * Checks if specified DOM element has specified class.
433
+ *
434
+ * @method hasClass
435
+ * @static
436
+ * @param {Object} obj DOM element like object to add handler to.
437
+ * @param {String} name Class name
438
+ */
439
+ hasClass : o.hasClass,
440
+
441
+ /**
442
+ * Adds specified className to specified DOM element.
443
+ *
444
+ * @method addClass
445
+ * @static
446
+ * @param {Object} obj DOM element like object to add handler to.
447
+ * @param {String} name Class name
448
+ */
449
+ addClass : o.addClass,
450
+
451
+ /**
452
+ * Removes specified className from specified DOM element.
453
+ *
454
+ * @method removeClass
455
+ * @static
456
+ * @param {Object} obj DOM element like object to add handler to.
457
+ * @param {String} name Class name
458
+ */
459
+ removeClass : o.removeClass,
460
+
461
+ /**
462
+ * Returns a given computed style of a DOM element.
463
+ *
464
+ * @method getStyle
465
+ * @static
466
+ * @param {Object} obj DOM element like object.
467
+ * @param {String} name Style you want to get from the DOM element
468
+ */
469
+ getStyle : o.getStyle,
470
+
471
+ /**
472
+ * Adds an event handler to the specified object and store reference to the handler
473
+ * in objects internal Plupload registry (@see removeEvent).
474
+ *
475
+ * @method addEvent
476
+ * @static
477
+ * @param {Object} obj DOM element like object to add handler to.
478
+ * @param {String} name Name to add event listener to.
479
+ * @param {Function} callback Function to call when event occurs.
480
+ * @param {String} (optional) key that might be used to add specifity to the event record.
481
+ */
482
+ addEvent : o.addEvent,
483
+
484
+ /**
485
+ * Remove event handler from the specified object. If third argument (callback)
486
+ * is not specified remove all events with the specified name.
487
+ *
488
+ * @method removeEvent
489
+ * @static
490
+ * @param {Object} obj DOM element to remove event listener(s) from.
491
+ * @param {String} name Name of event listener to remove.
492
+ * @param {Function|String} (optional) might be a callback or unique key to match.
493
+ */
494
+ removeEvent: o.removeEvent,
495
+
496
+ /**
497
+ * Remove all kind of events from the specified object
498
+ *
499
+ * @method removeAllEvents
500
+ * @static
501
+ * @param {Object} obj DOM element to remove event listeners from.
502
+ * @param {String} (optional) unique key to match, when removing events.
503
+ */
504
+ removeAllEvents: o.removeAllEvents,
505
+
506
+ /**
507
+ * Cleans the specified name from national characters (diacritics). The result will be a name with only a-z, 0-9 and _.
508
+ *
509
+ * @method cleanName
510
+ * @static
511
+ * @param {String} s String to clean up.
512
+ * @return {String} Cleaned string.
513
+ */
514
+ cleanName : function(name) {
515
+ var i, lookup;
516
+
517
+ // Replace diacritics
518
+ lookup = [
519
+ /[\300-\306]/g, 'A', /[\340-\346]/g, 'a',
520
+ /\307/g, 'C', /\347/g, 'c',
521
+ /[\310-\313]/g, 'E', /[\350-\353]/g, 'e',
522
+ /[\314-\317]/g, 'I', /[\354-\357]/g, 'i',
523
+ /\321/g, 'N', /\361/g, 'n',
524
+ /[\322-\330]/g, 'O', /[\362-\370]/g, 'o',
525
+ /[\331-\334]/g, 'U', /[\371-\374]/g, 'u'
526
+ ];
527
+
528
+ for (i = 0; i < lookup.length; i += 2) {
529
+ name = name.replace(lookup[i], lookup[i + 1]);
530
+ }
531
+
532
+ // Replace whitespace
533
+ name = name.replace(/\s+/g, '_');
534
+
535
+ // Remove anything else
536
+ name = name.replace(/[^a-z0-9_\-\.]+/gi, '');
537
+
538
+ return name;
539
+ },
540
+
541
+ /**
542
+ * Builds a full url out of a base URL and an object with items to append as query string items.
543
+ *
544
+ * @method buildUrl
545
+ * @static
546
+ * @param {String} url Base URL to append query string items to.
547
+ * @param {Object} items Name/value object to serialize as a querystring.
548
+ * @return {String} String with url + serialized query string items.
549
+ */
550
+ buildUrl : function(url, items) {
551
+ var query = '';
552
+
553
+ plupload.each(items, function(value, name) {
554
+ query += (query ? '&' : '') + encodeURIComponent(name) + '=' + encodeURIComponent(value);
555
+ });
556
+
557
+ if (query) {
558
+ url += (url.indexOf('?') > 0 ? '&' : '?') + query;
559
+ }
560
+
561
+ return url;
562
+ },
563
+
564
+ /**
565
+ * Formats the specified number as a size string for example 1024 becomes 1 KB.
566
+ *
567
+ * @method formatSize
568
+ * @static
569
+ * @param {Number} size Size to format as string.
570
+ * @return {String} Formatted size string.
571
+ */
572
+ formatSize : function(size) {
573
+
574
+ if (size === undef || /\D/.test(size)) {
575
+ return plupload.translate('N/A');
576
+ }
577
+
578
+ function round(num, precision) {
579
+ return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision);
580
+ }
581
+
582
+ var boundary = Math.pow(1024, 4);
583
+
584
+ // TB
585
+ if (size > boundary) {
586
+ return round(size / boundary, 1) + " " + plupload.translate('tb');
587
+ }
588
+
589
+ // GB
590
+ if (size > (boundary/=1024)) {
591
+ return round(size / boundary, 1) + " " + plupload.translate('gb');
592
+ }
593
+
594
+ // MB
595
+ if (size > (boundary/=1024)) {
596
+ return round(size / boundary, 1) + " " + plupload.translate('mb');
597
+ }
598
+
599
+ // KB
600
+ if (size > 1024) {
601
+ return Math.round(size / 1024) + " " + plupload.translate('kb');
602
+ }
603
+
604
+ return size + " " + plupload.translate('b');
605
+ },
606
+
607
+
608
+ /**
609
+ * Parses the specified size string into a byte value. For example 10kb becomes 10240.
610
+ *
611
+ * @method parseSize
612
+ * @static
613
+ * @param {String|Number} size String to parse or number to just pass through.
614
+ * @return {Number} Size in bytes.
615
+ */
616
+ parseSize : o.parseSizeStr,
617
+
618
+
619
+ /**
620
+ * A way to predict what runtime will be choosen in the current environment with the
621
+ * specified settings.
622
+ *
623
+ * @method predictRuntime
624
+ * @static
625
+ * @param {Object|String} config Plupload settings to check
626
+ * @param {String} [runtimes] Comma-separated list of runtimes to check against
627
+ * @return {String} Type of compatible runtime
628
+ */
629
+ predictRuntime : function(config, runtimes) {
630
+ var up, runtime;
631
+
632
+ up = new plupload.Uploader(config);
633
+ runtime = o.Runtime.thatCan(up.getOption().required_features, runtimes || config.runtimes);
634
+ up.destroy();
635
+ return runtime;
636
+ },
637
+
638
+ /**
639
+ * Registers a filter that will be executed for each file added to the queue.
640
+ * If callback returns false, file will not be added.
641
+ *
642
+ * Callback receives two arguments: a value for the filter as it was specified in settings.filters
643
+ * and a file to be filtered. Callback is executed in the context of uploader instance.
644
+ *
645
+ * @method addFileFilter
646
+ * @static
647
+ * @param {String} name Name of the filter by which it can be referenced in settings.filters
648
+ * @param {String} cb Callback - the actual routine that every added file must pass
649
+ */
650
+ addFileFilter: function(name, cb) {
651
+ fileFilters[name] = cb;
652
+ }
653
+ };
654
+
655
+
656
+ plupload.addFileFilter('mime_types', function(filters, file, cb) {
657
+ if (filters.length && !filters.regexp.test(file.name)) {
658
+ this.trigger('Error', {
659
+ code : plupload.FILE_EXTENSION_ERROR,
660
+ message : plupload.translate('File extension error.'),
661
+ file : file
662
+ });
663
+ cb(false);
664
+ } else {
665
+ cb(true);
666
+ }
667
+ });
668
+
669
+
670
+ plupload.addFileFilter('max_file_size', function(maxSize, file, cb) {
671
+ var undef;
672
+
673
+ maxSize = plupload.parseSize(maxSize);
674
+
675
+ // Invalid file size
676
+ if (file.size !== undef && maxSize && file.size > maxSize) {
677
+ this.trigger('Error', {
678
+ code : plupload.FILE_SIZE_ERROR,
679
+ message : plupload.translate('File size error.'),
680
+ file : file
681
+ });
682
+ cb(false);
683
+ } else {
684
+ cb(true);
685
+ }
686
+ });
687
+
688
+
689
+ plupload.addFileFilter('prevent_duplicates', function(value, file, cb) {
690
+ if (value) {
691
+ var ii = this.files.length;
692
+ while (ii--) {
693
+ // Compare by name and size (size might be 0 or undefined, but still equivalent for both)
694
+ if (file.name === this.files[ii].name && file.size === this.files[ii].size) {
695
+ this.trigger('Error', {
696
+ code : plupload.FILE_DUPLICATE_ERROR,
697
+ message : plupload.translate('Duplicate file error.'),
698
+ file : file
699
+ });
700
+ cb(false);
701
+ return;
702
+ }
703
+ }
704
+ }
705
+ cb(true);
706
+ });
707
+
708
+
709
+ /**
710
+ @class Uploader
711
+ @constructor
712
+
713
+ @param {Object} settings For detailed information about each option check documentation.
714
+ @param {String|DOMElement} settings.browse_button id of the DOM element or DOM element itself to use as file dialog trigger.
715
+ @param {String} settings.url URL of the server-side upload handler.
716
+ @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled.
717
+ @param {String} [settings.container] id of the DOM element to use as a container for uploader structures. Defaults to document.body.
718
+ @param {String|DOMElement} [settings.drop_element] id of the DOM element or DOM element itself to use as a drop zone for Drag-n-Drop.
719
+ @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message.
720
+ @param {Object} [settings.filters={}] Set of file type filters.
721
+ @param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR`
722
+ @param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`.
723
+ @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
724
+ @param {String} [settings.flash_swf_url] URL of the Flash swf.
725
+ @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
726
+ @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
727
+ @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
728
+ @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
729
+ @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
730
+ @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
731
+ @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}`
732
+ @param {Number} [settings.resize.width] If image is bigger, it will be resized.
733
+ @param {Number} [settings.resize.height] If image is bigger, it will be resized.
734
+ @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
735
+ @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
736
+ @param {String} [settings.runtimes="html5,flash,silverlight,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails.
737
+ @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
738
+ @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
739
+ */
740
+ plupload.Uploader = function(options) {
741
+ /**
742
+ * Fires when the current RunTime has been initialized.
743
+ *
744
+ * @event Init
745
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
746
+ */
747
+
748
+ /**
749
+ * Fires after the init event incase you need to perform actions there.
750
+ *
751
+ * @event PostInit
752
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
753
+ */
754
+
755
+ /**
756
+ * Fires when the option is changed in via uploader.setOption().
757
+ *
758
+ * @event OptionChanged
759
+ * @since 2.1
760
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
761
+ * @param {String} name Name of the option that was changed
762
+ * @param {Mixed} value New value for the specified option
763
+ * @param {Mixed} oldValue Previous value of the option
764
+ */
765
+
766
+ /**
767
+ * Fires when the silverlight/flash or other shim needs to move.
768
+ *
769
+ * @event Refresh
770
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
771
+ */
772
+
773
+ /**
774
+ * Fires when the overall state is being changed for the upload queue.
775
+ *
776
+ * @event StateChanged
777
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
778
+ */
779
+
780
+ /**
781
+ * Fires when a file is to be uploaded by the runtime.
782
+ *
783
+ * @event UploadFile
784
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
785
+ * @param {plupload.File} file File to be uploaded.
786
+ */
787
+
788
+ /**
789
+ * Fires when just before a file is uploaded. This event enables you to override settings
790
+ * on the uploader instance before the file is uploaded.
791
+ *
792
+ * @event BeforeUpload
793
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
794
+ * @param {plupload.File} file File to be uploaded.
795
+ */
796
+
797
+ /**
798
+ * Fires when the file queue is changed. In other words when files are added/removed to the files array of the uploader instance.
799
+ *
800
+ * @event QueueChanged
801
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
802
+ */
803
+
804
+ /**
805
+ * Fires while a file is being uploaded. Use this event to update the current file upload progress.
806
+ *
807
+ * @event UploadProgress
808
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
809
+ * @param {plupload.File} file File that is currently being uploaded.
810
+ */
811
+
812
+ /**
813
+ * Fires when file is removed from the queue.
814
+ *
815
+ * @event FilesRemoved
816
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
817
+ * @param {Array} files Array of files that got removed.
818
+ */
819
+
820
+ /**
821
+ * Fires for every filtered file before it is added to the queue.
822
+ *
823
+ * @event FileFiltered
824
+ * @since 2.1
825
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
826
+ * @param {plupload.File} file Another file that has to be added to the queue.
827
+ */
828
+
829
+ /**
830
+ * Fires after files were filtered and added to the queue.
831
+ *
832
+ * @event FilesAdded
833
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
834
+ * @param {Array} files Array of file objects that were added to queue by the user.
835
+ */
836
+
837
+ /**
838
+ * Fires when a file is successfully uploaded.
839
+ *
840
+ * @event FileUploaded
841
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
842
+ * @param {plupload.File} file File that was uploaded.
843
+ * @param {Object} response Object with response properties.
844
+ */
845
+
846
+ /**
847
+ * Fires when file chunk is uploaded.
848
+ *
849
+ * @event ChunkUploaded
850
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
851
+ * @param {plupload.File} file File that the chunk was uploaded for.
852
+ * @param {Object} response Object with response properties.
853
+ */
854
+
855
+ /**
856
+ * Fires when all files in a queue are uploaded.
857
+ *
858
+ * @event UploadComplete
859
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
860
+ * @param {Array} files Array of file objects that was added to queue/selected by the user.
861
+ */
862
+
863
+ /**
864
+ * Fires when a error occurs.
865
+ *
866
+ * @event Error
867
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
868
+ * @param {Object} error Contains code, message and sometimes file and other details.
869
+ */
870
+
871
+ /**
872
+ * Fires when destroy method is called.
873
+ *
874
+ * @event Destroy
875
+ * @param {plupload.Uploader} uploader Uploader instance sending the event.
876
+ */
877
+ var uid = plupload.guid()
878
+ , settings
879
+ , files = []
880
+ , preferred_caps = {}
881
+ , fileInputs = []
882
+ , fileDrops = []
883
+ , startTime
884
+ , total
885
+ , disabled = false
886
+ , xhr
887
+ ;
888
+
889
+
890
+ // Private methods
891
+ function uploadNext() {
892
+ var file, count = 0, i;
893
+
894
+ if (this.state == plupload.STARTED) {
895
+ // Find first QUEUED file
896
+ for (i = 0; i < files.length; i++) {
897
+ if (!file && files[i].status == plupload.QUEUED) {
898
+ file = files[i];
899
+ if (this.trigger("BeforeUpload", file)) {
900
+ file.status = plupload.UPLOADING;
901
+ this.trigger("UploadFile", file);
902
+ }
903
+ } else {
904
+ count++;
905
+ }
906
+ }
907
+
908
+ // All files are DONE or FAILED
909
+ if (count == files.length) {
910
+ if (this.state !== plupload.STOPPED) {
911
+ this.state = plupload.STOPPED;
912
+ this.trigger("StateChanged");
913
+ }
914
+ this.trigger("UploadComplete", files);
915
+ }
916
+ }
917
+ }
918
+
919
+
920
+ function calcFile(file) {
921
+ file.percent = file.size > 0 ? Math.ceil(file.loaded / file.size * 100) : 100;
922
+ calc();
923
+ }
924
+
925
+
926
+ function calc() {
927
+ var i, file;
928
+
929
+ // Reset stats
930
+ total.reset();
931
+
932
+ // Check status, size, loaded etc on all files
933
+ for (i = 0; i < files.length; i++) {
934
+ file = files[i];
935
+
936
+ if (file.size !== undef) {
937
+ // We calculate totals based on original file size
938
+ total.size += file.origSize;
939
+
940
+ // Since we cannot predict file size after resize, we do opposite and
941
+ // interpolate loaded amount to match magnitude of total
942
+ total.loaded += file.loaded * file.origSize / file.size;
943
+ } else {
944
+ total.size = undef;
945
+ }
946
+
947
+ if (file.status == plupload.DONE) {
948
+ total.uploaded++;
949
+ } else if (file.status == plupload.FAILED) {
950
+ total.failed++;
951
+ } else {
952
+ total.queued++;
953
+ }
954
+ }
955
+
956
+ // If we couldn't calculate a total file size then use the number of files to calc percent
957
+ if (total.size === undef) {
958
+ total.percent = files.length > 0 ? Math.ceil(total.uploaded / files.length * 100) : 0;
959
+ } else {
960
+ total.bytesPerSec = Math.ceil(total.loaded / ((+new Date() - startTime || 1) / 1000.0));
961
+ total.percent = total.size > 0 ? Math.ceil(total.loaded / total.size * 100) : 0;
962
+ }
963
+ }
964
+
965
+
966
+ function getRUID() {
967
+ var ctrl = fileInputs[0] || fileDrops[0];
968
+ if (ctrl) {
969
+ return ctrl.getRuntime().uid;
970
+ }
971
+ return false;
972
+ }
973
+
974
+
975
+ function runtimeCan(file, cap) {
976
+ if (file.ruid) {
977
+ var info = o.Runtime.getInfo(file.ruid);
978
+ if (info) {
979
+ return info.can(cap);
980
+ }
981
+ }
982
+ return false;
983
+ }
984
+
985
+
986
+ function bindEventListeners() {
987
+ this.bind('FilesAdded', onFilesAdded);
988
+
989
+ this.bind('CancelUpload', onCancelUpload);
990
+
991
+ this.bind('BeforeUpload', onBeforeUpload);
992
+
993
+ this.bind('UploadFile', onUploadFile);
994
+
995
+ this.bind('UploadProgress', onUploadProgress);
996
+
997
+ this.bind('StateChanged', onStateChanged);
998
+
999
+ this.bind('QueueChanged', calc);
1000
+
1001
+ this.bind('Error', onError);
1002
+
1003
+ this.bind('FileUploaded', onFileUploaded);
1004
+
1005
+ this.bind('Destroy', onDestroy);
1006
+ }
1007
+
1008
+
1009
+ function initControls(settings, cb) {
1010
+ var self = this, inited = 0, queue = [];
1011
+
1012
+ // common settings
1013
+ var options = {
1014
+ accept: settings.filters.mime_types,
1015
+ runtime_order: settings.runtimes,
1016
+ required_caps: settings.required_features,
1017
+ preferred_caps: preferred_caps,
1018
+ swf_url: settings.flash_swf_url,
1019
+ xap_url: settings.silverlight_xap_url
1020
+ };
1021
+
1022
+ // add runtime specific options if any
1023
+ plupload.each(settings.runtimes.split(/\s*,\s*/), function(runtime) {
1024
+ if (settings[runtime]) {
1025
+ options[runtime] = settings[runtime];
1026
+ }
1027
+ });
1028
+
1029
+ // initialize file pickers - there can be many
1030
+ if (settings.browse_button) {
1031
+ plupload.each(settings.browse_button, function(el) {
1032
+ queue.push(function(cb) {
1033
+ var fileInput = new o.FileInput(plupload.extend({}, options, {
1034
+ name: settings.file_data_name,
1035
+ multiple: settings.multi_selection,
1036
+ container: settings.container,
1037
+ browse_button: el
1038
+ }));
1039
+
1040
+ fileInput.onready = function() {
1041
+ var info = o.Runtime.getInfo(this.ruid);
1042
+
1043
+ // for backward compatibility
1044
+ o.extend(self.features, {
1045
+ chunks: info.can('slice_blob'),
1046
+ multipart: info.can('send_multipart'),
1047
+ multi_selection: info.can('select_multiple')
1048
+ });
1049
+
1050
+ inited++;
1051
+ fileInputs.push(this);
1052
+ cb();
1053
+ };
1054
+
1055
+ fileInput.onchange = function() {
1056
+ self.addFile(this.files);
1057
+ };
1058
+
1059
+ fileInput.bind('mouseenter mouseleave mousedown mouseup', function(e) {
1060
+ if (!disabled) {
1061
+ if (settings.browse_button_hover) {
1062
+ if ('mouseenter' === e.type) {
1063
+ o.addClass(el, settings.browse_button_hover);
1064
+ } else if ('mouseleave' === e.type) {
1065
+ o.removeClass(el, settings.browse_button_hover);
1066
+ }
1067
+ }
1068
+
1069
+ if (settings.browse_button_active) {
1070
+ if ('mousedown' === e.type) {
1071
+ o.addClass(el, settings.browse_button_active);
1072
+ } else if ('mouseup' === e.type) {
1073
+ o.removeClass(el, settings.browse_button_active);
1074
+ }
1075
+ }
1076
+ }
1077
+ });
1078
+
1079
+ fileInput.bind('error runtimeerror', function() {
1080
+ fileInput = null;
1081
+ cb();
1082
+ });
1083
+
1084
+ fileInput.init();
1085
+ });
1086
+ });
1087
+ }
1088
+
1089
+ // initialize drop zones
1090
+ if (settings.drop_element) {
1091
+ plupload.each(settings.drop_element, function(el) {
1092
+ queue.push(function(cb) {
1093
+ var fileDrop = new o.FileDrop(plupload.extend({}, options, {
1094
+ drop_zone: el
1095
+ }));
1096
+
1097
+ fileDrop.onready = function() {
1098
+ var info = o.Runtime.getInfo(this.ruid);
1099
+
1100
+ self.features.dragdrop = info.can('drag_and_drop'); // for backward compatibility
1101
+
1102
+ inited++;
1103
+ fileDrops.push(this);
1104
+ cb();
1105
+ };
1106
+
1107
+ fileDrop.ondrop = function() {
1108
+ self.addFile(this.files);
1109
+ };
1110
+
1111
+ fileDrop.bind('error runtimeerror', function() {
1112
+ fileDrop = null;
1113
+ cb();
1114
+ });
1115
+
1116
+ fileDrop.init();
1117
+ });
1118
+ });
1119
+ }
1120
+
1121
+
1122
+ o.inSeries(queue, function() {
1123
+ if (typeof(cb) === 'function') {
1124
+ cb(inited);
1125
+ }
1126
+ });
1127
+ }
1128
+
1129
+
1130
+ function resizeImage(blob, params, cb) {
1131
+ var img = new o.Image();
1132
+
1133
+ try {
1134
+ img.onload = function() {
1135
+ img.downsize(params.width, params.height, params.crop, params.preserve_headers);
1136
+ };
1137
+
1138
+ img.onresize = function() {
1139
+ cb(this.getAsBlob(blob.type, params.quality));
1140
+ this.destroy();
1141
+ };
1142
+
1143
+ img.onerror = function() {
1144
+ cb(blob);
1145
+ };
1146
+
1147
+ img.load(blob);
1148
+ } catch(ex) {
1149
+ cb(blob);
1150
+ }
1151
+ }
1152
+
1153
+
1154
+ function setOption(option, value, init) {
1155
+ var self = this, reinitRequired = false;
1156
+
1157
+ function _setOption(option, value, init) {
1158
+ var oldValue = settings[option];
1159
+
1160
+ switch (option) {
1161
+ case 'max_file_size':
1162
+ if (option === 'max_file_size') {
1163
+ settings.max_file_size = settings.filters.max_file_size = value;
1164
+ }
1165
+ break;
1166
+
1167
+ case 'chunk_size':
1168
+ if (value = plupload.parseSize(value)) {
1169
+ settings[option] = value;
1170
+ }
1171
+ break;
1172
+
1173
+ case 'filters':
1174
+ // for sake of backward compatibility
1175
+ if (plupload.typeOf(value) === 'array') {
1176
+ value = {
1177
+ mime_types: value
1178
+ };
1179
+ }
1180
+
1181
+ if (init) {
1182
+ plupload.extend(settings.filters, value);
1183
+ } else {
1184
+ settings.filters = value;
1185
+ }
1186
+
1187
+ // if file format filters are being updated, regenerate the matching expressions
1188
+ if (value.mime_types) {
1189
+ settings.filters.mime_types.regexp = (function(filters) {
1190
+ var extensionsRegExp = [];
1191
+
1192
+ plupload.each(filters, function(filter) {
1193
+ plupload.each(filter.extensions.split(/,/), function(ext) {
1194
+ if (/^\s*\*\s*$/.test(ext)) {
1195
+ extensionsRegExp.push('\\.*');
1196
+ } else {
1197
+ extensionsRegExp.push('\\.' + ext.replace(new RegExp('[' + ('/^$.*+?|()[]{}\\'.replace(/./g, '\\$&')) + ']', 'g'), '\\$&'));
1198
+ }
1199
+ });
1200
+ });
1201
+
1202
+ return new RegExp('(' + extensionsRegExp.join('|') + ')$', 'i');
1203
+ }(settings.filters.mime_types));
1204
+ }
1205
+ break;
1206
+
1207
+ case 'resize':
1208
+ if (init) {
1209
+ plupload.extend(settings.resize, value, {
1210
+ enabled: true
1211
+ });
1212
+ } else {
1213
+ settings.resize = value;
1214
+ }
1215
+ break;
1216
+
1217
+ case 'prevent_duplicates':
1218
+ settings.prevent_duplicates = settings.filters.prevent_duplicates = !!value;
1219
+ break;
1220
+
1221
+ case 'browse_button':
1222
+ case 'drop_element':
1223
+ value = plupload.get(value);
1224
+
1225
+ case 'container':
1226
+ case 'runtimes':
1227
+ case 'multi_selection':
1228
+ case 'flash_swf_url':
1229
+ case 'silverlight_xap_url':
1230
+ settings[option] = value;
1231
+ if (!init) {
1232
+ reinitRequired = true;
1233
+ }
1234
+ break;
1235
+
1236
+ default:
1237
+ settings[option] = value;
1238
+ }
1239
+
1240
+ if (!init) {
1241
+ self.trigger('OptionChanged', option, value, oldValue);
1242
+ }
1243
+ }
1244
+
1245
+ if (typeof(option) === 'object') {
1246
+ plupload.each(option, function(value, option) {
1247
+ _setOption(option, value, init);
1248
+ });
1249
+ } else {
1250
+ _setOption(option, value, init);
1251
+ }
1252
+
1253
+ if (init) {
1254
+ // Normalize the list of required capabilities
1255
+ settings.required_features = normalizeCaps(plupload.extend({}, settings));
1256
+
1257
+ // Come up with the list of capabilities that can affect default mode in a multi-mode runtimes
1258
+ preferred_caps = normalizeCaps(plupload.extend({}, settings, {
1259
+ required_features: true
1260
+ }));
1261
+ } else if (reinitRequired) {
1262
+ self.trigger('Destroy');
1263
+
1264
+ initControls.call(self, settings, function(inited) {
1265
+ if (inited) {
1266
+ self.runtime = o.Runtime.getInfo(getRUID()).type;
1267
+ self.trigger('Init', { runtime: self.runtime });
1268
+ self.trigger('PostInit');
1269
+ } else {
1270
+ self.trigger('Error', {
1271
+ code : plupload.INIT_ERROR,
1272
+ message : plupload.translate('Init error.')
1273
+ });
1274
+ }
1275
+ });
1276
+ }
1277
+ }
1278
+
1279
+
1280
+ // Internal event handlers
1281
+ function onFilesAdded(up, filteredFiles) {
1282
+ // Add files to queue
1283
+ [].push.apply(files, filteredFiles);
1284
+
1285
+ up.trigger('QueueChanged');
1286
+ up.refresh();
1287
+ }
1288
+
1289
+
1290
+ function onBeforeUpload(up, file) {
1291
+ // Generate unique target filenames
1292
+ if (settings.unique_names) {
1293
+ var matches = file.name.match(/\.([^.]+)$/), ext = "part";
1294
+ if (matches) {
1295
+ ext = matches[1];
1296
+ }
1297
+ file.target_name = file.id + '.' + ext;
1298
+ }
1299
+ }
1300
+
1301
+
1302
+ function onUploadFile(up, file) {
1303
+ var url = up.settings.url
1304
+ , chunkSize = up.settings.chunk_size
1305
+ , retries = up.settings.max_retries
1306
+ , features = up.features
1307
+ , offset = 0
1308
+ , blob
1309
+ ;
1310
+
1311
+ // make sure we start at a predictable offset
1312
+ if (file.loaded) {
1313
+ offset = file.loaded = chunkSize * Math.floor(file.loaded / chunkSize);
1314
+ }
1315
+
1316
+ function handleError() {
1317
+ if (retries-- > 0) {
1318
+ delay(uploadNextChunk, 1000);
1319
+ } else {
1320
+ file.loaded = offset; // reset all progress
1321
+
1322
+ up.trigger('Error', {
1323
+ code : plupload.HTTP_ERROR,
1324
+ message : plupload.translate('HTTP Error.'),
1325
+ file : file,
1326
+ response : xhr.responseText,
1327
+ status : xhr.status,
1328
+ responseHeaders: xhr.getAllResponseHeaders()
1329
+ });
1330
+ }
1331
+ }
1332
+
1333
+ function uploadNextChunk() {
1334
+ var chunkBlob, formData, args, curChunkSize;
1335
+
1336
+ // File upload finished
1337
+ if (file.status == plupload.DONE || file.status == plupload.FAILED || up.state == plupload.STOPPED) {
1338
+ return;
1339
+ }
1340
+
1341
+ // Standard arguments
1342
+ args = {name : file.target_name || file.name};
1343
+
1344
+ if (chunkSize && features.chunks && blob.size > chunkSize) { // blob will be of type string if it was loaded in memory
1345
+ curChunkSize = Math.min(chunkSize, blob.size - offset);
1346
+ chunkBlob = blob.slice(offset, offset + curChunkSize);
1347
+ } else {
1348
+ curChunkSize = blob.size;
1349
+ chunkBlob = blob;
1350
+ }
1351
+
1352
+ // If chunking is enabled add corresponding args, no matter if file is bigger than chunk or smaller
1353
+ if (chunkSize && features.chunks) {
1354
+ // Setup query string arguments
1355
+ if (up.settings.send_chunk_number) {
1356
+ args.chunk = Math.ceil(offset / chunkSize);
1357
+ args.chunks = Math.ceil(blob.size / chunkSize);
1358
+ } else { // keep support for experimental chunk format, just in case
1359
+ args.offset = offset;
1360
+ args.total = blob.size;
1361
+ }
1362
+ }
1363
+
1364
+ xhr = new o.XMLHttpRequest();
1365
+
1366
+ // Do we have upload progress support
1367
+ if (xhr.upload) {
1368
+ xhr.upload.onprogress = function(e) {
1369
+ file.loaded = Math.min(file.size, offset + e.loaded);
1370
+ up.trigger('UploadProgress', file);
1371
+ };
1372
+ }
1373
+
1374
+ xhr.onload = function() {
1375
+ // check if upload made itself through
1376
+ if (xhr.status >= 400) {
1377
+ handleError();
1378
+ return;
1379
+ }
1380
+
1381
+ retries = up.settings.max_retries; // reset the counter
1382
+
1383
+ // Handle chunk response
1384
+ if (curChunkSize < blob.size) {
1385
+ chunkBlob.destroy();
1386
+
1387
+ offset += curChunkSize;
1388
+ file.loaded = Math.min(offset, blob.size);
1389
+
1390
+ up.trigger('ChunkUploaded', file, {
1391
+ offset : file.loaded,
1392
+ total : blob.size,
1393
+ response : xhr.responseText,
1394
+ status : xhr.status,
1395
+ responseHeaders: xhr.getAllResponseHeaders()
1396
+ });
1397
+
1398
+ // stock Android browser doesn't fire upload progress events, but in chunking mode we can fake them
1399
+ if (o.Env.browser === 'Android Browser') {
1400
+ // doesn't harm in general, but is not required anywhere else
1401
+ up.trigger('UploadProgress', file);
1402
+ }
1403
+ } else {
1404
+ file.loaded = file.size;
1405
+ }
1406
+
1407
+ chunkBlob = formData = null; // Free memory
1408
+
1409
+ // Check if file is uploaded
1410
+ if (!offset || offset >= blob.size) {
1411
+ // If file was modified, destory the copy
1412
+ if (file.size != file.origSize) {
1413
+ blob.destroy();
1414
+ blob = null;
1415
+ }
1416
+
1417
+ up.trigger('UploadProgress', file);
1418
+
1419
+ file.status = plupload.DONE;
1420
+
1421
+ up.trigger('FileUploaded', file, {
1422
+ response : xhr.responseText,
1423
+ status : xhr.status,
1424
+ responseHeaders: xhr.getAllResponseHeaders()
1425
+ });
1426
+ } else {
1427
+ // Still chunks left
1428
+ delay(uploadNextChunk, 1); // run detached, otherwise event handlers interfere
1429
+ }
1430
+ };
1431
+
1432
+ xhr.onerror = function() {
1433
+ handleError();
1434
+ };
1435
+
1436
+ xhr.onloadend = function() {
1437
+ this.destroy();
1438
+ xhr = null;
1439
+ };
1440
+
1441
+ // Build multipart request
1442
+ if (up.settings.multipart && features.multipart) {
1443
+
1444
+ args.name = file.target_name || file.name;
1445
+
1446
+ xhr.open("post", url, true);
1447
+
1448
+ // Set custom headers
1449
+ plupload.each(up.settings.headers, function(value, name) {
1450
+ xhr.setRequestHeader(name, value);
1451
+ });
1452
+
1453
+ formData = new o.FormData();
1454
+
1455
+ // Add multipart params
1456
+ plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) {
1457
+ formData.append(name, value);
1458
+ });
1459
+
1460
+ // Add file and send it
1461
+ formData.append(up.settings.file_data_name, chunkBlob);
1462
+ xhr.send(formData, {
1463
+ runtime_order: up.settings.runtimes,
1464
+ required_caps: up.settings.required_features,
1465
+ preferred_caps: preferred_caps,
1466
+ swf_url: up.settings.flash_swf_url,
1467
+ xap_url: up.settings.silverlight_xap_url
1468
+ });
1469
+ } else {
1470
+ // if no multipart, send as binary stream
1471
+ url = plupload.buildUrl(up.settings.url, plupload.extend(args, up.settings.multipart_params));
1472
+
1473
+ xhr.open("post", url, true);
1474
+
1475
+ xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // Binary stream header
1476
+
1477
+ // Set custom headers
1478
+ plupload.each(up.settings.headers, function(value, name) {
1479
+ xhr.setRequestHeader(name, value);
1480
+ });
1481
+
1482
+ xhr.send(chunkBlob, {
1483
+ runtime_order: up.settings.runtimes,
1484
+ required_caps: up.settings.required_features,
1485
+ preferred_caps: preferred_caps,
1486
+ swf_url: up.settings.flash_swf_url,
1487
+ xap_url: up.settings.silverlight_xap_url
1488
+ });
1489
+ }
1490
+ }
1491
+
1492
+ blob = file.getSource();
1493
+
1494
+ // Start uploading chunks
1495
+ if (up.settings.resize.enabled && runtimeCan(blob, 'send_binary_string') && !!~o.inArray(blob.type, ['image/jpeg', 'image/png'])) {
1496
+ // Resize if required
1497
+ resizeImage.call(this, blob, up.settings.resize, function(resizedBlob) {
1498
+ blob = resizedBlob;
1499
+ file.size = resizedBlob.size;
1500
+ uploadNextChunk();
1501
+ });
1502
+ } else {
1503
+ uploadNextChunk();
1504
+ }
1505
+ }
1506
+
1507
+
1508
+ function onUploadProgress(up, file) {
1509
+ calcFile(file);
1510
+ }
1511
+
1512
+
1513
+ function onStateChanged(up) {
1514
+ if (up.state == plupload.STARTED) {
1515
+ // Get start time to calculate bps
1516
+ startTime = (+new Date());
1517
+ } else if (up.state == plupload.STOPPED) {
1518
+ // Reset currently uploading files
1519
+ for (var i = up.files.length - 1; i >= 0; i--) {
1520
+ if (up.files[i].status == plupload.UPLOADING) {
1521
+ up.files[i].status = plupload.QUEUED;
1522
+ calc();
1523
+ }
1524
+ }
1525
+ }
1526
+ }
1527
+
1528
+
1529
+ function onCancelUpload() {
1530
+ if (xhr) {
1531
+ xhr.abort();
1532
+ }
1533
+ }
1534
+
1535
+
1536
+ function onFileUploaded(up) {
1537
+ calc();
1538
+
1539
+ // Upload next file but detach it from the error event
1540
+ // since other custom listeners might want to stop the queue
1541
+ delay(function() {
1542
+ uploadNext.call(up);
1543
+ }, 1);
1544
+ }
1545
+
1546
+
1547
+ function onError(up, err) {
1548
+ // Set failed status if an error occured on a file
1549
+ if (err.file) {
1550
+ err.file.status = plupload.FAILED;
1551
+ calcFile(err.file);
1552
+
1553
+ // Upload next file but detach it from the error event
1554
+ // since other custom listeners might want to stop the queue
1555
+ if (up.state == plupload.STARTED) { // upload in progress
1556
+ up.trigger('CancelUpload');
1557
+ delay(function() {
1558
+ uploadNext.call(up);
1559
+ }, 1);
1560
+ }
1561
+ }
1562
+ }
1563
+
1564
+
1565
+ function onDestroy(up) {
1566
+ up.stop();
1567
+
1568
+ // Purge the queue
1569
+ plupload.each(files, function(file) {
1570
+ file.destroy();
1571
+ });
1572
+ files = [];
1573
+
1574
+ if (fileInputs.length) {
1575
+ plupload.each(fileInputs, function(fileInput) {
1576
+ fileInput.destroy();
1577
+ });
1578
+ fileInputs = [];
1579
+ }
1580
+
1581
+ if (fileDrops.length) {
1582
+ plupload.each(fileDrops, function(fileDrop) {
1583
+ fileDrop.destroy();
1584
+ });
1585
+ fileDrops = [];
1586
+ }
1587
+
1588
+ preferred_caps = {};
1589
+ disabled = false;
1590
+ startTime = xhr = null;
1591
+ total.reset();
1592
+ }
1593
+
1594
+
1595
+ // Default settings
1596
+ settings = {
1597
+ runtimes: o.Runtime.order,
1598
+ max_retries: 0,
1599
+ chunk_size: 0,
1600
+ multipart: true,
1601
+ multi_selection: true,
1602
+ file_data_name: 'file',
1603
+ flash_swf_url: 'js/Moxie.swf',
1604
+ silverlight_xap_url: 'js/Moxie.xap',
1605
+ filters: {
1606
+ mime_types: [],
1607
+ prevent_duplicates: false,
1608
+ max_file_size: 0
1609
+ },
1610
+ resize: {
1611
+ enabled: false,
1612
+ preserve_headers: true,
1613
+ crop: false
1614
+ },
1615
+ send_chunk_number: true // whether to send chunks and chunk numbers, or total and offset bytes
1616
+ };
1617
+
1618
+
1619
+ setOption.call(this, options, null, true);
1620
+
1621
+ // Inital total state
1622
+ total = new plupload.QueueProgress();
1623
+
1624
+ // Add public methods
1625
+ plupload.extend(this, {
1626
+
1627
+ /**
1628
+ * Unique id for the Uploader instance.
1629
+ *
1630
+ * @property id
1631
+ * @type String
1632
+ */
1633
+ id : uid,
1634
+ uid : uid, // mOxie uses this to differentiate between event targets
1635
+
1636
+ /**
1637
+ * Current state of the total uploading progress. This one can either be plupload.STARTED or plupload.STOPPED.
1638
+ * These states are controlled by the stop/start methods. The default value is STOPPED.
1639
+ *
1640
+ * @property state
1641
+ * @type Number
1642
+ */
1643
+ state : plupload.STOPPED,
1644
+
1645
+ /**
1646
+ * Map of features that are available for the uploader runtime. Features will be filled
1647
+ * before the init event is called, these features can then be used to alter the UI for the end user.
1648
+ * Some of the current features that might be in this map is: dragdrop, chunks, jpgresize, pngresize.
1649
+ *
1650
+ * @property features
1651
+ * @type Object
1652
+ */
1653
+ features : {},
1654
+
1655
+ /**
1656
+ * Current runtime name.
1657
+ *
1658
+ * @property runtime
1659
+ * @type String
1660
+ */
1661
+ runtime : null,
1662
+
1663
+ /**
1664
+ * Current upload queue, an array of File instances.
1665
+ *
1666
+ * @property files
1667
+ * @type Array
1668
+ * @see plupload.File
1669
+ */
1670
+ files : files,
1671
+
1672
+ /**
1673
+ * Object with name/value settings.
1674
+ *
1675
+ * @property settings
1676
+ * @type Object
1677
+ */
1678
+ settings : settings,
1679
+
1680
+ /**
1681
+ * Total progess information. How many files has been uploaded, total percent etc.
1682
+ *
1683
+ * @property total
1684
+ * @type plupload.QueueProgress
1685
+ */
1686
+ total : total,
1687
+
1688
+
1689
+ /**
1690
+ * Initializes the Uploader instance and adds internal event listeners.
1691
+ *
1692
+ * @method init
1693
+ */
1694
+ init : function() {
1695
+ var self = this;
1696
+
1697
+ if (typeof(settings.preinit) == "function") {
1698
+ settings.preinit(self);
1699
+ } else {
1700
+ plupload.each(settings.preinit, function(func, name) {
1701
+ self.bind(name, func);
1702
+ });
1703
+ }
1704
+
1705
+ // Check for required options
1706
+ if (!settings.browse_button || !settings.url) {
1707
+ this.trigger('Error', {
1708
+ code : plupload.INIT_ERROR,
1709
+ message : plupload.translate('Init error.')
1710
+ });
1711
+ return;
1712
+ }
1713
+
1714
+ bindEventListeners.call(this);
1715
+
1716
+ initControls.call(this, settings, function(inited) {
1717
+ if (typeof(settings.init) == "function") {
1718
+ settings.init(self);
1719
+ } else {
1720
+ plupload.each(settings.init, function(func, name) {
1721
+ self.bind(name, func);
1722
+ });
1723
+ }
1724
+
1725
+ if (inited) {
1726
+ self.runtime = o.Runtime.getInfo(getRUID()).type;
1727
+ self.trigger('Init', { runtime: self.runtime });
1728
+ self.trigger('PostInit');
1729
+ } else {
1730
+ self.trigger('Error', {
1731
+ code : plupload.INIT_ERROR,
1732
+ message : plupload.translate('Init error.')
1733
+ });
1734
+ }
1735
+ });
1736
+ },
1737
+
1738
+ /**
1739
+ * Set the value for the specified option(s).
1740
+ *
1741
+ * @method setOption
1742
+ * @since 2.1
1743
+ * @param {String|Object} option Name of the option to change or the set of key/value pairs
1744
+ * @param {Mixed} [value] Value for the option (is ignored, if first argument is object)
1745
+ */
1746
+ setOption: function(option, value) {
1747
+ setOption.call(this, option, value, !this.runtime); // until runtime not set we do not need to reinitialize
1748
+ },
1749
+
1750
+ /**
1751
+ * Get the value for the specified option or the whole configuration, if not specified.
1752
+ *
1753
+ * @method getOption
1754
+ * @since 2.1
1755
+ * @param {String} [option] Name of the option to get
1756
+ * @return {Mixed} Value for the option or the whole set
1757
+ */
1758
+ getOption: function(option) {
1759
+ if (!option) {
1760
+ return settings;
1761
+ }
1762
+ return settings[option];
1763
+ },
1764
+
1765
+ /**
1766
+ * Refreshes the upload instance by dispatching out a refresh event to all runtimes.
1767
+ * This would for example reposition flash/silverlight shims on the page.
1768
+ *
1769
+ * @method refresh
1770
+ */
1771
+ refresh : function() {
1772
+ if (fileInputs.length) {
1773
+ plupload.each(fileInputs, function(fileInput) {
1774
+ fileInput.trigger('Refresh');
1775
+ });
1776
+ }
1777
+ this.trigger('Refresh');
1778
+ },
1779
+
1780
+ /**
1781
+ * Starts uploading the queued files.
1782
+ *
1783
+ * @method start
1784
+ */
1785
+ start : function() {
1786
+ if (this.state != plupload.STARTED) {
1787
+ this.state = plupload.STARTED;
1788
+ this.trigger('StateChanged');
1789
+
1790
+ uploadNext.call(this);
1791
+ }
1792
+ },
1793
+
1794
+ /**
1795
+ * Stops the upload of the queued files.
1796
+ *
1797
+ * @method stop
1798
+ */
1799
+ stop : function() {
1800
+ if (this.state != plupload.STOPPED) {
1801
+ this.state = plupload.STOPPED;
1802
+ this.trigger('StateChanged');
1803
+ this.trigger('CancelUpload');
1804
+ }
1805
+ },
1806
+
1807
+
1808
+ /**
1809
+ * Disables/enables browse button on request.
1810
+ *
1811
+ * @method disableBrowse
1812
+ * @param {Boolean} disable Whether to disable or enable (default: true)
1813
+ */
1814
+ disableBrowse : function() {
1815
+ disabled = arguments[0] !== undef ? arguments[0] : true;
1816
+
1817
+ if (fileInputs.length) {
1818
+ plupload.each(fileInputs, function(fileInput) {
1819
+ fileInput.disable(disabled);
1820
+ });
1821
+ }
1822
+
1823
+ this.trigger('DisableBrowse', disabled);
1824
+ },
1825
+
1826
+ /**
1827
+ * Returns the specified file object by id.
1828
+ *
1829
+ * @method getFile
1830
+ * @param {String} id File id to look for.
1831
+ * @return {plupload.File} File object or undefined if it wasn't found;
1832
+ */
1833
+ getFile : function(id) {
1834
+ var i;
1835
+ for (i = files.length - 1; i >= 0; i--) {
1836
+ if (files[i].id === id) {
1837
+ return files[i];
1838
+ }
1839
+ }
1840
+ },
1841
+
1842
+ /**
1843
+ * Adds file to the queue programmatically. Can be native file, instance of Plupload.File,
1844
+ * instance of mOxie.File, input[type="file"] element, or array of these. Fires FilesAdded,
1845
+ * if any files were added to the queue. Otherwise nothing happens.
1846
+ *
1847
+ * @method addFile
1848
+ * @since 2.0
1849
+ * @param {plupload.File|mOxie.File|File|Node|Array} file File or files to add to the queue.
1850
+ * @param {String} [fileName] If specified, will be used as a name for the file
1851
+ */
1852
+ addFile : function(file, fileName) {
1853
+ var self = this
1854
+ , queue = []
1855
+ , files = []
1856
+ , ruid
1857
+ ;
1858
+
1859
+ function filterFile(file, cb) {
1860
+ var queue = [];
1861
+ o.each(self.settings.filters, function(rule, name) {
1862
+ if (fileFilters[name]) {
1863
+ queue.push(function(cb) {
1864
+ fileFilters[name].call(self, rule, file, function(res) {
1865
+ cb(!res);
1866
+ });
1867
+ });
1868
+ }
1869
+ });
1870
+ o.inSeries(queue, cb);
1871
+ }
1872
+
1873
+ /**
1874
+ * @method resolveFile
1875
+ * @private
1876
+ * @param {o.File|o.Blob|plupload.File|File|Blob|input[type="file"]} file
1877
+ */
1878
+ function resolveFile(file) {
1879
+ var type = o.typeOf(file);
1880
+
1881
+ // o.File
1882
+ if (file instanceof o.File) {
1883
+ if (!file.ruid && !file.isDetached()) {
1884
+ if (!ruid) { // weird case
1885
+ return false;
1886
+ }
1887
+ file.ruid = ruid;
1888
+ file.connectRuntime(ruid);
1889
+ }
1890
+ resolveFile(new plupload.File(file));
1891
+ }
1892
+ // o.Blob
1893
+ else if (file instanceof o.Blob) {
1894
+ resolveFile(file.getSource());
1895
+ file.destroy();
1896
+ }
1897
+ // plupload.File - final step for other branches
1898
+ else if (file instanceof plupload.File) {
1899
+ if (fileName) {
1900
+ file.name = fileName;
1901
+ }
1902
+
1903
+ queue.push(function(cb) {
1904
+ // run through the internal and user-defined filters, if any
1905
+ filterFile(file, function(err) {
1906
+ if (!err) {
1907
+ files.push(file);
1908
+ self.trigger("FileFiltered", file);
1909
+ }
1910
+ delay(cb, 1); // do not build up recursions or eventually we might hit the limits
1911
+ });
1912
+ });
1913
+ }
1914
+ // native File or blob
1915
+ else if (o.inArray(type, ['file', 'blob']) !== -1) {
1916
+ resolveFile(new o.File(null, file));
1917
+ }
1918
+ // input[type="file"]
1919
+ else if (type === 'node' && o.typeOf(file.files) === 'filelist') {
1920
+ // if we are dealing with input[type="file"]
1921
+ o.each(file.files, resolveFile);
1922
+ }
1923
+ // mixed array of any supported types (see above)
1924
+ else if (type === 'array') {
1925
+ fileName = null; // should never happen, but unset anyway to avoid funny situations
1926
+ o.each(file, resolveFile);
1927
+ }
1928
+ }
1929
+
1930
+ ruid = getRUID();
1931
+
1932
+ resolveFile(file);
1933
+
1934
+ if (queue.length) {
1935
+ o.inSeries(queue, function() {
1936
+ // if any files left after filtration, trigger FilesAdded
1937
+ if (files.length) {
1938
+ self.trigger("FilesAdded", files);
1939
+ }
1940
+ });
1941
+ }
1942
+ },
1943
+
1944
+ /**
1945
+ * Removes a specific file.
1946
+ *
1947
+ * @method removeFile
1948
+ * @param {plupload.File|String} file File to remove from queue.
1949
+ */
1950
+ removeFile : function(file) {
1951
+ var id = typeof(file) === 'string' ? file : file.id;
1952
+
1953
+ for (var i = files.length - 1; i >= 0; i--) {
1954
+ if (files[i].id === id) {
1955
+ return this.splice(i, 1)[0];
1956
+ }
1957
+ }
1958
+ },
1959
+
1960
+ /**
1961
+ * Removes part of the queue and returns the files removed. This will also trigger the FilesRemoved and QueueChanged events.
1962
+ *
1963
+ * @method splice
1964
+ * @param {Number} start (Optional) Start index to remove from.
1965
+ * @param {Number} length (Optional) Lengh of items to remove.
1966
+ * @return {Array} Array of files that was removed.
1967
+ */
1968
+ splice : function(start, length) {
1969
+ // Splice and trigger events
1970
+ var removed = files.splice(start === undef ? 0 : start, length === undef ? files.length : length);
1971
+
1972
+ // if upload is in progress we need to stop it and restart after files are removed
1973
+ var restartRequired = false;
1974
+ if (this.state == plupload.STARTED) { // upload in progress
1975
+ restartRequired = true;
1976
+ this.stop();
1977
+ }
1978
+
1979
+ this.trigger("FilesRemoved", removed);
1980
+
1981
+ // Dispose any resources allocated by those files
1982
+ plupload.each(removed, function(file) {
1983
+ file.destroy();
1984
+ });
1985
+
1986
+ this.trigger("QueueChanged");
1987
+ this.refresh();
1988
+
1989
+ if (restartRequired) {
1990
+ this.start();
1991
+ }
1992
+
1993
+ return removed;
1994
+ },
1995
+
1996
+ /**
1997
+ * Dispatches the specified event name and it's arguments to all listeners.
1998
+ *
1999
+ *
2000
+ * @method trigger
2001
+ * @param {String} name Event name to fire.
2002
+ * @param {Object..} Multiple arguments to pass along to the listener functions.
2003
+ */
2004
+
2005
+ /**
2006
+ * Check whether uploader has any listeners to the specified event.
2007
+ *
2008
+ * @method hasEventListener
2009
+ * @param {String} name Event name to check for.
2010
+ */
2011
+
2012
+
2013
+ /**
2014
+ * Adds an event listener by name.
2015
+ *
2016
+ * @method bind
2017
+ * @param {String} name Event name to listen for.
2018
+ * @param {function} func Function to call ones the event gets fired.
2019
+ * @param {Object} scope Optional scope to execute the specified function in.
2020
+ */
2021
+ bind : function(name, func, scope) {
2022
+ var self = this;
2023
+ // adapt moxie EventTarget style to Plupload-like
2024
+ plupload.Uploader.prototype.bind.call(this, name, function() {
2025
+ var args = [].slice.call(arguments);
2026
+ args.splice(0, 1, self); // replace event object with uploader instance
2027
+ return func.apply(this, args);
2028
+ }, 0, scope);
2029
+ },
2030
+
2031
+ /**
2032
+ * Removes the specified event listener.
2033
+ *
2034
+ * @method unbind
2035
+ * @param {String} name Name of event to remove.
2036
+ * @param {function} func Function to remove from listener.
2037
+ */
2038
+
2039
+ /**
2040
+ * Removes all event listeners.
2041
+ *
2042
+ * @method unbindAll
2043
+ */
2044
+
2045
+
2046
+ /**
2047
+ * Destroys Plupload instance and cleans after itself.
2048
+ *
2049
+ * @method destroy
2050
+ */
2051
+ destroy : function() {
2052
+ this.trigger('Destroy');
2053
+ settings = total = null; // purge these exclusively
2054
+ this.unbindAll();
2055
+ }
2056
+ });
2057
+ };
2058
+
2059
+ plupload.Uploader.prototype = o.EventTarget.instance;
2060
+
2061
+ /**
2062
+ * Constructs a new file instance.
2063
+ *
2064
+ * @class File
2065
+ * @constructor
2066
+ *
2067
+ * @param {Object} file Object containing file properties
2068
+ * @param {String} file.name Name of the file.
2069
+ * @param {Number} file.size File size.
2070
+ */
2071
+ plupload.File = (function() {
2072
+ var filepool = {};
2073
+
2074
+ function PluploadFile(file) {
2075
+
2076
+ plupload.extend(this, {
2077
+
2078
+ /**
2079
+ * File id this is a globally unique id for the specific file.
2080
+ *
2081
+ * @property id
2082
+ * @type String
2083
+ */
2084
+ id: plupload.guid(),
2085
+
2086
+ /**
2087
+ * File name for example "myfile.gif".
2088
+ *
2089
+ * @property name
2090
+ * @type String
2091
+ */
2092
+ name: file.name || file.fileName,
2093
+
2094
+ /**
2095
+ * File type, `e.g image/jpeg`
2096
+ *
2097
+ * @property type
2098
+ * @type String
2099
+ */
2100
+ type: file.type || '',
2101
+
2102
+ /**
2103
+ * File size in bytes (may change after client-side manupilation).
2104
+ *
2105
+ * @property size
2106
+ * @type Number
2107
+ */
2108
+ size: file.size || file.fileSize,
2109
+
2110
+ /**
2111
+ * Original file size in bytes.
2112
+ *
2113
+ * @property origSize
2114
+ * @type Number
2115
+ */
2116
+ origSize: file.size || file.fileSize,
2117
+
2118
+ /**
2119
+ * Number of bytes uploaded of the files total size.
2120
+ *
2121
+ * @property loaded
2122
+ * @type Number
2123
+ */
2124
+ loaded: 0,
2125
+
2126
+ /**
2127
+ * Number of percentage uploaded of the file.
2128
+ *
2129
+ * @property percent
2130
+ * @type Number
2131
+ */
2132
+ percent: 0,
2133
+
2134
+ /**
2135
+ * Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
2136
+ *
2137
+ * @property status
2138
+ * @type Number
2139
+ * @see plupload
2140
+ */
2141
+ status: plupload.QUEUED,
2142
+
2143
+ /**
2144
+ * Date of last modification.
2145
+ *
2146
+ * @property lastModifiedDate
2147
+ * @type {String}
2148
+ */
2149
+ lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString(), // Thu Aug 23 2012 19:40:00 GMT+0400 (GET)
2150
+
2151
+ /**
2152
+ * Returns native window.File object, when it's available.
2153
+ *
2154
+ * @method getNative
2155
+ * @return {window.File} or null, if plupload.File is of different origin
2156
+ */
2157
+ getNative: function() {
2158
+ var file = this.getSource().getSource();
2159
+ return o.inArray(o.typeOf(file), ['blob', 'file']) !== -1 ? file : null;
2160
+ },
2161
+
2162
+ /**
2163
+ * Returns mOxie.File - unified wrapper object that can be used across runtimes.
2164
+ *
2165
+ * @method getSource
2166
+ * @return {mOxie.File} or null
2167
+ */
2168
+ getSource: function() {
2169
+ if (!filepool[this.id]) {
2170
+ return null;
2171
+ }
2172
+ return filepool[this.id];
2173
+ },
2174
+
2175
+ /**
2176
+ * Destroys plupload.File object.
2177
+ *
2178
+ * @method destroy
2179
+ */
2180
+ destroy: function() {
2181
+ var src = this.getSource();
2182
+ if (src) {
2183
+ src.destroy();
2184
+ delete filepool[this.id];
2185
+ }
2186
+ }
2187
+ });
2188
+
2189
+ filepool[this.id] = file;
2190
+ }
2191
+
2192
+ return PluploadFile;
2193
+ }());
2194
+
2195
+
2196
+ /**
2197
+ * Constructs a queue progress.
2198
+ *
2199
+ * @class QueueProgress
2200
+ * @constructor
2201
+ */
2202
+ plupload.QueueProgress = function() {
2203
+ var self = this; // Setup alias for self to reduce code size when it's compressed
2204
+
2205
+ /**
2206
+ * Total queue file size.
2207
+ *
2208
+ * @property size
2209
+ * @type Number
2210
+ */
2211
+ self.size = 0;
2212
+
2213
+ /**
2214
+ * Total bytes uploaded.
2215
+ *
2216
+ * @property loaded
2217
+ * @type Number
2218
+ */
2219
+ self.loaded = 0;
2220
+
2221
+ /**
2222
+ * Number of files uploaded.
2223
+ *
2224
+ * @property uploaded
2225
+ * @type Number
2226
+ */
2227
+ self.uploaded = 0;
2228
+
2229
+ /**
2230
+ * Number of files failed to upload.
2231
+ *
2232
+ * @property failed
2233
+ * @type Number
2234
+ */
2235
+ self.failed = 0;
2236
+
2237
+ /**
2238
+ * Number of files yet to be uploaded.
2239
+ *
2240
+ * @property queued
2241
+ * @type Number
2242
+ */
2243
+ self.queued = 0;
2244
+
2245
+ /**
2246
+ * Total percent of the uploaded bytes.
2247
+ *
2248
+ * @property percent
2249
+ * @type Number
2250
+ */
2251
+ self.percent = 0;
2252
+
2253
+ /**
2254
+ * Bytes uploaded per second.
2255
+ *
2256
+ * @property bytesPerSec
2257
+ * @type Number
2258
+ */
2259
+ self.bytesPerSec = 0;
2260
+
2261
+ /**
2262
+ * Resets the progress to it's initial values.
2263
+ *
2264
+ * @method reset
2265
+ */
2266
+ self.reset = function() {
2267
+ self.size = self.loaded = self.uploaded = self.failed = self.queued = self.percent = self.bytesPerSec = 0;
2268
+ };
2269
+ };
2270
+
2271
+ window.plupload = plupload;
2272
+
2273
+ }(window, mOxie));
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/plupload.full.min.js ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * mOxie - multi-runtime File API & XMLHttpRequest L2 Polyfill
3
+ * v1.2.0
4
+ *
5
+ * Copyright 2013, Moxiecode Systems AB
6
+ * Released under GPL License.
7
+ *
8
+ * License: http://www.plupload.com/license
9
+ * Contributing: http://www.plupload.com/contributing
10
+ *
11
+ * Date: 2014-01-16
12
+ */
13
+ !function(e,t){"use strict";function n(e,t){for(var n,i=[],r=0;r<e.length;++r){if(n=s[e[r]]||o(e[r]),!n)throw"module definition dependecy not found: "+e[r];i.push(n)}t.apply(null,i)}function i(e,i,r){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(i===t)throw"invalid module definition, dependencies must be specified";if(r===t)throw"invalid module definition, definition function must be specified";n(i,function(){s[e]=r.apply(null,arguments)})}function r(e){return!!s[e]}function o(t){for(var n=e,i=t.split(/[.\/]/),r=0;r<i.length;++r){if(!n[i[r]])return;n=n[i[r]]}return n}function a(n){for(var i=0;i<n.length;i++){for(var r=e,o=n[i],a=o.split(/[.\/]/),u=0;u<a.length-1;++u)r[a[u]]===t&&(r[a[u]]={}),r=r[a[u]];r[a[a.length-1]]=s[o]}}var s={},u="moxie/core/utils/Basic",c="moxie/core/I18n",l="moxie/core/utils/Mime",d="moxie/core/utils/Env",f="moxie/core/utils/Dom",p="moxie/core/Exceptions",h="moxie/core/EventTarget",m="moxie/core/utils/Encode",g="moxie/runtime/Runtime",v="moxie/runtime/RuntimeClient",y="moxie/file/Blob",w="moxie/file/File",E="moxie/file/FileInput",_="moxie/file/FileDrop",x="moxie/runtime/RuntimeTarget",R="moxie/file/FileReader",b="moxie/core/utils/Url",T="moxie/file/FileReaderSync",S="moxie/xhr/FormData",A="moxie/xhr/XMLHttpRequest",O="moxie/runtime/Transporter",I="moxie/image/Image",D="moxie/runtime/html5/Runtime",N="moxie/runtime/html5/file/Blob",L="moxie/core/utils/Events",M="moxie/runtime/html5/file/FileInput",C="moxie/runtime/html5/file/FileDrop",F="moxie/runtime/html5/file/FileReader",H="moxie/runtime/html5/xhr/XMLHttpRequest",P="moxie/runtime/html5/utils/BinaryReader",k="moxie/runtime/html5/image/JPEGHeaders",U="moxie/runtime/html5/image/ExifParser",B="moxie/runtime/html5/image/JPEG",z="moxie/runtime/html5/image/PNG",G="moxie/runtime/html5/image/ImageInfo",q="moxie/runtime/html5/image/MegaPixel",X="moxie/runtime/html5/image/Image",j="moxie/runtime/flash/Runtime",V="moxie/runtime/flash/file/Blob",W="moxie/runtime/flash/file/FileInput",Y="moxie/runtime/flash/file/FileReader",$="moxie/runtime/flash/file/FileReaderSync",J="moxie/runtime/flash/xhr/XMLHttpRequest",Z="moxie/runtime/flash/runtime/Transporter",K="moxie/runtime/flash/image/Image",Q="moxie/runtime/silverlight/Runtime",et="moxie/runtime/silverlight/file/Blob",tt="moxie/runtime/silverlight/file/FileInput",nt="moxie/runtime/silverlight/file/FileDrop",it="moxie/runtime/silverlight/file/FileReader",rt="moxie/runtime/silverlight/file/FileReaderSync",ot="moxie/runtime/silverlight/xhr/XMLHttpRequest",at="moxie/runtime/silverlight/runtime/Transporter",st="moxie/runtime/silverlight/image/Image",ut="moxie/runtime/html4/Runtime",ct="moxie/runtime/html4/file/FileInput",lt="moxie/runtime/html4/file/FileReader",dt="moxie/runtime/html4/xhr/XMLHttpRequest",ft="moxie/runtime/html4/image/Image";i(u,[],function(){var e=function(e){var t;return e===t?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()},t=function(i){var r;return n(arguments,function(o,s){s>0&&n(o,function(n,o){n!==r&&(e(i[o])===e(n)&&~a(e(n),["array","object"])?t(i[o],n):i[o]=n)})}),i},n=function(e,t){var n,i,r,o;if(e){try{n=e.length}catch(a){n=o}if(n===o){for(i in e)if(e.hasOwnProperty(i)&&t(e[i],i)===!1)return}else for(r=0;n>r;r++)if(t(e[r],r)===!1)return}},i=function(t){var n;if(!t||"object"!==e(t))return!0;for(n in t)return!1;return!0},r=function(t,n){function i(r){"function"===e(t[r])&&t[r](function(e){++r<o&&!e?i(r):n(e)})}var r=0,o=t.length;"function"!==e(n)&&(n=function(){}),t&&t.length||n(),i(r)},o=function(e,t){var i=0,r=e.length,o=new Array(r);n(e,function(e,n){e(function(e){if(e)return t(e);var a=[].slice.call(arguments);a.shift(),o[n]=a,i++,i===r&&(o.unshift(null),t.apply(this,o))})})},a=function(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var n=0,i=t.length;i>n;n++)if(t[n]===e)return n}return-1},s=function(t,n){var i=[];"array"!==e(t)&&(t=[t]),"array"!==e(n)&&(n=[n]);for(var r in t)-1===a(t[r],n)&&i.push(t[r]);return i.length?i:!1},u=function(e,t){var i=[];return n(e,function(e){-1!==a(e,t)&&i.push(e)}),i.length?i:null},c=function(e){var t,n=[];for(t=0;t<e.length;t++)n[t]=e[t];return n},l=function(){var e=0;return function(t){var n=(new Date).getTime().toString(32),i;for(i=0;5>i;i++)n+=Math.floor(65535*Math.random()).toString(32);return(t||"o_")+n+(e++).toString(32)}}(),d=function(e){return e?String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""):e},f=function(e){if("string"!=typeof e)return e;var t={t:1099511627776,g:1073741824,m:1048576,k:1024},n;return e=/^([0-9]+)([mgk]?)$/.exec(e.toLowerCase().replace(/[^0-9mkg]/g,"")),n=e[2],e=+e[1],t.hasOwnProperty(n)&&(e*=t[n]),e};return{guid:l,typeOf:e,extend:t,each:n,isEmptyObj:i,inSeries:r,inParallel:o,inArray:a,arrayDiff:s,arrayIntersect:u,toArray:c,trim:d,parseSizeStr:f}}),i(c,[u],function(e){var t={};return{addI18n:function(n){return e.extend(t,n)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(t){var n=[].slice.call(arguments,1);return t.replace(/%[a-z]/g,function(){var t=n.shift();return"undefined"!==e.typeOf(t)?t:""})}}}),i(l,[u,c],function(e,t){var n="application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe",i={mimes:{},extensions:{},addMimeType:function(e){var t=e.split(/,/),n,i,r;for(n=0;n<t.length;n+=2){for(r=t[n+1].split(/ /),i=0;i<r.length;i++)this.mimes[r[i]]=t[n];this.extensions[t[n]]=r}},extList2mimes:function(t,n){var i=this,r,o,a,s,u=[];for(o=0;o<t.length;o++)for(r=t[o].extensions.split(/\s*,\s*/),a=0;a<r.length;a++){if("*"===r[a])return[];if(s=i.mimes[r[a]])-1===e.inArray(s,u)&&u.push(s);else{if(!n||!/^\w+$/.test(r[a]))return[];u.push("."+r[a])}}return u},mimes2exts:function(t){var n=this,i=[];return e.each(t,function(t){if("*"===t)return i=[],!1;var r=t.match(/^(\w+)\/(\*|\w+)$/);r&&("*"===r[2]?e.each(n.extensions,function(e,t){new RegExp("^"+r[1]+"/").test(t)&&[].push.apply(i,n.extensions[t])}):n.extensions[t]&&[].push.apply(i,n.extensions[t]))}),i},mimes2extList:function(n){var i=[],r=[];return"string"===e.typeOf(n)&&(n=e.trim(n).split(/\s*,\s*/)),r=this.mimes2exts(n),i.push({title:t.translate("Files"),extensions:r.length?r.join(","):"*"}),i.mimes=n,i},getFileExtension:function(e){var t=e&&e.match(/\.([^.]+)$/);return t?t[1].toLowerCase():""},getFileMime:function(e){return this.mimes[this.getFileExtension(e)]||""}};return i.addMimeType(n),i}),i(d,[u],function(e){function t(e,t,n){var i=0,r=0,o=0,a={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1},s=function(e){return e=(""+e).replace(/[_\-+]/g,"."),e=e.replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,"."),e.length?e.split("."):[-8]},u=function(e){return e?isNaN(e)?a[e]||-7:parseInt(e,10):0};for(e=s(e),t=s(t),r=Math.max(e.length,t.length),i=0;r>i;i++)if(e[i]!=t[i]){if(e[i]=u(e[i]),t[i]=u(t[i]),e[i]<t[i]){o=-1;break}if(e[i]>t[i]){o=1;break}}if(!n)return o;switch(n){case">":case"gt":return o>0;case">=":case"ge":return o>=0;case"<=":case"le":return 0>=o;case"==":case"=":case"eq":return 0===o;case"<>":case"!=":case"ne":return 0!==o;case"":case"<":case"lt":return 0>o;default:return null}}var n=function(e){var t="",n="?",i="function",r="undefined",o="object",a="major",s="model",u="name",c="type",l="vendor",d="version",f="architecture",p="console",h="mobile",m="tablet",g={has:function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},lowerize:function(e){return e.toLowerCase()}},v={rgx:function(){for(var t,n=0,a,s,u,c,l,d,f=arguments;n<f.length;n+=2){var p=f[n],h=f[n+1];if(typeof t===r){t={};for(u in h)c=h[u],typeof c===o?t[c[0]]=e:t[c]=e}for(a=s=0;a<p.length;a++)if(l=p[a].exec(this.getUA())){for(u=0;u<h.length;u++)d=l[++s],c=h[u],typeof c===o&&c.length>0?2==c.length?t[c[0]]=typeof c[1]==i?c[1].call(this,d):c[1]:3==c.length?t[c[0]]=typeof c[1]!==i||c[1].exec&&c[1].test?d?d.replace(c[1],c[2]):e:d?c[1].call(this,d,c[2]):e:4==c.length&&(t[c[0]]=d?c[3].call(this,d.replace(c[1],c[2])):e):t[c]=d?d:e;break}if(l)break}return t},str:function(t,i){for(var r in i)if(typeof i[r]===o&&i[r].length>0){for(var a=0;a<i[r].length;a++)if(g.has(i[r][a],t))return r===n?e:r}else if(g.has(i[r],t))return r===n?e:r;return t}},y={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2000:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}},w={browser:[[/(opera\smini)\/((\d+)?[\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/((\d+)?[\w\.-]+)/i,/(opera).+version\/((\d+)?[\w\.]+)/i,/(opera)[\/\s]+((\d+)?[\w\.]+)/i],[u,d,a],[/\s(opr)\/((\d+)?[\w\.]+)/i],[[u,"Opera"],d,a],[/(kindle)\/((\d+)?[\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?((\d+)?[\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?((\d+)?[\w\.]*)/i,/(?:ms|\()(ie)\s((\d+)?[\w\.]+)/i,/(rekonq)((?:\/)[\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron)\/((\d+)?[\w\.-]+)/i],[u,d,a],[/(trident).+rv[:\s]((\d+)?[\w\.]+).+like\sgecko/i],[[u,"IE"],d,a],[/(yabrowser)\/((\d+)?[\w\.]+)/i],[[u,"Yandex"],d,a],[/(comodo_dragon)\/((\d+)?[\w\.]+)/i],[[u,/_/g," "],d,a],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?((\d+)?[\w\.]+)/i],[u,d,a],[/(dolfin)\/((\d+)?[\w\.]+)/i],[[u,"Dolphin"],d,a],[/((?:android.+)crmo|crios)\/((\d+)?[\w\.]+)/i],[[u,"Chrome"],d,a],[/((?:android.+))version\/((\d+)?[\w\.]+)\smobile\ssafari/i],[[u,"Android Browser"],d,a],[/version\/((\d+)?[\w\.]+).+?mobile\/\w+\s(safari)/i],[d,a,[u,"Mobile Safari"]],[/version\/((\d+)?[\w\.]+).+?(mobile\s?safari|safari)/i],[d,a,u],[/webkit.+?(mobile\s?safari|safari)((\/[\w\.]+))/i],[u,[a,v.str,y.browser.oldsafari.major],[d,v.str,y.browser.oldsafari.version]],[/(konqueror)\/((\d+)?[\w\.]+)/i,/(webkit|khtml)\/((\d+)?[\w\.]+)/i],[u,d,a],[/(navigator|netscape)\/((\d+)?[\w\.-]+)/i],[[u,"Netscape"],d,a],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?((\d+)?[\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/((\d+)?[\w\.-]+)/i,/(mozilla)\/((\d+)?[\w\.]+).+rv\:.+gecko\/\d+/i,/(uc\s?browser|polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|qqbrowser)[\/\s]?((\d+)?[\w\.]+)/i,/(links)\s\(((\d+)?[\w\.]+)/i,/(gobrowser)\/?((\d+)?[\w\.]+)*/i,/(ice\s?browser)\/v?((\d+)?[\w\._]+)/i,/(mosaic)[\/\s]((\d+)?[\w\.]+)/i],[u,d,a]],engine:[[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[u,d],[/rv\:([\w\.]+).*(gecko)/i],[d,u]],os:[[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[u,[d,v.str,y.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[u,"Windows"],[d,v.str,y.os.windows.version]],[/\((bb)(10);/i],[[u,"BlackBerry"],d],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)\/([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego)[\/\s-]?([\w\.]+)*/i],[u,d],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[u,"Symbian"],d],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[u,"Firefox OS"],d],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[u,d],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[u,"Chromium OS"],d],[/(sunos)\s?([\w\.]+\d)*/i],[[u,"Solaris"],d],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[u,d],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[u,"iOS"],[d,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i],[u,[d,/_/g,"."]],[/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(macintosh|mac(?=_powerpc)|plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos)/i,/(unix)\s?([\w\.]+)*/i],[u,d]]},E=function(e){var n=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:t);this.getBrowser=function(){return v.rgx.apply(this,w.browser)},this.getEngine=function(){return v.rgx.apply(this,w.engine)},this.getOS=function(){return v.rgx.apply(this,w.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return n},this.setUA=function(e){return n=e,this},this.setUA(n)};return(new E).getResult()}(),i=function(){var t={define_property:function(){return!1}(),create_canvas:function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))}(),return_response_type:function(t){try{if(-1!==e.inArray(t,["","text","document"]))return!0;if(window.XMLHttpRequest){var n=new XMLHttpRequest;if(n.open("get","/"),"responseType"in n)return n.responseType=t,n.responseType!==t?!1:!0}}catch(i){}return!1},use_data_uri:function(){var e=new Image;return e.onload=function(){t.use_data_uri=1===e.width&&1===e.height},setTimeout(function(){e.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1}(),use_data_uri_over32kb:function(){return t.use_data_uri&&("IE"!==r.browser||r.version>=9)},use_data_uri_of:function(e){return t.use_data_uri&&33e3>e||t.use_data_uri_over32kb()},use_fileinput:function(){var e=document.createElement("input");return e.setAttribute("type","file"),!e.disabled}};return function(n){var i=[].slice.call(arguments);return i.shift(),"function"===e.typeOf(t[n])?t[n].apply(this,i):!!t[n]}}(),r={can:i,browser:n.browser.name,version:parseFloat(n.browser.major),os:n.os.name,osVersion:n.os.version,verComp:t,swf_url:"../flash/Moxie.swf",xap_url:"../silverlight/Moxie.xap",global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return r.OS=r.os,r}),i(f,[d],function(e){var t=function(e){return"string"!=typeof e?e:document.getElementById(e)},n=function(e,t){if(!e.className)return!1;var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");return n.test(e.className)},i=function(e,t){n(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},r=function(e,t){if(e.className){var n=new RegExp("(^|\\s+)"+t+"(\\s+|$)");e.className=e.className.replace(n,function(e,t,n){return" "===t&&" "===n?" ":""})}},o=function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},a=function(t,n){function i(e){var t,n,i=0,r=0;return e&&(n=e.getBoundingClientRect(),t="CSS1Compat"===s.compatMode?s.documentElement:s.body,i=n.left+t.scrollLeft,r=n.top+t.scrollTop),{x:i,y:r}}var r=0,o=0,a,s=document,u,c;if(t=t,n=n||s.body,t&&t.getBoundingClientRect&&"IE"===e.browser&&(!s.documentMode||s.documentMode<8))return u=i(t),c=i(n),{x:u.x-c.x,y:u.y-c.y};for(a=t;a&&a!=n&&a.nodeType;)r+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=t.parentNode;a&&a!=n&&a.nodeType;)r-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode;return{x:r,y:o}},s=function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}};return{get:t,hasClass:n,addClass:i,removeClass:r,getStyle:o,getPos:a,getSize:s}}),i(p,[u],function(e){function t(e,t){var n;for(n in e)if(e[n]===t)return n;return null}return{RuntimeError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": RuntimeError "+this.code}var i={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4};return e.extend(n,i),n.prototype=Error.prototype,n}(),OperationNotAllowedException:function(){function t(e){this.code=e,this.name="OperationNotAllowedException"}return e.extend(t,{NOT_ALLOWED_ERR:1}),t.prototype=Error.prototype,t}(),ImageError:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": ImageError "+this.code}var i={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2};return e.extend(n,i),n.prototype=Error.prototype,n}(),FileException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": FileException "+this.code}var i={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8};return e.extend(n,i),n.prototype=Error.prototype,n}(),DOMException:function(){function n(e){this.code=e,this.name=t(i,e),this.message=this.name+": DOMException "+this.code}var i={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25};return e.extend(n,i),n.prototype=Error.prototype,n}(),EventException:function(){function t(e){this.code=e,this.name="EventException"}return e.extend(t,{UNSPECIFIED_EVENT_TYPE_ERR:0}),t.prototype=Error.prototype,t}()}}),i(h,[p,u],function(e,t){function n(){var n={};t.extend(this,{uid:null,init:function(){this.uid||(this.uid=t.guid("uid_"))},addEventListener:function(e,i,r,o){var a=this,s;return e=t.trim(e),/\s/.test(e)?(t.each(e.split(/\s+/),function(e){a.addEventListener(e,i,r,o)}),void 0):(e=e.toLowerCase(),r=parseInt(r,10)||0,s=n[this.uid]&&n[this.uid][e]||[],s.push({fn:i,priority:r,scope:o||this}),n[this.uid]||(n[this.uid]={}),n[this.uid][e]=s,void 0)},hasEventListener:function(e){return e?!(!n[this.uid]||!n[this.uid][e]):!!n[this.uid]},removeEventListener:function(e,i){e=e.toLowerCase();var r=n[this.uid]&&n[this.uid][e],o;if(r){if(i){for(o=r.length-1;o>=0;o--)if(r[o].fn===i){r.splice(o,1);break}}else r=[];r.length||(delete n[this.uid][e],t.isEmptyObj(n[this.uid])&&delete n[this.uid])}},removeAllEventListeners:function(){n[this.uid]&&delete n[this.uid]},dispatchEvent:function(i){var r,o,a,s,u={},c=!0,l;if("string"!==t.typeOf(i)){if(s=i,"string"!==t.typeOf(s.type))throw new e.EventException(e.EventException.UNSPECIFIED_EVENT_TYPE_ERR);i=s.type,s.total!==l&&s.loaded!==l&&(u.total=s.total,u.loaded=s.loaded),u.async=s.async||!1}if(-1!==i.indexOf("::")?function(e){r=e[0],i=e[1]}(i.split("::")):r=this.uid,i=i.toLowerCase(),o=n[r]&&n[r][i]){o.sort(function(e,t){return t.priority-e.priority}),a=[].slice.call(arguments),a.shift(),u.type=i,a.unshift(u);var d=[];t.each(o,function(e){a[0].target=e.scope,u.async?d.push(function(t){setTimeout(function(){t(e.fn.apply(e.scope,a)===!1)},1)}):d.push(function(t){t(e.fn.apply(e.scope,a)===!1)})}),d.length&&t.inSeries(d,function(e){c=!e})}return c},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},convertEventPropsToHandlers:function(e){var n;"array"!==t.typeOf(e)&&(e=[e]);for(var i=0;i<e.length;i++)n="on"+e[i],"function"===t.typeOf(this[n])?this.addEventListener(e[i],this[n]):"undefined"===t.typeOf(this[n])&&(this[n]=null)}})}return n.instance=new n,n}),i(m,[],function(){var e=function(e){return unescape(encodeURIComponent(e))},t=function(e){return decodeURIComponent(escape(e))},n=function(e,n){if("function"==typeof window.atob)return n?t(window.atob(e)):window.atob(e);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,p=0,h="",m=[];if(!e)return e;e+="";do s=i.indexOf(e.charAt(f++)),u=i.indexOf(e.charAt(f++)),c=i.indexOf(e.charAt(f++)),l=i.indexOf(e.charAt(f++)),d=s<<18|u<<12|c<<6|l,r=255&d>>16,o=255&d>>8,a=255&d,m[p++]=64==c?String.fromCharCode(r):64==l?String.fromCharCode(r,o):String.fromCharCode(r,o,a);while(f<e.length);return h=m.join(""),n?t(h):h},i=function(t,n){if(n&&e(t),"function"==typeof window.btoa)return window.btoa(t);var i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",r,o,a,s,u,c,l,d,f=0,p=0,h="",m=[];if(!t)return t;do r=t.charCodeAt(f++),o=t.charCodeAt(f++),a=t.charCodeAt(f++),d=r<<16|o<<8|a,s=63&d>>18,u=63&d>>12,c=63&d>>6,l=63&d,m[p++]=i.charAt(s)+i.charAt(u)+i.charAt(c)+i.charAt(l);while(f<t.length);h=m.join("");var g=t.length%3;return(g?h.slice(0,g-3):h)+"===".slice(g||3)};return{utf8_encode:e,utf8_decode:t,atob:n,btoa:i}}),i(g,[u,f,h],function(e,t,n){function i(n,r,a,s,u){var c=this,l,d=e.guid(r+"_"),f=u||"browser";n=n||{},o[d]=this,a=e.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},a),n.preferred_caps&&(f=i.getMode(s,n.preferred_caps,f)),l=function(){var t={};return{exec:function(e,n,i,r){return l[n]&&(t[e]||(t[e]={context:this,instance:new l[n]}),t[e].instance[i])?t[e].instance[i].apply(this,r):void 0},removeInstance:function(e){delete t[e]},removeAllInstances:function(){var n=this;e.each(t,function(t,i){"function"===e.typeOf(t.instance.destroy)&&t.instance.destroy.call(t.context),n.removeInstance(i)})}}}(),e.extend(this,{initialized:!1,uid:d,type:r,mode:i.getMode(s,n.required_caps,f),shimid:d+"_container",clients:0,options:n,can:function(t,n){var r=arguments[2]||a;if("string"===e.typeOf(t)&&"undefined"===e.typeOf(n)&&(t=i.parseCaps(t)),"object"===e.typeOf(t)){for(var o in t)if(!this.can(o,t[o],r))return!1;return!0}return"function"===e.typeOf(r[t])?r[t].call(this,n):n===r[t]},getShimContainer:function(){var n,i=t.get(this.shimid);return i||(n=this.options.container?t.get(this.options.container):document.body,i=document.createElement("div"),i.id=this.shimid,i.className="moxie-shim moxie-shim-"+this.type,e.extend(i.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),n.appendChild(i),n=null),i},getShim:function(){return l},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec.call(this,this.uid,e,t,n)},exec:function(e,t){var n=[].slice.call(arguments,2);return c[e]&&c[e][t]?c[e][t].apply(this,n):c.shimExec.apply(this,arguments)},destroy:function(){if(c){var e=t.get(this.shimid);e&&e.parentNode.removeChild(e),l&&l.removeAllInstances(),this.unbindAll(),delete o[this.uid],this.uid=null,d=c=l=e=null}}}),this.mode&&n.required_caps&&!this.can(n.required_caps)&&(this.mode=!1)}var r={},o={};return i.order="html5,flash,silverlight,html4",i.getRuntime=function(e){return o[e]?o[e]:!1},i.addConstructor=function(e,t){t.prototype=n.instance,r[e]=t},i.getConstructor=function(e){return r[e]||null},i.getInfo=function(e){var t=i.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},i.parseCaps=function(t){var n={};return"string"!==e.typeOf(t)?t||{}:(e.each(t.split(","),function(e){n[e]=!0}),n)},i.can=function(e,t){var n,r=i.getConstructor(e),o;return r?(n=new r({required_caps:t}),o=n.mode,n.destroy(),!!o):!1},i.thatCan=function(e,t){var n=(t||i.order).split(/\s*,\s*/);for(var r in n)if(i.can(n[r],e))return n[r];return null},i.getMode=function(t,n,i){var r=null;if("undefined"===e.typeOf(i)&&(i="browser"),n&&!e.isEmptyObj(t)){if(e.each(n,function(n,i){if(t.hasOwnProperty(i)){var o=t[i](n);if("string"==typeof o&&(o=[o]),r){if(!(r=e.arrayIntersect(r,o)))return r=!1}else r=o}}),r)return-1!==e.inArray(i,r)?i:r[0];if(r===!1)return!1}return i},i.capTrue=function(){return!0},i.capFalse=function(){return!1},i.capTest=function(e){return function(){return!!e}},i}),i(v,[p,u,g],function(e,t,n){return function i(){var i;t.extend(this,{connectRuntime:function(r){function o(t){var s,u;return t.length?(s=t.shift(),(u=n.getConstructor(s))?(i=new u(r),i.bind("Init",function(){i.initialized=!0,setTimeout(function(){i.clients++,a.trigger("RuntimeInit",i)},1)}),i.bind("Error",function(){i.destroy(),o(t)}),i.mode?(i.init(),void 0):(i.trigger("Error"),void 0)):(o(t),void 0)):(a.trigger("RuntimeError",new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)),i=null,void 0)}var a=this,s;if("string"===t.typeOf(r)?s=r:"string"===t.typeOf(r.ruid)&&(s=r.ruid),s){if(i=n.getRuntime(s))return i.clients++,i;throw new e.RuntimeError(e.RuntimeError.NOT_INIT_ERR)}o((r.runtime_order||n.order).split(/\s*,\s*/))},getRuntime:function(){return i&&i.uid?i:(i=null,null)},disconnectRuntime:function(){i&&--i.clients<=0&&(i.destroy(),i=null)}})}}),i(y,[u,m,v],function(e,t,n){function i(o,a){function s(t,n,o){var a,s=r[this.uid];return"string"===e.typeOf(s)&&s.length?(a=new i(null,{type:o,size:n-t}),a.detach(s.substr(t,a.size)),a):null}n.call(this),o&&this.connectRuntime(o),a?"string"===e.typeOf(a)&&(a={data:a}):a={},e.extend(this,{uid:a.uid||e.guid("uid_"),ruid:o,size:a.size||0,type:a.type||"",slice:function(e,t,n){return this.isDetached()?s.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,n)},getSource:function(){return r[this.uid]?r[this.uid]:null},detach:function(e){this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy",r[this.uid]),this.disconnectRuntime(),this.ruid=null),e=e||"";var n=e.match(/^data:([^;]*);base64,/);n&&(this.type=n[1],e=t.atob(e.substring(e.indexOf("base64,")+7))),this.size=e.length,r[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===e.typeOf(r[this.uid])},destroy:function(){this.detach(),delete r[this.uid]}}),a.data?this.detach(a.data):r[this.uid]=a}var r={};return i}),i(w,[u,l,y],function(e,t,n){function i(i,r){var o,a;if(r||(r={}),a=r.type&&""!==r.type?r.type:t.getFileMime(r.name),r.name)o=r.name.replace(/\\/g,"/"),o=o.substr(o.lastIndexOf("/")+1);else{var s=a.split("/")[0];o=e.guid((""!==s?s:"file")+"_"),t.extensions[a]&&(o+="."+t.extensions[a][0])}n.apply(this,arguments),e.extend(this,{type:a||"",name:o||e.guid("file_"),lastModifiedDate:r.lastModifiedDate||(new Date).toLocaleString()})}return i.prototype=n.prototype,i}),i(E,[u,l,f,p,h,c,w,g,v],function(e,t,n,i,r,o,a,s,u){function c(r){var c=this,d,f,p;if(-1!==e.inArray(e.typeOf(r),["string","node"])&&(r={browse_button:r}),f=n.get(r.browse_button),!f)throw new i.DOMException(i.DOMException.NOT_FOUND_ERR);p={accept:[{title:o.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:f.parentNode||document.body},r=e.extend({},p,r),"string"==typeof r.required_caps&&(r.required_caps=s.parseCaps(r.required_caps)),"string"==typeof r.accept&&(r.accept=t.mimes2extList(r.accept)),d=n.get(r.container),d||(d=document.body),"static"===n.getStyle(d,"position")&&(d.style.position="relative"),d=f=null,u.call(c),e.extend(c,{uid:e.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){c.convertEventPropsToHandlers(l),c.bind("RuntimeInit",function(t,i){c.ruid=i.uid,c.shimid=i.shimid,c.bind("Ready",function(){c.trigger("Refresh")},999),c.bind("Change",function(){var t=i.exec.call(c,"FileInput","getFiles");c.files=[],e.each(t,function(e){return 0===e.size?!0:(c.files.push(new a(c.ruid,e)),void 0)})},999),c.bind("Refresh",function(){var t,o,a,s;a=n.get(r.browse_button),s=n.get(i.shimid),a&&(t=n.getPos(a,n.get(r.container)),o=n.getSize(a),s&&e.extend(s.style,{top:t.y+"px",left:t.x+"px",width:o.w+"px",height:o.h+"px"})),s=a=null}),i.exec.call(c,"FileInput","init",r)}),c.connectRuntime(e.extend({},r,{required_caps:{select_file:!0}}))},disable:function(t){var n=this.getRuntime();n&&n.exec.call(this,"FileInput","disable","undefined"===e.typeOf(t)?!0:t)},refresh:function(){c.trigger("Refresh")},destroy:function(){var t=this.getRuntime();t&&(t.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===e.typeOf(this.files)&&e.each(this.files,function(e){e.destroy()}),this.files=null}})}var l=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];return c.prototype=r.instance,c}),i(_,[c,f,p,u,w,v,h,l],function(e,t,n,i,r,o,a,s){function u(n){var a=this,u;"string"==typeof n&&(n={drop_zone:n}),u={accept:[{title:e.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},n="object"==typeof n?i.extend({},u,n):u,n.container=t.get(n.drop_zone)||document.body,"static"===t.getStyle(n.container,"position")&&(n.container.style.position="relative"),"string"==typeof n.accept&&(n.accept=s.mimes2extList(n.accept)),o.call(a),i.extend(a,{uid:i.guid("uid_"),ruid:null,files:null,init:function(){a.convertEventPropsToHandlers(c),a.bind("RuntimeInit",function(e,t){a.ruid=t.uid,a.bind("Drop",function(){var e=t.exec.call(a,"FileDrop","getFiles");a.files=[],i.each(e,function(e){a.files.push(new r(a.ruid,e))})},999),t.exec.call(a,"FileDrop","init",n),a.dispatchEvent("ready")}),a.connectRuntime(n)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null}})}var c=["ready","dragenter","dragleave","drop","error"];return u.prototype=a.instance,u}),i(x,[u,v,h],function(e,t,n){function i(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return i.prototype=n.instance,i}),i(R,[u,m,p,h,y,w,x],function(e,t,n,i,r,o,a){function s(){function i(e,i){function l(e){o.readyState=s.DONE,o.error=e,o.trigger("error"),d()}function d(){c.destroy(),c=null,o.trigger("loadend")}function f(t){c.bind("Error",function(e,t){l(t)}),c.bind("Progress",function(e){o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e)}),c.bind("Load",function(e){o.readyState=s.DONE,o.result=t.exec.call(c,"FileReader","getResult"),o.trigger(e),d()}),t.exec.call(c,"FileReader","read",e,i)}if(c=new a,this.convertEventPropsToHandlers(u),this.readyState===s.LOADING)return l(new n.DOMException(n.DOMException.INVALID_STATE_ERR));if(this.readyState=s.LOADING,this.trigger("loadstart"),i instanceof r)if(i.isDetached()){var p=i.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=p;break;case"readAsDataURL":this.result="data:"+i.type+";base64,"+t.btoa(p)}this.readyState=s.DONE,this.trigger("load"),d()}else f(c.connectRuntime(i.ruid));else l(new n.DOMException(n.DOMException.NOT_FOUND_ERR))}var o=this,c;e.extend(this,{uid:e.guid("uid_"),readyState:s.EMPTY,result:null,error:null,readAsBinaryString:function(e){i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){i.call(this,"readAsDataURL",e)},readAsText:function(e){i.call(this,"readAsText",e)
14
+ },abort:function(){this.result=null,-1===e.inArray(this.readyState,[s.EMPTY,s.DONE])&&(this.readyState===s.LOADING&&(this.readyState=s.DONE),c&&c.getRuntime().exec.call(this,"FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))},destroy:function(){this.abort(),c&&(c.getRuntime().exec.call(this,"FileReader","destroy"),c.disconnectRuntime()),o=c=null}})}var u=["loadstart","progress","load","abort","error","loadend"];return s.EMPTY=0,s.LOADING=1,s.DONE=2,s.prototype=i.instance,s}),i(b,[],function(){var e=function(t,n){for(var i=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],r=i.length,o={http:80,https:443},a={},s=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,u=s.exec(t||"");r--;)u[r]&&(a[i[r]]=u[r]);if(!a.scheme){n&&"string"!=typeof n||(n=e(n||document.location.href)),a.scheme=n.scheme,a.host=n.host,a.port=n.port;var c="";/^[^\/]/.test(a.path)&&(c=n.path,/(\/|\/[^\.]+)$/.test(c)?c+="/":c=c.replace(/\/[^\/]+$/,"/")),a.path=c+(a.path||"")}return a.port||(a.port=o[a.scheme]||80),a.port=parseInt(a.port,10),a.path||(a.path="/"),delete a.source,a},t=function(t){var n={http:80,https:443},i=e(t);return i.scheme+"://"+i.host+(i.port!==n[i.scheme]?":"+i.port:"")+i.path+(i.query?i.query:"")},n=function(t){function n(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof t&&(t=e(t)),n(e())===n(t)};return{parseUrl:e,resolveUrl:t,hasSameOrigin:n}}),i(T,[u,v,m],function(e,t,n){return function(){function i(e,t){if(!t.isDetached()){var i=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t);return this.disconnectRuntime(),i}var r=t.getSource();switch(e){case"readAsBinaryString":return r;case"readAsDataURL":return"data:"+t.type+";base64,"+n.btoa(r);case"readAsText":for(var o="",a=0,s=r.length;s>a;a++)o+=String.fromCharCode(r[a]);return o}}t.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return i.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return i.call(this,"readAsDataURL",e)},readAsText:function(e){return i.call(this,"readAsText",e)}})}}),i(S,[p,u,y],function(e,t,n){function i(){var e,i=[];t.extend(this,{append:function(r,o){var a=this,s=t.typeOf(o);o instanceof n?e={name:r,value:o}:"array"===s?(r+="[]",t.each(o,function(e){a.append(r,e)})):"object"===s?t.each(o,function(e,t){a.append(r+"["+t+"]",e)}):"null"===s||"undefined"===s||"number"===s&&isNaN(o)?a.append(r,"false"):i.push({name:r,value:o.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return e&&e.value||null},getBlobName:function(){return e&&e.name||null},each:function(n){t.each(i,function(e){n(e.value,e.name)}),e&&n(e.value,e.name)},destroy:function(){e=null,i=[]}})}return i}),i(A,[u,p,h,m,b,g,x,y,T,S,d,l],function(e,t,n,i,r,o,a,s,u,c,l,d){function f(){this.uid=e.guid("uid_")}function p(){function n(e,t){return y.hasOwnProperty(e)?1===arguments.length?l.can("define_property")?y[e]:v[e]:(l.can("define_property")?y[e]=t:v[e]=t,void 0):void 0}function u(t){function i(){k.destroy(),k=null,s.dispatchEvent("loadend"),s=null}function r(r){k.bind("LoadStart",function(e){n("readyState",p.LOADING),s.dispatchEvent("readystatechange"),s.dispatchEvent(e),I&&s.upload.dispatchEvent(e)}),k.bind("Progress",function(e){n("readyState")!==p.LOADING&&(n("readyState",p.LOADING),s.dispatchEvent("readystatechange")),s.dispatchEvent(e)}),k.bind("UploadProgress",function(e){I&&s.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),k.bind("Load",function(t){n("readyState",p.DONE),n("status",Number(r.exec.call(k,"XMLHttpRequest","getStatus")||0)),n("statusText",h[n("status")]||""),n("response",r.exec.call(k,"XMLHttpRequest","getResponse",n("responseType"))),~e.inArray(n("responseType"),["text",""])?n("responseText",n("response")):"document"===n("responseType")&&n("responseXML",n("response")),U=r.exec.call(k,"XMLHttpRequest","getAllResponseHeaders"),s.dispatchEvent("readystatechange"),n("status")>0?(I&&s.upload.dispatchEvent(t),s.dispatchEvent(t)):(N=!0,s.dispatchEvent("error")),i()}),k.bind("Abort",function(e){s.dispatchEvent(e),i()}),k.bind("Error",function(e){N=!0,n("readyState",p.DONE),s.dispatchEvent("readystatechange"),D=!0,s.dispatchEvent(e),i()}),r.exec.call(k,"XMLHttpRequest","send",{url:E,method:_,async:w,user:R,password:b,headers:x,mimeType:S,encoding:T,responseType:s.responseType,withCredentials:s.withCredentials,options:P},t)}var s=this;M=(new Date).getTime(),k=new a,"string"==typeof P.required_caps&&(P.required_caps=o.parseCaps(P.required_caps)),P.required_caps=e.extend({},P.required_caps,{return_response_type:s.responseType}),t instanceof c&&(P.required_caps.send_multipart=!0),L||(P.required_caps.do_cors=!0),P.ruid?r(k.connectRuntime(P)):(k.bind("RuntimeInit",function(e,t){r(t)}),k.bind("RuntimeError",function(e,t){s.dispatchEvent("RuntimeError",t)}),k.connectRuntime(P))}function g(){n("responseText",""),n("responseXML",null),n("response",null),n("status",0),n("statusText",""),M=C=null}var v=this,y={timeout:0,readyState:p.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},w=!0,E,_,x={},R,b,T=null,S=null,A=!1,O=!1,I=!1,D=!1,N=!1,L=!1,M,C,F=null,H=null,P={},k,U="",B;e.extend(this,y,{uid:e.guid("uid_"),upload:new f,open:function(o,a,s,u,c){var l;if(!o||!a)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(o)||i.utf8_encode(o)!==o)throw new t.DOMException(t.DOMException.SYNTAX_ERR);if(~e.inArray(o.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(_=o.toUpperCase()),~e.inArray(_,["CONNECT","TRACE","TRACK"]))throw new t.DOMException(t.DOMException.SECURITY_ERR);if(a=i.utf8_encode(a),l=r.parseUrl(a),L=r.hasSameOrigin(l),E=r.resolveUrl(a),(u||c)&&!L)throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);if(R=u||l.user,b=c||l.pass,w=s||!0,w===!1&&(n("timeout")||n("withCredentials")||""!==n("responseType")))throw new t.DOMException(t.DOMException.INVALID_ACCESS_ERR);A=!w,O=!1,x={},g.call(this),n("readyState",p.OPENED),this.convertEventPropsToHandlers(["readystatechange"]),this.dispatchEvent("readystatechange")},setRequestHeader:function(r,o){var a=["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"];if(n("readyState")!==p.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(r)||i.utf8_encode(r)!==r)throw new t.DOMException(t.DOMException.SYNTAX_ERR);return r=e.trim(r).toLowerCase(),~e.inArray(r,a)||/^(proxy\-|sec\-)/.test(r)?!1:(x[r]?x[r]+=", "+o:x[r]=o,!0)},getAllResponseHeaders:function(){return U||""},getResponseHeader:function(t){return t=t.toLowerCase(),N||~e.inArray(t,["set-cookie","set-cookie2"])?null:U&&""!==U&&(B||(B={},e.each(U.split(/\r\n/),function(t){var n=t.split(/:\s+/);2===n.length&&(n[0]=e.trim(n[0]),B[n[0].toLowerCase()]={header:n[0],value:e.trim(n[1])})})),B.hasOwnProperty(t))?B[t].header+": "+B[t].value:null},overrideMimeType:function(i){var r,o;if(~e.inArray(n("readyState"),[p.LOADING,p.DONE]))throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(i=e.trim(i.toLowerCase()),/;/.test(i)&&(r=i.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(i=r[1],r[2]&&(o=r[2])),!d.mimes[i])throw new t.DOMException(t.DOMException.SYNTAX_ERR);F=i,H=o},send:function(n,r){if(P="string"===e.typeOf(r)?{ruid:r}:r?r:{},this.convertEventPropsToHandlers(m),this.upload.convertEventPropsToHandlers(m),this.readyState!==p.OPENED||O)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);if(n instanceof s)P.ruid=n.ruid,S=n.type||"application/octet-stream";else if(n instanceof c){if(n.hasBlob()){var o=n.getBlob();P.ruid=o.ruid,S=o.type||"application/octet-stream"}}else"string"==typeof n&&(T="UTF-8",S="text/plain;charset=UTF-8",n=i.utf8_encode(n));this.withCredentials||(this.withCredentials=P.required_caps&&P.required_caps.send_browser_cookies&&!L),I=!A&&this.upload.hasEventListener(),N=!1,D=!n,A||(O=!0),u.call(this,n)},abort:function(){if(N=!0,A=!1,~e.inArray(n("readyState"),[p.UNSENT,p.OPENED,p.DONE]))n("readyState",p.UNSENT);else{if(n("readyState",p.DONE),O=!1,!k)throw new t.DOMException(t.DOMException.INVALID_STATE_ERR);k.getRuntime().exec.call(k,"XMLHttpRequest","abort",D),D=!0}},destroy:function(){k&&("function"===e.typeOf(k.destroy)&&k.destroy(),k=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}})}var h={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};f.prototype=n.instance;var m=["loadstart","progress","abort","error","load","timeout","loadend"],g=1,v=2;return p.UNSENT=0,p.OPENED=1,p.HEADERS_RECEIVED=2,p.LOADING=3,p.DONE=4,p.prototype=n.instance,p}),i(O,[u,m,v,h],function(e,t,n,i){function r(){function i(){l=d=0,c=this.result=null}function o(t,n){var i=this;u=n,i.bind("TransportingProgress",function(t){d=t.loaded,l>d&&-1===e.inArray(i.state,[r.IDLE,r.DONE])&&a.call(i)},999),i.bind("TransportingComplete",function(){d=l,i.state=r.DONE,c=null,i.result=u.exec.call(i,"Transporter","getAsBlob",t||"")},999),i.state=r.BUSY,i.trigger("TransportingStarted"),a.call(i)}function a(){var e=this,n,i=l-d;f>i&&(f=i),n=t.btoa(c.substr(d,f)),u.exec.call(e,"Transporter","receive",n,l)}var s,u,c,l,d,f;n.call(this),e.extend(this,{uid:e.guid("uid_"),state:r.IDLE,result:null,transport:function(t,n,r){var a=this;if(r=e.extend({chunk_size:204798},r),(s=r.chunk_size%3)&&(r.chunk_size+=3-s),f=r.chunk_size,i.call(this),c=t,l=t.length,"string"===e.typeOf(r)||r.ruid)o.call(a,n,this.connectRuntime(r));else{var u=function(e,t){a.unbind("RuntimeInit",u),o.call(a,n,t)};this.bind("RuntimeInit",u),this.connectRuntime(r)}},abort:function(){var e=this;e.state=r.IDLE,u&&(u.exec.call(e,"Transporter","clear"),e.trigger("TransportingAborted")),i.call(e)},destroy:function(){this.unbindAll(),u=null,this.disconnectRuntime(),i.call(this)}})}return r.IDLE=0,r.BUSY=1,r.DONE=2,r.prototype=i.instance,r}),i(I,[u,f,p,T,A,g,v,O,d,h,y,w,m],function(e,t,n,i,r,o,a,s,u,c,l,d,f){function p(){function i(e){e||(e=this.getRuntime().exec.call(this,"Image","getInfo")),this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}function c(t){var i=e.typeOf(t);try{if(t instanceof p){if(!t.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);m.apply(this,arguments)}else if(t instanceof l){if(!~e.inArray(t.type,["image/jpeg","image/png"]))throw new n.ImageError(n.ImageError.WRONG_FORMAT);g.apply(this,arguments)}else if(-1!==e.inArray(i,["blob","file"]))c.call(this,new d(null,t),arguments[1]);else if("string"===i)/^data:[^;]*;base64,/.test(t)?c.call(this,new l(null,{data:t}),arguments[1]):v.apply(this,arguments);else{if("node"!==i||"img"!==t.nodeName.toLowerCase())throw new n.DOMException(n.DOMException.TYPE_MISMATCH_ERR);c.call(this,t.src,arguments[1])}}catch(r){this.trigger("error",r)}}function m(t,n){var i=this.connectRuntime(t.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",t,"undefined"===e.typeOf(n)?!0:n)}function g(t,n){function i(e){r.ruid=e.uid,e.exec.call(r,"Image","loadFromBlob",t)}var r=this;r.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){i(t)}),n&&"string"==typeof n.required_caps&&(n.required_caps=o.parseCaps(n.required_caps)),this.connectRuntime(e.extend({required_caps:{access_image_binary:!0,resize_image:!0}},n))):i(this.connectRuntime(t.ruid))}function v(e,t){var n=this,i;i=new r,i.open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){g.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}a.call(this),e.extend(this,{uid:e.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){this.bind("Load Resize",function(){i.call(this)},999),this.convertEventPropsToHandlers(h),c.apply(this,arguments)},downsize:function(t,i,r,o){try{if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>p.MAX_RESIZE_WIDTH||this.height>p.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);(!t&&!i||"undefined"===e.typeOf(r))&&(r=!1),t=t||this.width,i=i||this.height,o="undefined"===e.typeOf(o)?!0:!!o,this.getRuntime().exec.call(this,"Image","downsize",t,i,r,o)}catch(a){this.trigger("error",a)}},crop:function(e,t,n){this.downsize(e,t,!0,n)},getAsCanvas:function(){if(!u.can("create_canvas"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);var e=this.connectRuntime(this.ruid);return e.exec.call(this,"Image","getAsCanvas")},getAsBlob:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return e||(e="image/jpeg"),"image/jpeg"!==e||t||(t=90),this.getRuntime().exec.call(this,"Image","getAsBlob",e,t)},getAsDataURL:function(e,t){if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);return this.getRuntime().exec.call(this,"Image","getAsDataURL",e,t)},getAsBinaryString:function(e,t){var n=this.getAsDataURL(e,t);return f.atob(n.substring(n.indexOf("base64,")+7))},embed:function(i){function r(){if(u.can("create_canvas")){var t=a.getAsCanvas();if(t)return i.appendChild(t),t=null,a.destroy(),o.trigger("embedded"),void 0}var r=a.getAsDataURL(c,l);if(!r)throw new n.ImageError(n.ImageError.WRONG_FORMAT);if(u.can("use_data_uri_of",r.length))i.innerHTML='<img src="'+r+'" width="'+a.width+'" height="'+a.height+'" />',a.destroy(),o.trigger("embedded");else{var d=new s;d.bind("TransportingComplete",function(){v=o.connectRuntime(this.result.ruid),o.bind("Embedded",function(){e.extend(v.getShimContainer().style,{top:"0px",left:"0px",width:a.width+"px",height:a.height+"px"}),v=null},999),v.exec.call(o,"ImageView","display",this.result.uid,m,g),a.destroy()}),d.transport(f.atob(r.substring(r.indexOf("base64,")+7)),c,e.extend({},h,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:i}))}}var o=this,a,c,l,d,h=arguments[1]||{},m=this.width,g=this.height,v;try{if(!(i=t.get(i)))throw new n.DOMException(n.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new n.DOMException(n.DOMException.INVALID_STATE_ERR);if(this.width>p.MAX_RESIZE_WIDTH||this.height>p.MAX_RESIZE_HEIGHT)throw new n.ImageError(n.ImageError.MAX_RESOLUTION_ERR);if(c=h.type||this.type||"image/jpeg",l=h.quality||90,d="undefined"!==e.typeOf(h.crop)?h.crop:!1,h.width)m=h.width,g=h.height||m;else{var y=t.getSize(i);y.w&&y.h&&(m=y.w,g=y.h)}return a=new p,a.bind("Resize",function(){r.call(o)}),a.bind("Load",function(){a.downsize(m,g,d,!1)}),a.clone(this,!1),a}catch(w){this.trigger("error",w)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}})}var h=["progress","load","error","resize","embedded"];return p.MAX_RESIZE_WIDTH=6500,p.MAX_RESIZE_HEIGHT=6500,p.prototype=c.instance,p}),i(D,[u,p,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue,c=e.extend({access_binary:s(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return r.can("access_binary")&&!!a.Image},display_media:s(i.can("create_canvas")||i.can("use_data_uri_over32kb")),do_cors:s(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:s(function(){var e=document.createElement("div");return("draggable"in e||"ondragstart"in e&&"ondrop"in e)&&("IE"!==i.browser||i.version>9)}()),filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),return_response_headers:u,return_response_type:function(e){return"json"===e&&window.JSON?!0:i.can("return_response_type",e)},return_status_code:u,report_upload_progress:s(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return r.can("access_binary")&&i.can("create_canvas")},select_file:function(){return i.can("use_fileinput")&&window.File},select_folder:function(){return r.can("select_file")&&"Chrome"===i.browser&&i.version>=21},select_multiple:function(){return!(!r.can("select_file")||"Safari"===i.browser&&"Windows"===i.os||"iOS"===i.os&&i.verComp(i.osVersion,"7.0.4","<"))},send_binary_string:s(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:s(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||r.can("send_binary_string")},slice_blob:s(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return r.can("slice_blob")&&r.can("send_multipart")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||"IE"===i.browser&&i.version>=10||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u},arguments[2]);n.call(this,t,arguments[1]||o,c),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html5",a={};return n.addConstructor(o,r),a}),i(N,[D,y],function(e,t){function n(){function e(e,t,n){var i;if(!window.File.prototype.slice)return(i=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?i.call(e,t,n):null;try{return e.slice(),e.slice(t,n)}catch(r){return e.slice(t,n-t)}}this.slice=function(){return new t(this.getRuntime().uid,e.apply(this,arguments))}}return e.Blob=n}),i(L,[u],function(e){function t(){this.returnValue=!1}function n(){this.cancelBubble=!0}var i={},r="moxie_"+e.guid(),o=function(o,a,s,u){var c,l;a=a.toLowerCase(),o.addEventListener?(c=s,o.addEventListener(a,c,!1)):o.attachEvent&&(c=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=t,e.stopPropagation=n,s(e)},o.attachEvent("on"+a,c)),o[r]||(o[r]=e.guid()),i.hasOwnProperty(o[r])||(i[o[r]]={}),l=i[o[r]],l.hasOwnProperty(a)||(l[a]=[]),l[a].push({func:c,orig:s,key:u})},a=function(t,n,o){var a,s;if(n=n.toLowerCase(),t[r]&&i[t[r]]&&i[t[r]][n]){a=i[t[r]][n];for(var u=a.length-1;u>=0&&(a[u].orig!==o&&a[u].key!==o||(t.removeEventListener?t.removeEventListener(n,a[u].func,!1):t.detachEvent&&t.detachEvent("on"+n,a[u].func),a[u].orig=null,a[u].func=null,a.splice(u,1),o===s));u--);if(a.length||delete i[t[r]][n],e.isEmptyObj(i[t[r]])){delete i[t[r]];try{delete t[r]}catch(c){t[r]=s}}}},s=function(t,n){t&&t[r]&&e.each(i[t[r]],function(e,i){a(t,i,n)})};return{addEvent:o,removeEvent:a,removeAllEvents:s}}),i(M,[D,u,f,L,l,d],function(e,t,n,i,r,o){function a(){var e=[],a;t.extend(this,{init:function(s){var u=this,c=u.getRuntime(),l,d,f,p,h,m;a=s,e=[],f=a.accept.mimes||r.extList2mimes(a.accept,c.can("filter_by_extension")),d=c.getShimContainer(),d.innerHTML='<input id="'+c.uid+'" type="file" style="font-size:999px;opacity:0;"'+(a.multiple&&c.can("select_multiple")?"multiple":"")+(a.directory&&c.can("select_folder")?"webkitdirectory directory":"")+(f?' accept="'+f.join(",")+'"':"")+" />",l=n.get(c.uid),t.extend(l.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),p=n.get(a.browse_button),c.can("summon_file_dialog")&&("static"===n.getStyle(p,"position")&&(p.style.position="relative"),h=parseInt(n.getStyle(p,"z-index"),10)||1,p.style.zIndex=h,d.style.zIndex=h-1,i.addEvent(p,"click",function(e){var t=n.get(c.uid);t&&!t.disabled&&t.click(),e.preventDefault()},u.uid)),m=c.can("summon_file_dialog")?p:d,i.addEvent(m,"mouseover",function(){u.trigger("mouseenter")},u.uid),i.addEvent(m,"mouseout",function(){u.trigger("mouseleave")},u.uid),i.addEvent(m,"mousedown",function(){u.trigger("mousedown")},u.uid),i.addEvent(n.get(a.container),"mouseup",function(){u.trigger("mouseup")},u.uid),l.onchange=function g(){if(e=[],a.directory?t.each(this.files,function(t){"."!==t.name&&e.push(t)}):e=[].slice.call(this.files),"IE"!==o.browser)this.value="";else{var n=this.cloneNode(!0);this.parentNode.replaceChild(n,this),n.onchange=g}u.trigger("change")},u.trigger({type:"ready",async:!0}),d=null},getFiles:function(){return e},disable:function(e){var t=this.getRuntime(),i;(i=n.get(t.uid))&&(i.disabled=!!e)},destroy:function(){var t=this.getRuntime(),r=t.getShim(),o=t.getShimContainer();i.removeAllEvents(o,this.uid),i.removeAllEvents(a&&n.get(a.container),this.uid),i.removeAllEvents(a&&n.get(a.browse_button),this.uid),o&&(o.innerHTML=""),r.removeInstance(this.uid),e=a=o=r=null}})}return e.FileInput=a}),i(C,[D,u,f,L,l],function(e,t,n,i,r){function o(){function e(e){for(var n=[],i=0;i<e.length;i++)[].push.apply(n,e[i].extensions.split(/\s*,\s*/));return-1===t.inArray("*",n)?n:[]}function o(e){var n=r.getFileExtension(e.name);return!n||!d.length||-1!==t.inArray(n,d)}function a(e,n){var i=[];t.each(e,function(e){var t=e.webkitGetAsEntry();if(t)if(t.isFile){var n=e.getAsFile();o(n)&&l.push(n)}else i.push(t)}),i.length?s(i,n):n()}function s(e,n){var i=[];t.each(e,function(e){i.push(function(t){u(e,t)})}),t.inSeries(i,function(){n()})}function u(e,t){e.isFile?e.file(function(e){o(e)&&l.push(e),t()},function(){t()}):e.isDirectory?c(e,t):t()}function c(e,t){function n(e){r.readEntries(function(t){t.length?([].push.apply(i,t),n(e)):e()},e)}var i=[],r=e.createReader();n(function(){s(i,t)})}var l=[],d=[],f;t.extend(this,{init:function(n){var r=this,s;f=n,d=e(f.accept),s=f.container,i.addEvent(s,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},r.uid),i.addEvent(s,"drop",function(e){e.preventDefault(),e.stopPropagation(),l=[],e.dataTransfer.items&&e.dataTransfer.items[0].webkitGetAsEntry?a(e.dataTransfer.items,function(){r.trigger("drop")}):(t.each(e.dataTransfer.files,function(e){o(e)&&l.push(e)}),r.trigger("drop"))},r.uid),i.addEvent(s,"dragenter",function(e){e.preventDefault(),e.stopPropagation(),r.trigger("dragenter")},r.uid),i.addEvent(s,"dragleave",function(e){e.preventDefault(),e.stopPropagation(),r.trigger("dragleave")},r.uid)},getFiles:function(){return l},destroy:function(){i.removeAllEvents(f&&n.get(f.container),this.uid),l=d=f=null}})}return e.FileDrop=o}),i(F,[D,m,u],function(e,t,n){function i(){function e(e){return t.atob(e.substring(e.indexOf("base64,")+7))}var i,r=!1;n.extend(this,{read:function(e,t){var o=this;i=new window.FileReader,i.addEventListener("progress",function(e){o.trigger(e)}),i.addEventListener("load",function(e){o.trigger(e)}),i.addEventListener("error",function(e){o.trigger(e,i.error)}),i.addEventListener("loadend",function(){i=null}),"function"===n.typeOf(i[e])?(r=!1,i[e](t.getSource())):"readAsBinaryString"===e&&(r=!0,i.readAsDataURL(t.getSource()))},getResult:function(){return i&&i.result?r?e(i.result):i.result:null},abort:function(){i&&i.abort()},destroy:function(){i=null}})}return e.FileReader=i}),i(H,[D,u,l,b,w,y,S,p,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(e,t){var n=this,i,r;i=t.getBlob().getSource(),r=new window.FileReader,r.onload=function(){t.append(t.getBlobName(),new o(null,{type:i.type,data:r.result})),f.send.call(n,e,t)},r.readAsBinaryString(i)}function c(){return!window.XMLHttpRequest||"IE"===u.browser&&u.version<8?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(n){}}():new window.XMLHttpRequest}function l(e){var t=e.responseXML,n=e.responseText;return"IE"===u.browser&&n&&t&&!t.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(e.getResponseHeader("Content-Type"))&&(t=new window.ActiveXObject("Microsoft.XMLDOM"),t.async=!1,t.validateOnParse=!1,t.loadXML(n)),t&&("IE"===u.browser&&0!==t.parseError||!t.documentElement||"parsererror"===t.documentElement.tagName)?null:t}function d(e){var t="----moxieboundary"+(new Date).getTime(),n="--",i="\r\n",r="",a=this.getRuntime();if(!a.can("send_binary_string"))throw new s.RuntimeError(s.RuntimeError.NOT_SUPPORTED_ERR);return p.setRequestHeader("Content-Type","multipart/form-data; boundary="+t),e.each(function(e,a){r+=e instanceof o?n+t+i+'Content-Disposition: form-data; name="'+a+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'"'+i+"Content-Type: "+(e.type||"application/octet-stream")+i+i+e.getSource()+i:n+t+i+'Content-Disposition: form-data; name="'+a+'"'+i+i+unescape(encodeURIComponent(e))+i}),r+=n+t+n+i}var f=this,p,h;t.extend(this,{send:function(n,r){var s=this,l="Mozilla"===u.browser&&u.version>=4&&u.version<7,f="Android Browser"===u.browser,m=!1;if(h=n.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),p=c(),p.open(n.method,n.url,n.async,n.user,n.password),r instanceof o)r.isDetached()&&(m=!0),r=r.getSource();else if(r instanceof a){if(r.hasBlob())if(r.getBlob().isDetached())r=d.call(s,r),m=!0;else if((l||f)&&"blob"===t.typeOf(r.getBlob().getSource())&&window.FileReader)return e.call(s,n,r),void 0;if(r instanceof a){var g=new window.FormData;r.each(function(e,t){e instanceof o?g.append(t,e.getSource()):g.append(t,e)}),r=g}}p.upload?(n.withCredentials&&(p.withCredentials=!0),p.addEventListener("load",function(e){s.trigger(e)}),p.addEventListener("error",function(e){s.trigger(e)}),p.addEventListener("progress",function(e){s.trigger(e)}),p.upload.addEventListener("progress",function(e){s.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):p.onreadystatechange=function v(){switch(p.readyState){case 1:break;case 2:break;case 3:var e,t;try{i.hasSameOrigin(n.url)&&(e=p.getResponseHeader("Content-Length")||0),p.responseText&&(t=p.responseText.length)}catch(r){e=t=0}s.trigger({type:"progress",lengthComputable:!!e,total:parseInt(e,10),loaded:t});break;case 4:p.onreadystatechange=function(){},0===p.status?s.trigger("error"):s.trigger("load")}},t.isEmptyObj(n.headers)||t.each(n.headers,function(e,t){p.setRequestHeader(t,e)}),""!==n.responseType&&"responseType"in p&&(p.responseType="json"!==n.responseType||u.can("return_response_type","json")?n.responseType:"text"),m?p.sendAsBinary?p.sendAsBinary(r):function(){for(var e=new Uint8Array(r.length),t=0;t<r.length;t++)e[t]=255&r.charCodeAt(t);p.send(e.buffer)}():p.send(r),s.trigger("loadstart")},getStatus:function(){try{if(p)return p.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var i=new r(t.uid,p.response),o=p.getResponseHeader("Content-Disposition");if(o){var a=o.match(/filename=([\'\"'])([^\1]+)\1/);a&&(h=a[2])}return i.name=h,i.type||(i.type=n.getFileMime(h)),i;case"json":return u.can("return_response_type","json")?p.response:200===p.status&&window.JSON?JSON.parse(p.responseText):null;case"document":return l(p);default:return""!==p.responseText?p.responseText:null}}catch(s){return null}},getAllResponseHeaders:function(){try{return p.getAllResponseHeaders()}catch(e){}return""},abort:function(){p&&p.abort()},destroy:function(){f=h=null}})}return e.XMLHttpRequest=c}),i(P,[],function(){return function(){function e(e,t){var n=r?0:-8*(t-1),i=0,a;for(a=0;t>a;a++)i|=o.charCodeAt(e+a)<<Math.abs(n+8*a);return i}function n(e,t,n){n=3===arguments.length?n:o.length-t-1,o=o.substr(0,t)+e+o.substr(n+t)}function i(e,t,i){var o="",a=r?0:-8*(i-1),s;for(s=0;i>s;s++)o+=String.fromCharCode(255&t>>Math.abs(a+8*s));n(o,e,i)}var r=!1,o;return{II:function(e){return e===t?r:(r=e,void 0)},init:function(e){r=!1,o=e},SEGMENT:function(e,t,i){switch(arguments.length){case 1:return o.substr(e,o.length-e-1);case 2:return o.substr(e,t);case 3:n(i,e,t);break;default:return o}},BYTE:function(t){return e(t,1)},SHORT:function(t){return e(t,2)},LONG:function(n,r){return r===t?e(n,4):(i(n,r,4),void 0)},SLONG:function(t){var n=e(t,4);return n>2147483647?n-4294967296:n},STRING:function(t,n){var i="";for(n+=t;n>t;t++)i+=String.fromCharCode(e(t,1));return i}}}}),i(k,[P],function(e){return function t(n){var i=[],r,o,a,s=0;if(r=new e,r.init(n),65496===r.SHORT(0)){for(o=2;o<=n.length;)if(a=r.SHORT(o),a>=65488&&65495>=a)o+=2;else{if(65498===a||65497===a)break;s=r.SHORT(o+2)+2,a>=65505&&65519>=a&&i.push({hex:a,name:"APP"+(15&a),start:o,length:s,segment:r.SEGMENT(o,s)}),o+=s}return r.init(null),{headers:i,restore:function(e){var t,n;for(r.init(e),o=65504==r.SHORT(2)?4+r.SHORT(4):2,n=0,t=i.length;t>n;n++)r.SEGMENT(o,0,i[n].segment),o+=i[n].length;return e=r.SEGMENT(),r.init(null),e},strip:function(e){var n,i,o;for(i=new t(e),n=i.headers,i.purge(),r.init(e),o=n.length;o--;)r.SEGMENT(n[o].start,n[o].length,"");return e=r.SEGMENT(),r.init(null),e},get:function(e){for(var t=[],n=0,r=i.length;r>n;n++)i[n].name===e.toUpperCase()&&t.push(i[n].segment);return t},set:function(e,t){var n=[],r,o,a;for("string"==typeof t?n.push(t):n=t,r=o=0,a=i.length;a>r&&(i[r].name===e.toUpperCase()&&(i[r].segment=n[o],i[r].length=n[o].length,o++),!(o>=n.length));r++);},purge:function(){i=[],r.init(null),r=null}}}}}),i(U,[u,P],function(e,n){return function i(){function i(e,n){var i=a.SHORT(e),r,o,s,u,d,f,p,h,m=[],g={};for(r=0;i>r;r++)if(p=f=e+12*r+2,s=n[a.SHORT(p)],s!==t){switch(u=a.SHORT(p+=2),d=a.LONG(p+=2),p+=4,m=[],u){case 1:case 7:for(d>4&&(p=a.LONG(p)+c.tiffHeader),o=0;d>o;o++)m[o]=a.BYTE(p+o);break;case 2:d>4&&(p=a.LONG(p)+c.tiffHeader),g[s]=a.STRING(p,d-1);continue;case 3:for(d>2&&(p=a.LONG(p)+c.tiffHeader),o=0;d>o;o++)m[o]=a.SHORT(p+2*o);break;case 4:for(d>1&&(p=a.LONG(p)+c.tiffHeader),o=0;d>o;o++)m[o]=a.LONG(p+4*o);break;case 5:for(p=a.LONG(p)+c.tiffHeader,o=0;d>o;o++)m[o]=a.LONG(p+4*o)/a.LONG(p+4*o+4);break;case 9:for(p=a.LONG(p)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(p+4*o);break;case 10:for(p=a.LONG(p)+c.tiffHeader,o=0;d>o;o++)m[o]=a.SLONG(p+4*o)/a.SLONG(p+4*o+4);break;default:continue}h=1==d?m[0]:m,g[s]=l.hasOwnProperty(s)&&"object"!=typeof h?l[s][h]:h}return g}function r(){var e=c.tiffHeader;return a.II(18761==a.SHORT(e)),42!==a.SHORT(e+=2)?!1:(c.IFD0=c.tiffHeader+a.LONG(e+=2),u=i(c.IFD0,s.tiff),"ExifIFDPointer"in u&&(c.exifIFD=c.tiffHeader+u.ExifIFDPointer,delete u.ExifIFDPointer),"GPSInfoIFDPointer"in u&&(c.gpsIFD=c.tiffHeader+u.GPSInfoIFDPointer,delete u.GPSInfoIFDPointer),!0)}function o(e,t,n){var i,r,o,u=0;if("string"==typeof t){var l=s[e.toLowerCase()];for(var d in l)if(l[d]===t){t=d;break}}i=c[e.toLowerCase()+"IFD"],r=a.SHORT(i);for(var f=0;r>f;f++)if(o=i+12*f+2,a.SHORT(o)==t){u=o+8;break}return u?(a.LONG(u,n),!0):!1}var a,s,u,c={},l;return a=new n,s={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"}},l={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire.",1:"Flash fired.",5:"Strobe return light not detected.",7:"Strobe return light detected.",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},{init:function(e){return c={tiffHeader:10},e!==t&&e.length?(a.init(e),65505===a.SHORT(0)&&"EXIF\0"===a.STRING(4,5).toUpperCase()?r():!1):!1
15
+ },TIFF:function(){return u},EXIF:function(){var t;if(t=i(c.exifIFD,s.exif),t.ExifVersion&&"array"===e.typeOf(t.ExifVersion)){for(var n=0,r="";n<t.ExifVersion.length;n++)r+=String.fromCharCode(t.ExifVersion[n]);t.ExifVersion=r}return t},GPS:function(){var t;return t=i(c.gpsIFD,s.gps),t.GPSVersionID&&"array"===e.typeOf(t.GPSVersionID)&&(t.GPSVersionID=t.GPSVersionID.join(".")),t},setExif:function(e,t){return"PixelXDimension"!==e&&"PixelYDimension"!==e?!1:o("exif",e,t)},getBinary:function(){return a.SEGMENT()},purge:function(){a.init(null),a=u=null,c={}}}}}),i(B,[u,p,k,P,U],function(e,t,n,i,r){function o(o){function a(){for(var e=0,t,n;e<=u.length;){if(t=c.SHORT(e+=2),t>=65472&&65475>=t)return e+=5,{height:c.SHORT(e),width:c.SHORT(e+=2)};n=c.SHORT(e+=2),e+=n-2}return null}function s(){d&&l&&c&&(d.purge(),l.purge(),c.init(null),u=f=l=d=c=null)}var u,c,l,d,f,p;if(u=o,c=new i,c.init(u),65496!==c.SHORT(0))throw new t.ImageError(t.ImageError.WRONG_FORMAT);l=new n(o),d=new r,p=!!d.init(l.get("app1")[0]),f=a.call(this),e.extend(this,{type:"image/jpeg",size:u.length,width:f&&f.width||0,height:f&&f.height||0,setExif:function(t,n){return p?("object"===e.typeOf(t)?e.each(t,function(e,t){d.setExif(t,e)}):d.setExif(t,n),l.set("app1",d.getBinary()),void 0):!1},writeHeaders:function(){return arguments.length?l.restore(arguments[0]):u=l.restore(u)},stripHeaders:function(e){return l.strip(e)},purge:function(){s.call(this)}}),p&&(this.meta={tiff:d.TIFF(),exif:d.EXIF(),gps:d.GPS()})}return o}),i(z,[p,u,P],function(e,t,n){function i(i){function r(){var e,t;return e=a.call(this,8),"IHDR"==e.type?(t=e.start,{width:u.LONG(t),height:u.LONG(t+=4)}):null}function o(){u&&(u.init(null),s=d=c=l=u=null)}function a(e){var t,n,i,r;return t=u.LONG(e),n=u.STRING(e+=4,4),i=e+=4,r=u.LONG(e+t),{length:t,type:n,start:i,CRC:r}}var s,u,c,l,d;s=i,u=new n,u.init(s),function(){var t=0,n=0,i=[35152,20039,3338,6666];for(n=0;n<i.length;n++,t+=2)if(i[n]!=u.SHORT(t))throw new e.ImageError(e.ImageError.WRONG_FORMAT)}(),d=r.call(this),t.extend(this,{type:"image/png",size:s.length,width:d.width,height:d.height,purge:function(){o.call(this)}}),o.call(this)}return i}),i(G,[u,p,B,z],function(e,t,n,i){return function(r){var o=[n,i],a;a=function(){for(var e=0;e<o.length;e++)try{return new o[e](r)}catch(n){}throw new t.ImageError(t.ImageError.WRONG_FORMAT)}(),e.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){}}),e.extend(this,a),this.purge=function(){a.purge(),a=null}}}),i(q,[],function(){function e(e,i,r){var o=e.naturalWidth,a=e.naturalHeight,s=r.width,u=r.height,c=r.x||0,l=r.y||0,d=i.getContext("2d");t(e)&&(o/=2,a/=2);var f=1024,p=document.createElement("canvas");p.width=p.height=f;for(var h=p.getContext("2d"),m=n(e,o,a),g=0;a>g;){for(var v=g+f>a?a-g:f,y=0;o>y;){var w=y+f>o?o-y:f;h.clearRect(0,0,f,f),h.drawImage(e,-y,-g);var E=y*s/o+c<<0,_=Math.ceil(w*s/o),x=g*u/a/m+l<<0,R=Math.ceil(v*u/a/m);d.drawImage(p,0,0,w,v,E,x,_,R),y+=f}g+=f}p=h=null}function t(e){var t=e.naturalWidth,n=e.naturalHeight;if(t*n>1048576){var i=document.createElement("canvas");i.width=i.height=1;var r=i.getContext("2d");return r.drawImage(e,-t+1,0),0===r.getImageData(0,0,1,1).data[3]}return!1}function n(e,t,n){var i=document.createElement("canvas");i.width=1,i.height=n;var r=i.getContext("2d");r.drawImage(e,0,0);for(var o=r.getImageData(0,0,1,n).data,a=0,s=n,u=n;u>a;){var c=o[4*(u-1)+3];0===c?s=u:a=u,u=s+a>>1}i=null;var l=u/n;return 0===l?1:l}return{isSubsampled:t,renderTo:e}}),i(X,[D,u,p,m,w,G,q,l,d],function(e,t,n,i,r,o,a,s,u){function c(){function e(){if(!E&&!y)throw new n.ImageError(n.DOMException.INVALID_STATE_ERR);return E||y}function c(e){return i.atob(e.substring(e.indexOf("base64,")+7))}function l(e,t){return"data:"+(t||"")+";base64,"+i.btoa(e)}function d(e){var t=this;y=new Image,y.onerror=function(){g.call(this),t.trigger("error",new n.ImageError(n.ImageError.WRONG_FORMAT))},y.onload=function(){t.trigger("load")},y.src=/^data:[^;]*;base64,/.test(e)?e:l(e,x.type)}function f(e,t){var i=this,r;return window.FileReader?(r=new FileReader,r.onload=function(){t(this.result)},r.onerror=function(){i.trigger("error",new n.FileException(n.FileException.NOT_READABLE_ERR))},r.readAsDataURL(e),void 0):t(e.getAsDataURL())}function p(n,i,r,o){var a=this,s,u,c=0,l=0,d,f,p,g;if(b=o,g=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==t.inArray(g,[5,6,7,8])){var v=n;n=i,i=v}return d=e(),u=r?Math.max:Math.min,s=u(n/d.width,i/d.height),s>1&&(!r||o)?(this.trigger("Resize"),void 0):(E||(E=document.createElement("canvas")),f=Math.round(d.width*s),p=Math.round(d.height*s),r?(E.width=n,E.height=i,f>n&&(c=Math.round((f-n)/2)),p>i&&(l=Math.round((p-i)/2))):(E.width=f,E.height=p),b||m(E.width,E.height,g),h.call(this,d,E,-c,-l,f,p),this.width=E.width,this.height=E.height,R=!0,a.trigger("Resize"),void 0)}function h(e,t,n,i,r,o){if("iOS"===u.OS)a.renderTo(e,t,{width:r,height:o,x:n,y:i});else{var s=t.getContext("2d");s.drawImage(e,n,i,r,o)}}function m(e,t,n){switch(n){case 5:case 6:case 7:case 8:E.width=t,E.height=e;break;default:E.width=e,E.height=t}var i=E.getContext("2d");switch(n){case 2:i.translate(e,0),i.scale(-1,1);break;case 3:i.translate(e,t),i.rotate(Math.PI);break;case 4:i.translate(0,t),i.scale(1,-1);break;case 5:i.rotate(.5*Math.PI),i.scale(1,-1);break;case 6:i.rotate(.5*Math.PI),i.translate(0,-t);break;case 7:i.rotate(.5*Math.PI),i.translate(e,-t),i.scale(-1,1);break;case 8:i.rotate(-.5*Math.PI),i.translate(-e,0)}}function g(){w&&(w.purge(),w=null),_=y=E=x=null,R=!1}var v=this,y,w,E,_,x,R=!1,b=!0;t.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),r=arguments.length>1?arguments[1]:!0;if(!i.can("access_binary"))throw new n.RuntimeError(n.RuntimeError.NOT_SUPPORTED_ERR);return x=e,e.isDetached()?(_=e.getSource(),d.call(this,_),void 0):(f.call(this,e.getSource(),function(e){r&&(_=c(e)),d.call(t,e)}),void 0)},loadFromImage:function(e,t){this.meta=e.meta,x=new r(null,{name:e.name,size:e.size,type:e.type}),d.call(this,t?_=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var t=this.getRuntime(),n;return!w&&_&&t.can("access_image_binary")&&(w=new o(_)),n={width:e().width||0,height:e().height||0,type:x.type||s.getFileMime(x.name),size:_&&_.length||x.size||0,name:x.name||"",meta:w&&w.meta||this.meta||{}}},downsize:function(){p.apply(this,arguments)},getAsCanvas:function(){return E&&(E.id=this.uid+"_canvas"),E},getAsBlob:function(e,t){return e!==this.type&&p.call(this,this.width,this.height,!1),new r(null,{name:x.name||"",type:e,data:v.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!R)return y.src;if("image/jpeg"!==e)return E.toDataURL("image/png");try{return E.toDataURL("image/jpeg",t/100)}catch(n){return E.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!R)return _||(_=c(v.getAsDataURL(e,t))),_;if("image/jpeg"!==e)_=c(v.getAsDataURL(e,t));else{var n;t||(t=90);try{n=E.toDataURL("image/jpeg",t/100)}catch(i){n=E.toDataURL("image/jpeg")}_=c(n),w&&(_=w.stripHeaders(_),b&&(w.meta&&w.meta.exif&&w.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),_=w.writeHeaders(_)),w.purge(),w=null)}return R=!1,_},destroy:function(){v=null,g.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}return e.Image=c}),i(j,[u,d,f,p,g],function(e,t,n,i,r){function o(){var e;try{e=navigator.plugins["Shockwave Flash"],e=e.description}catch(t){try{e=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(n){e="0.0"}}return e=e.match(/\d+/g),parseFloat(e[0]+"."+e[1])}function a(a){var c=this,l;a=e.extend({swf_url:t.swf_url},a),r.call(this,a,s,{access_binary:function(e){return e&&"browser"===c.mode},access_image_binary:function(e){return e&&"browser"===c.mode},display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:function(){return"client"===c.mode},resize_image:r.capTrue,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!e.arrayDiff(t,["","text","document"])||"browser"===c.mode},return_status_code:function(t){return"browser"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:function(e){return e&&"browser"===c.mode},send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"browser"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:function(e){return e&&"browser"===c.mode},summon_file_dialog:!1,upload_filesize:function(t){return e.parseSizeStr(t)<=2097152||"client"===c.mode},use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}},{access_binary:function(e){return e?"browser":"client"},access_image_binary:function(e){return e?"browser":"client"},report_upload_progress:function(e){return e?"browser":"client"},return_response_type:function(t){return e.arrayDiff(t,["","text","json","document"])?"browser":["client","browser"]},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"browser":["client","browser"]},send_binary_string:function(e){return e?"browser":"client"},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"browser":"client"},stream_upload:function(e){return e?"client":"browser"},upload_filesize:function(t){return e.parseSizeStr(t)>=2097152?"client":"browser"}},"client"),o()<10&&(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid)},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var n,r,o;o=this.getShimContainer(),e.extend(o.style,{position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),n='<object id="'+this.uid+'" type="application/x-shockwave-flash" data="'+a.swf_url+'" ',"IE"===t.browser&&(n+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),n+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+a.swf_url+'" />'+'<param name="flashvars" value="uid='+escape(this.uid)+"&target="+t.global_event_dispatcher+'" />'+'<param name="wmode" value="transparent" />'+'<param name="allowscriptaccess" value="always" />'+"</object>","IE"===t.browser?(r=document.createElement("div"),o.appendChild(r),r.outerHTML=n,r=o=null):o.innerHTML=n,l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="flash",u={};return r.addConstructor(s,a),u}),i(V,[j,y],function(e,t){var n={slice:function(e,n,i,r){var o=this.getRuntime();return 0>n?n=Math.max(e.size+n,0):n>0&&(n=Math.min(n,e.size)),0>i?i=Math.max(e.size+i,0):i>0&&(i=Math.min(i,e.size)),e=o.shimExec.call(this,"Blob","slice",n,i,r||""),e&&(e=new t(o.uid,e)),e}};return e.Blob=n}),i(W,[j],function(e){var t={init:function(e){this.getRuntime().shimExec.call(this,"FileInput","init",{name:e.name,accept:e.accept,multiple:e.multiple}),this.trigger("ready")}};return e.FileInput=t}),i(Y,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i="",r={read:function(e,t){var r=this,o=r.getRuntime();return"readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"),r.bind("Progress",function(t,r){r&&(i+=n(r,e))}),o.shimExec.call(this,"FileReader","readAsBase64",t.uid)},getResult:function(){return i},destroy:function(){i=null}};return e.FileReader=r}),i($,[j,m],function(e,t){function n(e,n){switch(n){case"readAsText":return t.atob(e,"utf8");case"readAsBinaryString":return t.atob(e);case"readAsDataURL":return e}return null}var i={read:function(e,t){var i,r=this.getRuntime();return(i=r.shimExec.call(this,"FileReaderSync","readAsBase64",t.uid))?("readAsDataURL"===e&&(i="data:"+(t.type||"")+";base64,"+i),n(i,e,t.type)):null}};return e.FileReaderSync=i}),i(J,[j,u,y,w,T,S,O],function(e,t,n,i,r,o,a){var s={send:function(e,i){function r(){e.transport=l.mode,l.shimExec.call(c,"XMLHttpRequest","send",e,i)}function s(e,t){l.shimExec.call(c,"XMLHttpRequest","appendBlob",e,t.uid),i=null,r()}function u(e,t){var n=new a;n.bind("TransportingComplete",function(){t(this.result)}),n.transport(e.getSource(),e.type,{ruid:l.uid})}var c=this,l=c.getRuntime();if(t.isEmptyObj(e.headers)||t.each(e.headers,function(e,t){l.shimExec.call(c,"XMLHttpRequest","setRequestHeader",t,e.toString())}),i instanceof o){var d;if(i.each(function(e,t){e instanceof n?d=t:l.shimExec.call(c,"XMLHttpRequest","append",t,e)}),i.hasBlob()){var f=i.getBlob();f.isDetached()?u(f,function(e){f.destroy(),s(d,e)}):s(d,f)}else i=null,r()}else i instanceof n?i.isDetached()?u(i,function(e){i.destroy(),i=e.uid,r()}):(i=i.uid,r()):r()},getResponse:function(e){var n,o,a=this.getRuntime();if(o=a.shimExec.call(this,"XMLHttpRequest","getResponseAsBlob")){if(o=new i(a.uid,o),"blob"===e)return o;try{if(n=new r,~t.inArray(e,["","text"]))return n.readAsText(o);if("json"===e&&window.JSON)return JSON.parse(n.readAsText(o))}finally{o.destroy()}}return null},abort:function(e){var t=this.getRuntime();t.shimExec.call(this,"XMLHttpRequest","abort"),this.dispatchEvent("readystatechange"),this.dispatchEvent("abort")}};return e.XMLHttpRequest=s}),i(Z,[j,y],function(e,t){var n={getAsBlob:function(e){var n=this.getRuntime(),i=n.shimExec.call(this,"Transporter","getAsBlob",e);return i?new t(n.uid,i):null}};return e.Transporter=n}),i(K,[j,u,O,y,T],function(e,t,n,i,r){var o={loadFromBlob:function(e){function t(e){r.shimExec.call(i,"Image","loadFromBlob",e.uid),i=r=null}var i=this,r=i.getRuntime();if(e.isDetached()){var o=new n;o.bind("TransportingComplete",function(){t(o.result.getSource())}),o.transport(e.getSource(),e.type,{ruid:r.uid})}else t(e.getSource())},loadFromImage:function(e){var t=this.getRuntime();return t.shimExec.call(this,"Image","loadFromImage",e.uid)},getAsBlob:function(e,t){var n=this.getRuntime(),r=n.shimExec.call(this,"Image","getAsBlob",e,t);return r?new i(n.uid,r):null},getAsDataURL:function(){var e=this.getRuntime(),t=e.Image.getAsBlob.apply(this,arguments),n;return t?(n=new r,n.readAsDataURL(t)):null}};return e.Image=o}),i(Q,[u,d,f,p,g],function(e,t,n,i,r){function o(e){var t=!1,n=null,i,r,o,a,s,u=0;try{try{n=new ActiveXObject("AgControl.AgControl"),n.IsVersionSupported(e)&&(t=!0),n=null}catch(c){var l=navigator.plugins["Silverlight Plug-In"];if(l){for(i=l.description,"1.0.30226.2"===i&&(i="2.0.30226.2"),r=i.split(".");r.length>3;)r.pop();for(;r.length<4;)r.push(0);for(o=e.split(".");o.length>4;)o.pop();do a=parseInt(o[u],10),s=parseInt(r[u],10),u++;while(u<o.length&&a===s);s>=a&&!isNaN(a)&&(t=!0)}}}catch(d){t=!1}return t}function a(a){var c=this,l;a=e.extend({xap_url:t.xap_url},a),r.call(this,a,s,{access_binary:r.capTrue,access_image_binary:r.capTrue,display_media:r.capTrue,do_cors:r.capTrue,drag_and_drop:!1,report_upload_progress:r.capTrue,resize_image:r.capTrue,return_response_headers:function(e){return e&&"client"===c.mode},return_response_type:function(e){return"json"!==e?!0:!!window.JSON},return_status_code:function(t){return"client"===c.mode||!e.arrayDiff(t,[200,404])},select_file:r.capTrue,select_multiple:r.capTrue,send_binary_string:r.capTrue,send_browser_cookies:function(e){return e&&"browser"===c.mode},send_custom_headers:function(e){return e&&"client"===c.mode},send_multipart:r.capTrue,slice_blob:r.capTrue,stream_upload:!0,summon_file_dialog:!1,upload_filesize:r.capTrue,use_http_method:function(t){return"client"===c.mode||!e.arrayDiff(t,["GET","POST"])}},{return_response_headers:function(e){return e?"client":"browser"},return_status_code:function(t){return e.arrayDiff(t,[200,404])?"client":["client","browser"]},send_browser_cookies:function(e){return e?"browser":"client"},send_custom_headers:function(e){return e?"client":"browser"},use_http_method:function(t){return e.arrayDiff(t,["GET","POST"])?"client":["client","browser"]}}),o("2.0.31005.0")&&"Opera"!==t.browser||(this.mode=!1),e.extend(this,{getShim:function(){return n.get(this.uid).content.Moxie},shimExec:function(e,t){var n=[].slice.call(arguments,2);return c.getShim().exec(this.uid,e,t,n)},init:function(){var e;e=this.getShimContainer(),e.innerHTML='<object id="'+this.uid+'" data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%" style="outline:none;">'+'<param name="source" value="'+a.xap_url+'"/>'+'<param name="background" value="Transparent"/>'+'<param name="windowless" value="true"/>'+'<param name="enablehtmlaccess" value="true"/>'+'<param name="initParams" value="uid='+this.uid+",target="+t.global_event_dispatcher+'"/>'+"</object>",l=setTimeout(function(){c&&!c.initialized&&c.trigger("Error",new i.RuntimeError(i.RuntimeError.NOT_INIT_ERR))},"Windows"!==t.OS?1e4:5e3)},destroy:function(e){return function(){e.call(c),clearTimeout(l),a=l=e=c=null}}(this.destroy)},u)}var s="silverlight",u={};return r.addConstructor(s,a),u}),i(et,[Q,u,V],function(e,t,n){return e.Blob=t.extend({},n)}),i(tt,[Q],function(e){var t={init:function(e){function t(e){for(var t="",n=0;n<e.length;n++)t+=(""!==t?"|":"")+e[n].title+" | *."+e[n].extensions.replace(/,/g,";*.");return t}this.getRuntime().shimExec.call(this,"FileInput","init",t(e.accept),e.name,e.multiple),this.trigger("ready")}};return e.FileInput=t}),i(nt,[Q,f,L],function(e,t,n){var i={init:function(){var e=this,i=e.getRuntime(),r;return r=i.getShimContainer(),n.addEvent(r,"dragover",function(e){e.preventDefault(),e.stopPropagation(),e.dataTransfer.dropEffect="copy"},e.uid),n.addEvent(r,"dragenter",function(e){e.preventDefault();var n=t.get(i.uid).dragEnter(e);n&&e.stopPropagation()},e.uid),n.addEvent(r,"drop",function(e){e.preventDefault();var n=t.get(i.uid).dragDrop(e);n&&e.stopPropagation()},e.uid),i.shimExec.call(this,"FileDrop","init")}};return e.FileDrop=i}),i(it,[Q,u,Y],function(e,t,n){return e.FileReader=t.extend({},n)}),i(rt,[Q,u,$],function(e,t,n){return e.FileReaderSync=t.extend({},n)}),i(ot,[Q,u,J],function(e,t,n){return e.XMLHttpRequest=t.extend({},n)}),i(at,[Q,u,Z],function(e,t,n){return e.Transporter=t.extend({},n)}),i(st,[Q,u,K],function(e,t,n){return e.Image=t.extend({},n,{getInfo:function(){var e=this.getRuntime(),n=["tiff","exif","gps"],i={meta:{}},r=e.shimExec.call(this,"Image","getInfo");return r.meta&&t.each(n,function(e){var t=r.meta[e],n,o,a,s;if(t&&t.keys)for(i.meta[e]={},o=0,a=t.keys.length;a>o;o++)n=t.keys[o],s=t[n],s&&(/^(\d|[1-9]\d+)$/.test(s)?s=parseInt(s,10):/^\d*\.\d+$/.test(s)&&(s=parseFloat(s)),i.meta[e][n]=s)}),i.width=parseInt(r.width,10),i.height=parseInt(r.height,10),i.size=parseInt(r.size,10),i.type=r.type,i.name=r.name,i}})}),i(ut,[u,p,g,d],function(e,t,n,i){function r(t){var r=this,s=n.capTest,u=n.capTrue;n.call(this,t,o,{access_binary:s(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:s(a.Image&&(i.can("create_canvas")||i.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:s(function(){return"Chrome"===i.browser&&i.version>=28||"IE"===i.browser&&i.version>=10}()),resize_image:function(){return a.Image&&r.can("access_binary")&&i.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(t){return"json"===t&&window.JSON?!0:!!~e.inArray(t,["text","document",""])},return_status_code:function(t){return!e.arrayDiff(t,[200,404])},select_file:function(){return i.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return r.can("select_file")},summon_file_dialog:s(function(){return"Firefox"===i.browser&&i.version>=4||"Opera"===i.browser&&i.version>=12||!!~e.inArray(i.browser,["Chrome","Safari"])}()),upload_filesize:u,use_http_method:function(t){return!e.arrayDiff(t,["GET","POST"])}}),e.extend(this,{init:function(){this.trigger("Init")},destroy:function(e){return function(){e.call(r),e=r=null}}(this.destroy)}),e.extend(this.getShim(),a)}var o="html4",a={};return n.addConstructor(o,r),a}),i(ct,[ut,u,f,L,l,d],function(e,t,n,i,r,o){function a(){function e(){var r=this,l=r.getRuntime(),d,f,p,h,m,g;g=t.guid("uid_"),d=l.getShimContainer(),a&&(p=n.get(a+"_form"),p&&t.extend(p.style,{top:"100%"})),h=document.createElement("form"),h.setAttribute("id",g+"_form"),h.setAttribute("method","post"),h.setAttribute("enctype","multipart/form-data"),h.setAttribute("encoding","multipart/form-data"),t.extend(h.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),m=document.createElement("input"),m.setAttribute("id",g),m.setAttribute("type","file"),m.setAttribute("name",c.name||"Filedata"),m.setAttribute("accept",u.join(",")),t.extend(m.style,{fontSize:"999px",opacity:0}),h.appendChild(m),d.appendChild(h),t.extend(m.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===o.browser&&o.version<10&&t.extend(m.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),m.onchange=function(){var t;this.value&&(t=this.files?this.files[0]:{name:this.value},s=[t],this.onchange=function(){},e.call(r),r.bind("change",function i(){var e=n.get(g),t=n.get(g+"_form"),o;r.unbind("change",i),r.files.length&&e&&t&&(o=r.files[0],e.setAttribute("id",o.uid),t.setAttribute("id",o.uid+"_form"),t.setAttribute("target",o.uid+"_iframe")),e=t=null},998),m=h=null,r.trigger("change"))},l.can("summon_file_dialog")&&(f=n.get(c.browse_button),i.removeEvent(f,"click",r.uid),i.addEvent(f,"click",function(e){m&&!m.disabled&&m.click(),e.preventDefault()},r.uid)),a=g,d=p=f=null}var a,s=[],u=[],c;t.extend(this,{init:function(t){var o=this,a=o.getRuntime(),s;c=t,u=t.accept.mimes||r.extList2mimes(t.accept,a.can("filter_by_extension")),s=a.getShimContainer(),function(){var e,r,u;e=n.get(t.browse_button),a.can("summon_file_dialog")&&("static"===n.getStyle(e,"position")&&(e.style.position="relative"),r=parseInt(n.getStyle(e,"z-index"),10)||1,e.style.zIndex=r,s.style.zIndex=r-1),u=a.can("summon_file_dialog")?e:s,i.addEvent(u,"mouseover",function(){o.trigger("mouseenter")},o.uid),i.addEvent(u,"mouseout",function(){o.trigger("mouseleave")},o.uid),i.addEvent(u,"mousedown",function(){o.trigger("mousedown")},o.uid),i.addEvent(n.get(t.container),"mouseup",function(){o.trigger("mouseup")},o.uid),e=null}(),e.call(this),s=null,o.trigger({type:"ready",async:!0})},getFiles:function(){return s},disable:function(e){var t;(t=n.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),r=e.getShimContainer();i.removeAllEvents(r,this.uid),i.removeAllEvents(c&&n.get(c.container),this.uid),i.removeAllEvents(c&&n.get(c.browse_button),this.uid),r&&(r.innerHTML=""),t.removeInstance(this.uid),a=s=u=c=r=t=null}})}return e.FileInput=a}),i(lt,[ut,F],function(e,t){return e.FileReader=t}),i(dt,[ut,u,f,b,p,L,y,S],function(e,t,n,i,r,o,a,s){function u(){function e(e){var t=this,i,r,a,s,u=!1;if(l){if(i=l.id.replace(/_iframe$/,""),r=n.get(i+"_form")){for(a=r.getElementsByTagName("input"),s=a.length;s--;)switch(a[s].getAttribute("type")){case"hidden":a[s].parentNode.removeChild(a[s]);break;case"file":u=!0}a=[],u||r.parentNode.removeChild(r),r=null}setTimeout(function(){o.removeEvent(l,"load",t.uid),l.parentNode&&l.parentNode.removeChild(l);var n=t.getRuntime().getShimContainer();n.children.length||n.parentNode.removeChild(n),n=l=null,e()},1)}}var u,c,l;t.extend(this,{send:function(d,f){function p(){var n=m.getShimContainer()||document.body,r=document.createElement("div");r.innerHTML='<iframe id="'+g+'_iframe" name="'+g+'_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>',l=r.firstChild,n.appendChild(l),o.addEvent(l,"load",function(){var n;try{n=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(n.title)?u=n.title.replace(/^(\d+).*$/,"$1"):(u=200,c=t.trim(n.body.innerHTML),h.trigger({type:"progress",loaded:c.length,total:c.length}),w&&h.trigger({type:"uploadprogress",loaded:w.size||1025,total:w.size||1025}))}catch(r){if(!i.hasSameOrigin(d.url))return e.call(h,function(){h.trigger("error")}),void 0;u=404}e.call(h,function(){h.trigger("load")})},h.uid)}var h=this,m=h.getRuntime(),g,v,y,w;if(u=c=null,f instanceof s&&f.hasBlob()){if(w=f.getBlob(),g=w.uid,y=n.get(g),v=n.get(g+"_form"),!v)throw new r.DOMException(r.DOMException.NOT_FOUND_ERR)}else g=t.guid("uid_"),v=document.createElement("form"),v.setAttribute("id",g+"_form"),v.setAttribute("method",d.method),v.setAttribute("enctype","multipart/form-data"),v.setAttribute("encoding","multipart/form-data"),v.setAttribute("target",g+"_iframe"),m.getShimContainer().appendChild(v);f instanceof s&&f.each(function(e,n){if(e instanceof a)y&&y.setAttribute("name",n);else{var i=document.createElement("input");t.extend(i,{type:"hidden",name:n,value:e}),y?v.insertBefore(i,y):v.appendChild(i)}}),v.setAttribute("action",d.url),p(),v.submit(),h.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===t.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(n){return null}return c},abort:function(){var t=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),e.call(this,function(){t.dispatchEvent("abort")})}})}return e.XMLHttpRequest=u}),i(ft,[ut,X],function(e,t){return e.Image=t}),a([u,c,l,d,f,p,h,m,g,v,y,w,E,_,x,R,b,T,S,A,O,I,L])}(this);;(function(){"use strict";var e={},t=moxie.core.utils.Basic.inArray;return function n(r){var i,s;for(i in r)s=typeof r[i],s==="object"&&!~t(i,["Exceptions","Env","Mime"])?n(r[i]):s==="function"&&(e[i]=r[i])}(window.moxie),e.Env=window.moxie.core.utils.Env,e.Mime=window.moxie.core.utils.Mime,e.Exceptions=window.moxie.core.Exceptions,window.mOxie=e,window.o||(window.o=e),e})();
16
+ /**
17
+ * Plupload - multi-runtime File Uploader
18
+ * v2.1.1
19
+ *
20
+ * Copyright 2013, Moxiecode Systems AB
21
+ * Released under GPL License.
22
+ *
23
+ * License: http://www.plupload.com/license
24
+ * Contributing: http://www.plupload.com/contributing
25
+ *
26
+ * Date: 2014-01-16
27
+ */
28
+ ;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};return typeof t=="string"?o.each(t.split(/\s*,\s*/),function(e){r(e,!0)}):typeof t=="object"?o.each(t,function(e,t){r(t,e)}):t===!0&&(e.multipart||(n.send_binary_string=!0),e.chunk_size>0&&(n.slice_blob=!0),e.resize.enabled&&(n.send_binary_string=!0),o.each(e,function(e,t){r(t,!!e,!0)})),n}var r=e.setTimeout,i={},o={VERSION:"2.1.1",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,IMAGE_MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t<n.length;t+=2)e=e.replace(n[t],n[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,""),e},buildUrl:function(e,t){var n="";return o.each(t,function(e,t){n+=(n?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),n&&(e+=(e.indexOf("?")>0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n<f.length;n++)!e&&f[n].status==o.QUEUED?(e=f[n],this.trigger("BeforeUpload",e)&&(e.status=o.UPLOADING,this.trigger("UploadFile",e))):t++;t==f.length&&(this.state!==o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",f))}}function y(e){e.percent=e.size>0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e<f.length;e++)t=f[e],t.size!==n?(d.size+=t.origSize,d.loaded+=t.loaded*t.origSize/t.size):d.size=n,t.status==o.DONE?d.uploaded++:t.status==o.FAILED?d.failed++:d.queued++;d.size===n?d.percent=f.length>0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded",C),this.bind("CancelUpload",M),this.bind("BeforeUpload",k),this.bind("UploadFile",L),this.bind("UploadProgress",A),this.bind("StateChanged",O),this.bind("QueueChanged",b),this.bind("Error",D),this.bind("FileUploaded",_),this.bind("Destroy",P)}function x(e,n){var r=this,i=0,s=[],u={accept:e.filters.mime_types,runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,n,r){var i=new t.Image;try{i.onload=function(){i.downsize(n.width,n.height,n.crop,n.preserve_headers)},i.onresize=function(){r(this.getAsBlob(e.type,n.quality)),this.destroy()},i.onerror=function(){r(e)},i.load(e)}catch(s){r(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t;break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){[].push.apply(f,t),e.trigger("QueueChanged"),e.refresh()}function k(e,t){if(a.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function L(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g,y;if(n.status==o.DONE||n.status==o.FAILED||e.state==o.STOPPED)return;g={name:n.target_name||n.name},s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y<c.size?(d.destroy(),f+=y,n.loaded=Math.min(f,c.size),e.trigger("ChunkUploaded",n,{offset:n.loaded,total:c.size,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}),t.Env.browser==="Android Browser"&&e.trigger("UploadProgress",n)):n.loaded=n.size,d=v=null,!f||f>=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(g.name=n.target_name||n.name,m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s*Math.floor(n.loaded/s)),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function A(e,t){y(t)}function O(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function M(){m&&m.abort()}function _(e){b(),r(function(){g.call(e)},1)}function D(e,t){t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function P(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)});if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}S.call(this),x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function l(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function c(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!f)return!1;e.ruid=f,e.connectRuntime(f)}c(new o.File(e))}else e instanceof t.Blob?(c(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){l(e,function(n){n||(a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?c(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,c):i==="array"&&(n=null,t.each(e,c))}var s=this,u=[],a=[],f;f=w(),c(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(i=!0,this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),this.trigger("QueueChanged"),this.refresh(),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie);
products/photocrati_nextgen/modules/nextgen_addgallery_page/static/plupload-2.1.1/plupload.min.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Plupload - multi-runtime File Uploader
3
+ * v2.1.1
4
+ *
5
+ * Copyright 2013, Moxiecode Systems AB
6
+ * Released under GPL License.
7
+ *
8
+ * License: http://www.plupload.com/license
9
+ * Contributing: http://www.plupload.com/contributing
10
+ *
11
+ * Date: 2014-01-16
12
+ */
13
+ ;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};return typeof t=="string"?o.each(t.split(/\s*,\s*/),function(e){r(e,!0)}):typeof t=="object"?o.each(t,function(e,t){r(t,e)}):t===!0&&(e.multipart||(n.send_binary_string=!0),e.chunk_size>0&&(n.slice_blob=!0),e.resize.enabled&&(n.send_binary_string=!0),o.each(e,function(e,t){r(t,!!e,!0)})),n}var r=e.setTimeout,i={},o={VERSION:"2.1.1",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,IMAGE_MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t<n.length;t+=2)e=e.replace(n[t],n[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,""),e},buildUrl:function(e,t){var n="";return o.each(t,function(e,t){n+=(n?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),n&&(e+=(e.indexOf("?")>0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n<f.length;n++)!e&&f[n].status==o.QUEUED?(e=f[n],this.trigger("BeforeUpload",e)&&(e.status=o.UPLOADING,this.trigger("UploadFile",e))):t++;t==f.length&&(this.state!==o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",f))}}function y(e){e.percent=e.size>0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e<f.length;e++)t=f[e],t.size!==n?(d.size+=t.origSize,d.loaded+=t.loaded*t.origSize/t.size):d.size=n,t.status==o.DONE?d.uploaded++:t.status==o.FAILED?d.failed++:d.queued++;d.size===n?d.percent=f.length>0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded",C),this.bind("CancelUpload",M),this.bind("BeforeUpload",k),this.bind("UploadFile",L),this.bind("UploadProgress",A),this.bind("StateChanged",O),this.bind("QueueChanged",b),this.bind("Error",D),this.bind("FileUploaded",_),this.bind("Destroy",P)}function x(e,n){var r=this,i=0,s=[],u={accept:e.filters.mime_types,runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,n,r){var i=new t.Image;try{i.onload=function(){i.downsize(n.width,n.height,n.crop,n.preserve_headers)},i.onresize=function(){r(this.getAsBlob(e.type,n.quality)),this.destroy()},i.onerror=function(){r(e)},i.load(e)}catch(s){r(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t;break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){[].push.apply(f,t),e.trigger("QueueChanged"),e.refresh()}function k(e,t){if(a.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function L(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g,y;if(n.status==o.DONE||n.status==o.FAILED||e.state==o.STOPPED)return;g={name:n.target_name||n.name},s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y<c.size?(d.destroy(),f+=y,n.loaded=Math.min(f,c.size),e.trigger("ChunkUploaded",n,{offset:n.loaded,total:c.size,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}),t.Env.browser==="Android Browser"&&e.trigger("UploadProgress",n)):n.loaded=n.size,d=v=null,!f||f>=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(g.name=n.target_name||n.name,m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s*Math.floor(n.loaded/s)),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function A(e,t){y(t)}function O(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function M(){m&&m.abort()}function _(e){b(),r(function(){g.call(e)},1)}function D(e,t){t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function P(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)});if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}S.call(this),x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function l(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function c(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!f)return!1;e.ruid=f,e.connectRuntime(f)}c(new o.File(e))}else e instanceof t.Blob?(c(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){l(e,function(n){n||(a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?c(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,c):i==="array"&&(n=null,t.each(e,c))}var s=this,u=[],a=[],f;f=w(),c(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(i=!0,this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),this.trigger("QueueChanged"),this.refresh(),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie);
products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/import_folder.php CHANGED
@@ -2,6 +2,7 @@
2
  <div id="file_browser">
3
  </div>
4
  <p>
 
5
  <input type="button" id="import_button" name="import_folder" value="Import Folder" class="button-primary"/>
6
  </p>
7
  <script type="text/javascript">
@@ -43,19 +44,19 @@
43
  // Start importing process
44
  var post_params = {
45
  action: 'import_folder',
46
- folder: selected_folder
 
47
  };
48
  $.post(photocrati_ajax.url, post_params, function(response){
49
  if (typeof(response) != 'object') response = JSON.parse(response);
50
  if (typeof(response.error) == 'string') {
51
- progress_bar.set("Error occurred");
52
- alert(response.error);
53
  }
54
  else {
55
  progress_bar.set('Done! Successfully imported '+response.image_ids.length+' images.');
56
  }
57
- progress_bar.close();
58
  });
59
  })
60
  });
61
- </script>
2
  <div id="file_browser">
3
  </div>
4
  <p>
5
+ <input type="checkbox" id="import_keep_location" name="keep_location" value="on" /> <label for="import_keep_location"> <?php esc_html_e('Keep images in original location.', 'nggallery'); ?> <span style="font-size: 85%"><?php esc_html_e('Caution: If you keep images in the original folder and later delete the gallery, the images in that folder might be deleted depending on your settings.', 'nggallery'); ?></span></label><br/><br/>
6
  <input type="button" id="import_button" name="import_folder" value="Import Folder" class="button-primary"/>
7
  </p>
8
  <script type="text/javascript">
44
  // Start importing process
45
  var post_params = {
46
  action: 'import_folder',
47
+ folder: selected_folder,
48
+ keep_location: $('#import_keep_location').is(":checked") ? 'on' : 'off'
49
  };
50
  $.post(photocrati_ajax.url, post_params, function(response){
51
  if (typeof(response) != 'object') response = JSON.parse(response);
52
  if (typeof(response.error) == 'string') {
53
+ progress_bar.set(response.error);
 
54
  }
55
  else {
56
  progress_bar.set('Done! Successfully imported '+response.image_ids.length+' images.');
57
  }
58
+ progress_bar.close(2000);
59
  });
60
  })
61
  });
62
+ </script>
products/photocrati_nextgen/modules/nextgen_addgallery_page/templates/upload_images.php CHANGED
@@ -13,19 +13,16 @@
13
  <p>You browser doesn't have Flash, Silverlight, HTML5, or HTML4 support.</p>
14
  </div>
15
  <script type="text/javascript">
16
- (function($){
17
-
18
- // Listen for events emitted in other frames
19
- if (window.Frame_Event_Publisher) {
20
-
21
- // If a gallery has been deleted, remove it from the drop-downs of available galleries
22
- Frame_Event_Publisher.listen_for('attach_to_post:manage_galleries', function() {
23
- window.location.href = window.location.href;
24
- });
25
- }
26
 
27
- $(window).on('lazy_resources_loaded', function(){
28
- $(function(){
 
 
 
 
 
29
  // Show the page content
30
  $('#ngg_page_content').css('visibility', 'visible');
31
 
@@ -159,11 +156,21 @@
159
 
160
  // Display message/notification
161
  if (up.state == plupload.STOPPED) {
162
- $.gritter.add({
163
- title: "Upload complete",
164
- text: msg,
165
- sticky: true
166
- });
 
 
 
 
 
 
 
 
 
 
167
  setTimeout(function(){
168
  reinit_plupload(up);
169
  }, 3000);
@@ -187,38 +194,58 @@
187
  return;
188
  }
189
  }
190
- window.uploaded_image_ids = window.uploaded_image_ids.concat(response.image_ids);
191
- up.settings.url = window.set_plupload_url(response.gallery_id, $gallery_name.val());
192
-
193
- // If we created a new gallery, ensure it's now in the drop-down list, and select it
194
- if ($gallery_id.find('option[value="'+response.gallery_id+'"]').length == 0) {
195
- var option = $('<option/>').attr('value', response.gallery_id).text(response.gallery_name);
196
- $gallery_id.append(option);
197
- $gallery_id.val(response.gallery_id);
198
- option.attr('selected', 'selected');
199
- }
200
-
201
- // our Frame-Event-Publisher hooks onto the jQuery ajaxComplete action which plupload
202
- // of course does not honor. Tie them together here..
203
- if (window.Frame_Event_Publisher) {
204
- $.post(photocrati_ajax.url, {'action': 'cookie_dump'}, function(){
205
- window.Frame_Event_Publisher.find_parent(window).broadcast();
206
  });
207
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  },
209
 
210
  Error: function(up, args){
211
- if (typeof(window.console) != 'undefined') console.log(args);
 
 
212
  }
213
  };
214
  $("#uploader").pluploadQueue(plupload_options);
215
  var uploader = $('#uploader').pluploadQueue();
216
  uploader.refresh();
 
217
 
218
  };
219
 
220
  window.init_plupload();
221
  });
222
- });
223
  })(jQuery);
224
  </script>
13
  <p>You browser doesn't have Flash, Silverlight, HTML5, or HTML4 support.</p>
14
  </div>
15
  <script type="text/javascript">
16
+ // Listen for events emitted in other frames
17
+ if (window.Frame_Event_Publisher) {
 
 
 
 
 
 
 
 
18
 
19
+ // If a gallery has been deleted, remove it from the drop-downs of available galleries
20
+ Frame_Event_Publisher.listen_for('attach_to_post:manage_galleries', function() {
21
+ window.location.href = window.location.href;
22
+ });
23
+ }
24
+ (function($){
25
+ $(function(){
26
  // Show the page content
27
  $('#ngg_page_content').css('visibility', 'visible');
28
 
156
 
157
  // Display message/notification
158
  if (up.state == plupload.STOPPED) {
159
+ if (typeof(up.error_msg) != 'undefined') {
160
+ $.gritter.add({
161
+ title: up.error_msg,
162
+ text: msg,
163
+ sticky: true
164
+ });
165
+ }
166
+ else {
167
+ $.gritter.add({
168
+ title: "Upload complete",
169
+ text: msg,
170
+ sticky: true
171
+ });
172
+ }
173
+
174
  setTimeout(function(){
175
  reinit_plupload(up);
176
  }, 3000);
194
  return;
195
  }
196
  }
197
+ if(typeof(response.error) != 'undefined') {
198
+ up.trigger('Error', {
199
+ code: plupload.IO_ERROR,
200
+ msg: response.error,
201
+ details: response,
202
+ file: file
 
 
 
 
 
 
 
 
 
 
203
  });
204
+ }
205
+ else {
206
+ window.uploaded_image_ids = window.uploaded_image_ids.concat(response.image_ids);
207
+ up.settings.url = window.set_plupload_url(response.gallery_id, $gallery_name.val());
208
+
209
+ // If we created a new gallery, ensure it's now in the drop-down list, and select it
210
+ if ($gallery_id.find('option[value="'+response.gallery_id+'"]').length == 0) {
211
+ var option = $('<option/>').attr('value', response.gallery_id).html(response.gallery_name);
212
+ $gallery_id.append(option);
213
+ $gallery_id.val(response.gallery_id);
214
+ option.attr('selected', 'selected');
215
+ }
216
+
217
+ // our Frame-Event-Publisher hooks onto the jQuery ajaxComplete action which plupload
218
+ // of course does not honor. Tie them together here..
219
+ if (window.Frame_Event_Publisher) {
220
+ $.post(photocrati_ajax.url, {'action': 'cookie_dump'}, function(response){
221
+ if (typeof(response) != 'object') response = JSON.parse(response);
222
+ var events = {};
223
+ for (var name in response.cookies) {
224
+ if (name.indexOf('X-Frame-Events') !== -1) {
225
+ var event_data = JSON.parse(response.cookies[name]);
226
+ events[name] = event_data;
227
+ }
228
+ }
229
+ window.Frame_Event_Publisher.broadcast(events)
230
+ });
231
+ }
232
+ }
233
  },
234
 
235
  Error: function(up, args){
236
+ if (typeof(up.error_msg) == 'undefined') {
237
+ up.error_msg = args.msg;
238
+ }{}
239
  }
240
  };
241
  $("#uploader").pluploadQueue(plupload_options);
242
  var uploader = $('#uploader').pluploadQueue();
243
  uploader.refresh();
244
+ window.Frame_Event_Publisher.broadcast();
245
 
246
  };
247
 
248
  window.init_plupload();
249
  });
 
250
  })(jQuery);
251
  </script>
products/photocrati_nextgen/modules/nextgen_admin/adapter.nextgen_admin_default_pages.php CHANGED
@@ -4,8 +4,10 @@ class A_NextGen_Admin_Default_Pages extends Mixin
4
  {
5
  function initialize()
6
  {
7
- $this->object->add(
8
- NEXTGEN_FS_ACCESS_SLUG, 'A_Fs_Access_Page', NGGFOLDER, FALSE
9
- );
 
 
10
  }
11
  }
4
  {
5
  function initialize()
6
  {
7
+ $this->object->add(NGG_FS_ACCESS_SLUG, array(
8
+ 'adapter' => 'A_Fs_Access_Page',
9
+ 'parent' => NGGFOLDER,
10
+ 'add_menu' => FALSE
11
+ ));
12
  }
13
  }
products/photocrati_nextgen/modules/nextgen_admin/class.form.php CHANGED
@@ -3,6 +3,7 @@
3
  class C_Form extends C_MVC_Controller
4
  {
5
  static $_instances = array();
 
6
 
7
  /**
8
  * Gets an instance of a form
@@ -66,7 +67,8 @@ class Mixin_Form_Instance_Methods extends Mixin
66
  */
67
  function save_action($attributes=array())
68
  {
69
- if ($this->object->has_method('get_model')) {
 
70
  return $this->object->get_model()->save($attributes);
71
  }
72
  else return TRUE;
@@ -94,6 +96,11 @@ class Mixin_Form_Instance_Methods extends Mixin
94
  TRUE
95
  );
96
  }
 
 
 
 
 
97
  }
98
 
99
  /**
@@ -210,14 +217,26 @@ class Mixin_Form_Field_Generators extends Mixin
210
  True
211
  );
212
  }
 
 
 
 
 
 
 
 
 
 
213
 
214
  function _render_thumbnail_override_settings_field($display_type)
215
  {
 
 
216
  $override_field = $this->_render_radio_field(
217
  $display_type,
218
  'override_thumbnail_settings',
219
  'Override thumbnail settings',
220
- $display_type->settings['override_thumbnail_settings'],
221
  "This does not affect existing thumbnails; overriding the thumbnail settings will create an additional set of thumbnails. To change the size of existing thumbnails please visit 'Manage Galleries' and choose 'Create new thumbnails' for all images in the gallery."
222
  );
223
 
@@ -227,9 +246,9 @@ class Mixin_Form_Field_Generators extends Mixin
227
  'display_type_name' => $display_type->name,
228
  'name' => 'thumbnail_dimensions',
229
  'label'=> _('Thumbnail dimensions'),
230
- 'thumbnail_width' => $display_type->settings['thumbnail_width'],
231
- 'thumbnail_height'=> $display_type->settings['thumbnail_height'],
232
- 'hidden' => empty($display_type->settings['override_thumbnail_settings']) ? 'hidden' : '',
233
  'text' => ''
234
  ),
235
  TRUE
@@ -242,27 +261,27 @@ class Mixin_Form_Field_Generators extends Mixin
242
  'thumbnail_quality',
243
  'Thumbnail quality',
244
  $qualities,
245
- $display_type->settings['thumbnail_quality'],
246
  '',
247
- empty($display_type->settings['override_thumbnail_settings']) ? TRUE : FALSE
248
  );
249
 
250
  $crop_field = $this->_render_radio_field(
251
  $display_type,
252
  'thumbnail_crop',
253
  'Thumbnail crop',
254
- $display_type->settings['thumbnail_crop'],
255
  '',
256
- empty($display_type->settings['override_thumbnail_settings']) ? TRUE : FALSE
257
  );
258
 
259
  $watermark_field = $this->_render_radio_field(
260
  $display_type,
261
  'thumbnail_watermark',
262
  'Thumbnail watermark',
263
- $display_type->settings['thumbnail_watermark'],
264
  '',
265
- empty($display_type->settings['override_thumbnail_settings']) ? TRUE : FALSE
266
  );
267
 
268
  $everything = $override_field . $dimensions_field . $quality_field . $crop_field . $watermark_field;
@@ -279,11 +298,13 @@ class Mixin_Form_Field_Generators extends Mixin
279
  */
280
  function _render_image_override_settings_field($display_type)
281
  {
 
 
282
  $override_field = $this->_render_radio_field(
283
  $display_type,
284
  'override_image_settings',
285
  'Override image settings',
286
- $display_type->settings['override_image_settings'],
287
  'Overriding the image settings will create an additional set of images'
288
  );
289
 
@@ -296,7 +317,7 @@ class Mixin_Form_Field_Generators extends Mixin
296
  $qualities,
297
  $display_type->settings['image_quality'],
298
  '',
299
- empty($display_type->settings['override_image_settings']) ? TRUE : FALSE
300
  );
301
 
302
  $crop_field = $this->_render_radio_field(
@@ -305,7 +326,7 @@ class Mixin_Form_Field_Generators extends Mixin
305
  'Image crop',
306
  $display_type->settings['image_crop'],
307
  '',
308
- empty($display_type->settings['override_image_settings']) ? TRUE : FALSE
309
  );
310
 
311
  $watermark_field = $this->_render_radio_field(
@@ -314,7 +335,7 @@ class Mixin_Form_Field_Generators extends Mixin
314
  'Image watermark',
315
  $display_type->settings['image_watermark'],
316
  '',
317
- empty($display_type->settings['override_image_settings']) ? TRUE : FALSE
318
  );
319
 
320
  $everything = $override_field . $quality_field . $crop_field . $watermark_field;
3
  class C_Form extends C_MVC_Controller
4
  {
5
  static $_instances = array();
6
+ var $page = NULL;
7
 
8
  /**
9
  * Gets an instance of a form
67
  */
68
  function save_action($attributes=array())
69
  {
70
+ if (!$attributes) $attributes = array();
71
+ if ($this->object->has_method('get_model') && $this->object->get_model()) {
72
  return $this->object->get_model()->save($attributes);
73
  }
74
  else return TRUE;
96
  TRUE
97
  );
98
  }
99
+
100
+ function get_model()
101
+ {
102
+ return $this->page->has_method('get_model') ? $this->page->get_model() : NULL;
103
+ }
104
  }
105
 
106
  /**
217
  True
218
  );
219
  }
220
+
221
+ function _render_ajax_pagination_field($display_type)
222
+ {
223
+ return $this->object->_render_radio_field(
224
+ $display_type,
225
+ 'ajax_pagination',
226
+ _('Enable AJAX pagination'),
227
+ isset($display_type->settings['ajax_pagination']) ? $display_type->settings['ajax_pagination'] : FALSE
228
+ );
229
+ }
230
 
231
  function _render_thumbnail_override_settings_field($display_type)
232
  {
233
+ $hidden = !(isset($display_type->settings['override_thumbnail_settings']) ? $display_type->settings['override_thumbnail_settings'] : FALSE);
234
+
235
  $override_field = $this->_render_radio_field(
236
  $display_type,
237
  'override_thumbnail_settings',
238
  'Override thumbnail settings',
239
+ isset($display_type->settings['override_thumbnail_settings']) ? $display_type->settings['override_thumbnail_settings'] : FALSE,
240
  "This does not affect existing thumbnails; overriding the thumbnail settings will create an additional set of thumbnails. To change the size of existing thumbnails please visit 'Manage Galleries' and choose 'Create new thumbnails' for all images in the gallery."
241
  );
242
 
246
  'display_type_name' => $display_type->name,
247
  'name' => 'thumbnail_dimensions',
248
  'label'=> _('Thumbnail dimensions'),
249
+ 'thumbnail_width' => isset($display_type->settings['thumbnail_width']) ? $display_type->settings['thumbnail_width'] : 0,
250
+ 'thumbnail_height'=> isset($display_type->settings['thumbnail_height']) ? $display_type->settings['thumbnail_height'] : 0,
251
+ 'hidden' => $hidden ? 'hidden' : '',
252
  'text' => ''
253
  ),
254
  TRUE
261
  'thumbnail_quality',
262
  'Thumbnail quality',
263
  $qualities,
264
+ isset($display_type->settings['thumbnail_quality']) ? $display_type->settings['thumbnail_quality'] : 100,
265
  '',
266
+ $hidden
267
  );
268
 
269
  $crop_field = $this->_render_radio_field(
270
  $display_type,
271
  'thumbnail_crop',
272
  'Thumbnail crop',
273
+ isset($display_type->settings['thumbnail_crop']) ? $display_type->settings['thumbnail_crop'] : FALSE,
274
  '',
275
+ $hidden
276
  );
277
 
278
  $watermark_field = $this->_render_radio_field(
279
  $display_type,
280
  'thumbnail_watermark',
281
  'Thumbnail watermark',
282
+ isset($display_type->settings['thumbnail_watermark']) ? $display_type->settings['thumbnail_watermark'] : FALSE,
283
  '',
284
+ $hidden
285
  );
286
 
287
  $everything = $override_field . $dimensions_field . $quality_field . $crop_field . $watermark_field;
298
  */
299
  function _render_image_override_settings_field($display_type)
300
  {
301
+ $hidden = !(isset($display_type->settings['override_image_settings']) ? $display_type->settings['override_image_settings'] : FALSE);
302
+
303
  $override_field = $this->_render_radio_field(
304
  $display_type,
305
  'override_image_settings',
306
  'Override image settings',
307
+ isset($display_type->settings['override_image_settings']) ? $display_type->settings['override_image_settings'] : 0,
308
  'Overriding the image settings will create an additional set of images'
309
  );
310
 
317
  $qualities,
318
  $display_type->settings['image_quality'],
319
  '',
320
+ $hidden
321
  );
322
 
323
  $crop_field = $this->_render_radio_field(
326
  'Image crop',
327
  $display_type->settings['image_crop'],
328
  '',
329
+ $hidden
330
  );
331
 
332
  $watermark_field = $this->_render_radio_field(
335
  'Image watermark',
336
  $display_type->settings['image_watermark'],
337
  '',
338
+ $hidden
339
  );
340
 
341
  $everything = $override_field . $quality_field . $crop_field . $watermark_field;
products/photocrati_nextgen/modules/nextgen_admin/class.nextgen_admin_installer.php CHANGED
@@ -2,23 +2,31 @@
2
 
3
  class C_NextGen_Admin_Installer
4
  {
5
- function __construct()
6
- {
7
- $this->settings = C_NextGen_Global_Settings::get_instance();
8
- }
9
-
10
  function install()
11
  {
12
- $registry = C_Component_Registry::get_instance();
13
- $router = $registry->get_utility('I_Router');
14
- $theme_url = $router->get_static_url('photocrati-nextgen_admin#jquery-ui/jquery-ui-1.9.1.custom.css');
15
-
16
- $defaults = array(
17
- 'jquery_ui_theme' => 'jquery-ui-nextgen',
18
- 'jquery_ui_theme_version' => 1.8,
19
- 'jquery_ui_theme_url' => $theme_url
20
- );
 
 
 
 
 
 
21
 
22
- foreach ($defaults as $k=>$v) $this->settings->set_default_value($k, $v);
 
 
 
 
 
 
 
23
  }
24
  }
2
 
3
  class C_NextGen_Admin_Installer
4
  {
 
 
 
 
 
5
  function install()
6
  {
7
+ // In version 0.2 of this module and earlier, the following values
8
+ // were statically set rather than dynamically using a handler. Therefore, we need
9
+ // to delete those static values
10
+ $module_name = 'photocrati-nextgen_admin';
11
+ $settings = C_NextGen_Settings::get_instance();
12
+ $modules = $settings->get('pope_module_list', array());
13
+ $cleanup = FALSE;
14
+ foreach ($modules as $module) {
15
+ if (strpos($module, $module_name) !== FALSE) {
16
+ if (version_compare(array_pop(explode('|', $module)), '0.3') == -1) {
17
+ $cleanup = TRUE;
18
+ }
19
+ break;
20
+ }
21
+ }
22
 
23
+ if ($cleanup) {
24
+ $keys = array(
25
+ 'jquery_ui_theme',
26
+ 'jquery_ui_theme_version',
27
+ 'jquery_ui_theme_url'
28
+ );
29
+ foreach ($keys as $key) $settings->delete($key);
30
+ }
31
  }
32
  }
products/photocrati_nextgen/modules/nextgen_admin/class.nextgen_admin_option_handler.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class C_NextGen_Admin_Option_Handler
4
+ {
5
+ function get_router()
6
+ {
7
+ return C_Component_Registry::get_instance()->get_utility('I_Router');
8
+ }
9
+
10
+
11
+ function get($key, $default=NULL)
12
+ {
13
+ $retval = $default;
14
+
15
+ switch ($key) {
16
+ case 'jquery_ui_theme':
17
+ $retval = 'jquery-ui-nextgen';
18
+ break;
19
+ case 'jquery_ui_theme_version':
20
+ $retval = '1.8';
21
+ break;
22
+ case 'jquery_ui_theme_url':
23
+ $retval = $this->get_router()->get_static_url('photocrati-nextgen_admin#jquery-ui/jquery-ui-1.9.1.custom.css');
24
+ break;
25
+ }
26
+
27
+ return $retval;
28
+ }
29
+ }
products/photocrati_nextgen/modules/nextgen_admin/class.nextgen_admin_page_controller.php CHANGED
@@ -82,6 +82,9 @@ class Mixin_NextGen_Admin_Page_Instance_Methods extends Mixin
82
  */
83
  function enqueue_backend_resources()
84
  {
 
 
 
85
  $this->object->enqueue_jquery_ui_theme();
86
  wp_enqueue_script('jquery-ui-accordion');
87
  wp_enqueue_script(
@@ -91,8 +94,8 @@ class Mixin_NextGen_Admin_Page_Instance_Methods extends Mixin
91
  '2.0.7',
92
  TRUE
93
  );
94
- wp_register_script('iris', $this->get_router()->get_url('/wp-admin/js/iris.min.js', FALSE), array('jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch'));
95
- wp_register_script('wp-color-picker', $this->get_router()->get_url('/wp-admin/js/color-picker.js', FALSE), array('iris'));
96
  wp_localize_script('wp-color-picker', 'wpColorPickerL10n', array(
97
  'clear' => __( 'Clear' ),
98
  'defaultString' => __( 'Default' ),
@@ -113,11 +116,20 @@ class Mixin_NextGen_Admin_Page_Instance_Methods extends Mixin
113
  // Ensure select2
114
  wp_enqueue_style('select2');
115
  wp_enqueue_script('select2');
 
 
 
 
 
 
 
 
 
116
  }
117
 
118
  function enqueue_jquery_ui_theme()
119
  {
120
- $settings = C_NextGen_Global_Settings::get_instance();
121
  wp_enqueue_style(
122
  $settings->jquery_ui_theme,
123
  is_ssl() ?
@@ -162,7 +174,6 @@ class Mixin_NextGen_Admin_Page_Instance_Methods extends Mixin
162
  return "Saved successfully";
163
  }
164
 
165
-
166
  /**
167
  * Returns an accordion tab, encapsulating the form
168
  * @param I_Form $form
@@ -183,7 +194,7 @@ class Mixin_NextGen_Admin_Page_Instance_Methods extends Mixin
183
  function get_forms()
184
  {
185
  $forms = array();
186
- $form_manager = $this->get_registry()->get_utility('I_Form_Manager');
187
  foreach ($form_manager->get_forms($this->object->get_form_type()) as $form) {
188
  $forms[] = $this->get_registry()->get_utility('I_Form', $form);
189
  }
@@ -229,13 +240,22 @@ class Mixin_NextGen_Admin_Page_Instance_Methods extends Mixin
229
  // request
230
  $tabs = array();
231
  $errors = array();
232
- $success = $this->object->is_post_request() ?
233
- $this->object->get_success_message() : '';
 
 
 
 
 
 
 
 
234
 
 
235
  foreach ($this->object->get_forms() as $form) {
 
236
  $form->enqueue_static_resources();
237
  if ($this->object->is_post_request()) {
238
- $action = $this->object->_get_action();
239
  if ($form->has_method($action)) {
240
  $form->$action($this->object->param($form->context));
241
  }
@@ -260,7 +280,8 @@ class Mixin_NextGen_Admin_Page_Instance_Methods extends Mixin
260
  'errors' => $errors,
261
  'success' => $success,
262
  'form_header' => $token->get_form_html(),
263
- 'show_save_button' => $this->object->show_save_button()
 
264
  ));
265
  }
266
 
82
  */
83
  function enqueue_backend_resources()
84
  {
85
+ $atp = $this->object->get_registry()->get_utility('I_Attach_To_Post_Controller');
86
+
87
+ wp_enqueue_script('jquery');
88
  $this->object->enqueue_jquery_ui_theme();
89
  wp_enqueue_script('jquery-ui-accordion');
90
  wp_enqueue_script(
94
  '2.0.7',
95
  TRUE
96
  );
97
+ wp_register_script('iris', $this->get_router()->get_url('/wp-admin/js/iris.min.js', FALSE, TRUE), array('jquery-ui-draggable', 'jquery-ui-slider', 'jquery-touch-punch'));
98
+ wp_register_script('wp-color-picker', $this->get_router()->get_url('/wp-admin/js/color-picker.js', FALSE, TRUE), array('iris'));
99
  wp_localize_script('wp-color-picker', 'wpColorPickerL10n', array(
100
  'clear' => __( 'Clear' ),
101
  'defaultString' => __( 'Default' ),
116
  // Ensure select2
117
  wp_enqueue_style('select2');
118
  wp_enqueue_script('select2');
119
+
120
+ if ($atp != null) {
121
+ $atp->mark_script('jquery-ui-accordion');
122
+ $atp->mark_script('nextgen_display_settings_page_placeholder_stub');
123
+ $atp->mark_script('iris');
124
+ $atp->mark_script('wp-color-picker');
125
+ $atp->mark_script('nextgen_admin_page');
126
+ $atp->mark_script('select2');
127
+ }
128
  }
129
 
130
  function enqueue_jquery_ui_theme()
131
  {
132
+ $settings = C_NextGen_Settings::get_instance();
133
  wp_enqueue_style(
134
  $settings->jquery_ui_theme,
135
  is_ssl() ?
174
  return "Saved successfully";
175
  }
176
 
 
177
  /**
178
  * Returns an accordion tab, encapsulating the form
179
  * @param I_Form $form
194
  function get_forms()
195
  {
196
  $forms = array();
197
+ $form_manager = C_Form_Manager::get_instance();
198
  foreach ($form_manager->get_forms($this->object->get_form_type()) as $form) {
199
  $forms[] = $this->get_registry()->get_utility('I_Form', $form);
200
  }
240
  // request
241
  $tabs = array();
242
  $errors = array();
243
+ $action = $this->object->_get_action();
244
+ $success = $this->param('message');
245
+ if ($success) $success = $this->object->get_success_message();
246
+ else $success = $this->object->is_post_request() ?
247
+ $this->object->get_success_message() : '';
248
+
249
+ // First, process the Post request
250
+ if ($this->object->is_post_request() && $this->has_method($action)) {
251
+ $this->object->$action($this->object->param($this->context));
252
+ }
253
 
254
+ // Display and process all forms
255
  foreach ($this->object->get_forms() as $form) {
256
+ $form->page = $this->object;
257
  $form->enqueue_static_resources();
258
  if ($this->object->is_post_request()) {
 
259
  if ($form->has_method($action)) {
260
  $form->$action($this->object->param($form->context));
261
  }
280
  'errors' => $errors,
281
  'success' => $success,
282
  'form_header' => $token->get_form_html(),
283
+ 'show_save_button' => $this->object->show_save_button(),
284
+ 'model' => $this->object->has_method('get_model') ? $this->get_model() : NULL
285
  ));
286
  }
287
 
products/photocrati_nextgen/modules/nextgen_admin/class.page_manager.php CHANGED
@@ -33,14 +33,15 @@ class C_Page_Manager extends C_Component
33
 
34
  class Mixin_Page_Manager extends Mixin
35
  {
36
- function add($slug, $adapter, $parent=NULL, $add_menu=TRUE, $before = NULL)
37
  {
38
- $this->object->_pages[$slug] = array(
39
- 'adapter' => $adapter,
40
- 'parent' => $parent,
41
- 'add_menu' => $add_menu,
42
- 'before' => $before
43
- );
 
44
  }
45
 
46
  function move_page($slug, $other_slug, $after = false)
@@ -70,7 +71,7 @@ class Mixin_Page_Manager extends Mixin
70
  }
71
  }
72
 
73
- function remove_page($slug)
74
  {
75
  unset($this->object->_pages[$slug]);
76
  }
@@ -85,23 +86,56 @@ class Mixin_Page_Manager extends Mixin
85
  $registry = $this->get_registry();
86
  $controllers = array();
87
  foreach ($this->object->_pages as $slug => $properties) {
88
- $registry->add_adapter(
89
- 'I_NextGen_Admin_Page',
90
- $properties['adapter'],
91
- $slug
92
- );
93
- $controllers[$slug] = $registry->get_utility(
94
- 'I_NextGen_Admin_Page',
95
- $slug
96
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  if ($properties['add_menu']) {
 
98
  add_submenu_page(
99
  $properties['parent'],
100
- $controllers[$slug]->get_page_title(),
101
- $controllers[$slug]->get_page_heading(),
102
- $controllers[$slug]->get_required_permission(),
103
  $slug,
104
- array(&$controllers[$slug], 'index_action')
105
  );
106
 
107
  if ($properties['before']) {
33
 
34
  class Mixin_Page_Manager extends Mixin
35
  {
36
+ function add($slug, $properties=array())
37
  {
38
+ if (!isset($properties['adapter'])) $properties['adapter'] = NULL;
39
+ if (!isset($properties['parent'])) $properties['parent'] = NULL;
40
+ if (!isset($properties['add_menu']))$properties['add_menu'] = TRUE;
41
+ if (!isset($properties['before'])) $properties['before'] = NULL;
42
+ if (!isset($properties['url'])) $properties['url'] = NULL;
43
+
44
+ $this->object->_pages[$slug] = $properties;
45
  }
46
 
47
  function move_page($slug, $other_slug, $after = false)
71
  }
72
  }
73
 
74
+ function remove($slug)
75
  {
76
  unset($this->object->_pages[$slug]);
77
  }
86
  $registry = $this->get_registry();
87
  $controllers = array();
88
  foreach ($this->object->_pages as $slug => $properties) {
89
+
90
+ $page_title = "Unnamed Page";
91
+ $menu_title = "Unnamed Page";
92
+ $permission = NULL;
93
+ $callback = NULL;
94
+
95
+ // There's two type of pages we can have. Some are powered by our controllers, and others
96
+ // are powered by WordPress, such as a custom post type page.
97
+
98
+ // Is this powered by a controller? If so, we expect an adapter
99
+ if ($properties['adapter']) {
100
+
101
+ // Register the adapter and instantiate the controller
102
+ $registry->add_adapter(
103
+ 'I_NextGen_Admin_Page',
104
+ $properties['adapter'],
105
+ $slug
106
+ );
107
+ $controllers[$slug] = $registry->get_utility(
108
+ 'I_NextGen_Admin_Page',
109
+ $slug
110
+ );
111
+
112
+ $menu_title = $controllers[$slug]->get_page_heading();
113
+ $page_title = $controllers[$slug]->get_page_title();
114
+ $permission = $controllers[$slug]->get_required_permission();
115
+ $callback = array(&$controllers[$slug], 'index_action');
116
+ }
117
+
118
+ // Is this page powered by another url, such as one that WordPres provides?
119
+ elseif ($properties['url']) {
120
+ $slug = $properties['url'];
121
+ if (isset($properties['menu_title'])) {
122
+ $menu_title = $properties['menu_title'];
123
+ }
124
+ if (isset($properties['permission'])) {
125
+ $permission = $properties['permission'];
126
+ }
127
+ }
128
+
129
+ // Are we to add a menu?
130
  if ($properties['add_menu']) {
131
+
132
  add_submenu_page(
133
  $properties['parent'],
134
+ $page_title,
135
+ $menu_title,
136
+ $permission,
137
  $slug,
138
+ $callback
139
  );
140
 
141
  if ($properties['before']) {
products/photocrati_nextgen/modules/nextgen_admin/module.nextgen_admin.php CHANGED
@@ -6,7 +6,7 @@
6
  }
7
  ***/
8
 
9
- define('NEXTGEN_FS_ACCESS_SLUG', 'ngg_fs_access');
10
 
11
  class M_NextGen_Admin extends C_Base_Module
12
  {
@@ -19,7 +19,7 @@ class M_NextGen_Admin extends C_Base_Module
19
  'photocrati-nextgen_admin',
20
  'NextGEN Administration',
21
  'Provides a framework for adding Administration pages',
22
- '0.1',
23
  'http://www.nextgen-gallery.com',
24
  'Photocrati Media',
25
  'http://www.photocrati.com'
@@ -27,6 +27,13 @@ class M_NextGen_Admin extends C_Base_Module
27
 
28
  include_once('class.nextgen_admin_installer.php');
29
  C_Photocrati_Installer::add_handler($this->module_id, 'C_NextGen_Admin_Installer');
 
 
 
 
 
 
 
30
  }
31
 
32
  /**
@@ -85,13 +92,12 @@ class M_NextGen_Admin extends C_Base_Module
85
  function _register_hooks()
86
  {
87
  // Register scripts
88
- add_action('init', array(&$this, 'register_scripts'));
89
 
90
  // Provides menu options for managing NextGEN Settings
91
  add_action('admin_menu', array(&$this, 'add_menu_pages'), 999);
92
  }
93
 
94
-
95
  function register_scripts()
96
  {
97
  $router = $this->get_registry()->get_utility('I_Router');
@@ -102,8 +108,8 @@ class M_NextGen_Admin extends C_Base_Module
102
  wp_register_style('select2', $router->get_static_url('photocrati-nextgen_admin#select2/select2.css'));
103
  wp_register_script('select2', $router->get_static_url('photocrati-nextgen_admin#select2/select2.modded.js'));
104
 
105
- $match = preg_quote("/wp-admin/post.php", "#");
106
- if (preg_match("#{$match}#", $_SERVER['REQUEST_URI'])) {
107
  wp_enqueue_script('ngg_progressbar');
108
  wp_enqueue_style('ngg_progressbar');
109
  }
6
  }
7
  ***/
8
 
9
+ define('NGG_FS_ACCESS_SLUG', 'ngg_fs_access');
10
 
11
  class M_NextGen_Admin extends C_Base_Module
12
  {
19
  'photocrati-nextgen_admin',
20
  'NextGEN Administration',
21
  'Provides a framework for adding Administration pages',
22
+ '0.7',
23
  'http://www.nextgen-gallery.com',
24
  'Photocrati Media',
25
  'http://www.photocrati.com'
27
 
28
  include_once('class.nextgen_admin_installer.php');
29
  C_Photocrati_Installer::add_handler($this->module_id, 'C_NextGen_Admin_Installer');
30
+
31
+ include_once('class.nextgen_admin_option_handler.php');
32
+ C_NextGen_Settings::add_option_handler('C_NextGen_Admin_Option_Handler', array(
33
+ 'jquery_ui_theme',
34
+ 'jquery_ui_theme_version',
35
+ 'jquery_ui_theme_url'
36
+ ));
37
  }
38
 
39
  /**
92
  function _register_hooks()
93
  {
94
  // Register scripts
95
+ add_action('init', array(&$this, 'register_scripts'), 9);
96
 
97
  // Provides menu options for managing NextGEN Settings
98
  add_action('admin_menu', array(&$this, 'add_menu_pages'), 999);
99
  }
100
 
 
101
  function register_scripts()
102
  {
103
  $router = $this->get_registry()->get_utility('I_Router');
108
  wp_register_style('select2', $router->get_static_url('photocrati-nextgen_admin#select2/select2.css'));
109
  wp_register_script('select2', $router->get_static_url('photocrati-nextgen_admin#select2/select2.modded.js'));
110
 
111
+ if (preg_match("#/wp-admin/post(-new)?.php#", $_SERVER['REQUEST_URI']))
112
+ {
113
  wp_enqueue_script('ngg_progressbar');
114
  wp_enqueue_style('ngg_progressbar');
115
  }
products/photocrati_nextgen/modules/nextgen_admin/static/jquery-ui/jquery-ui-1.9.1.custom.css CHANGED
@@ -1885,3 +1885,8 @@ body .ui-tooltip {
1885
  filter: Alpha(Opacity = 40);
1886
  filter: -\9;
1887
  }
 
 
 
 
 
1885
  filter: Alpha(Opacity = 40);
1886
  filter: -\9;
1887
  }
1888
+
1889
+ /* necessary w/WP 3.8s new admin design */
1890
+ .ui-widget select {
1891
+ height: 2em;
1892
+ }
products/photocrati_nextgen/modules/nextgen_admin/static/nextgen_admin_page.css CHANGED
@@ -35,5 +35,20 @@ label.tooltip {
35
  background-image: url('information.png');
36
  background-repeat: no-repeat;
37
  padding-left: 18px;
38
- padding-bottom: 1px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
35
  background-image: url('information.png');
36
  background-repeat: no-repeat;
37
  padding-left: 18px;
38
+ padding-bottom: 4px;
39
+ }
40
+
41
+ #poststuff .ui-accordion h3 {
42
+ padding-left: 25px;
43
+ }
44
+
45
+ #lightbox_effects_content table tr td:first-child {
46
+ vertical-align: top;
47
+ text-align: right;
48
+ padding-right: 7px;
49
+ padding-top: 5px;
50
+ }
51
+
52
+ #lightbox_effects_content tr {
53
+ height: 28px;
54
  }
products/photocrati_nextgen/modules/nextgen_admin/static/nextgen_admin_page.js CHANGED
@@ -63,11 +63,5 @@ jQuery(function($){
63
  });
64
 
65
  $('input.nextgen_settings_field_colorpicker').wpColorPicker();
66
- });
67
-
68
- (function($){
69
- $(window).on('lazy_resources_loaded', function(){
70
- $('#ngg_page_content').css('visibility', 'visible');
71
- });
72
-
73
- })(jQuery);
63
  });
64
 
65
  $('input.nextgen_settings_field_colorpicker').wpColorPicker();
66
+ $('#ngg_page_content').css('visibility', 'visible');
67
+ });
 
 
 
 
 
 
products/photocrati_nextgen/modules/nextgen_admin/templates/field_generator/nextgen_settings_field_color.php CHANGED
@@ -11,7 +11,6 @@
11
  id='<?php print esc_attr("{$display_type_name}_{$name}"); ?>'
12
  name='<?php print esc_attr("{$display_type_name}[{$name}]"); ?>'
13
  class='<?php print esc_attr("{$display_type_name}_{$name}"); ?> nextgen_settings_field_colorpicker'
14
- value='<?php print esc_attr($value); ?>'
15
- data-default-color='<?php print esc_attr($value); ?>'/>
16
  </td>
17
  </tr>
11
  id='<?php print esc_attr("{$display_type_name}_{$name}"); ?>'
12
  name='<?php print esc_attr("{$display_type_name}[{$name}]"); ?>'
13
  class='<?php print esc_attr("{$display_type_name}_{$name}"); ?> nextgen_settings_field_colorpicker'
14
+ value='<?php print esc_attr($value); ?>'/>
 
15
  </td>
16
  </tr>
products/photocrati_nextgen/modules/nextgen_admin/templates/field_generator/thumbnail_settings.php CHANGED
@@ -16,7 +16,7 @@
16
  $thumbnails_template_name = $display_type_name . '_thumbnail_dimensions';
17
  $thumbnails_template_width_name = $display_type_name . '[thumbnail_width]';
18
  $thumbnails_template_height_name = $display_type_name . '[thumbnail_height]';
19
- include(path_join(NGGALLERY_ABSPATH, implode(DIRECTORY_SEPARATOR, array('admin', 'thumbnails-template.php'))));
20
  ?>
21
  </td>
22
  </tr>
16
  $thumbnails_template_name = $display_type_name . '_thumbnail_dimensions';
17
  $thumbnails_template_width_name = $display_type_name . '[thumbnail_width]';
18
  $thumbnails_template_height_name = $display_type_name . '[thumbnail_height]';
19
+ include(NGGALLERY_ABSPATH . implode(DIRECTORY_SEPARATOR, array('admin', 'thumbnails-template.php')));
20
  ?>
21
  </td>
22
  </tr>
products/photocrati_nextgen/modules/nextgen_admin/templates/nextgen_admin_page.php CHANGED
@@ -10,7 +10,7 @@
10
  <p><?php echo_h($success);?></p>
11
  </div>
12
  <?php endif ?>
13
- <form method="POST" action="<?php echo esc_url($_SERVER['REQUEST_URI'])?>">
14
  <?php if (isset($form_header)): ?>
15
  <?php echo $form_header."\n"; ?>
16
  <?php endif ?>
10
  <p><?php echo_h($success);?></p>
11
  </div>
12
  <?php endif ?>
13
+ <form method="POST" action="<?php echo nextgen_esc_url($_SERVER['REQUEST_URI'])?>">
14
  <?php if (isset($form_header)): ?>
15
  <?php echo $form_header."\n"; ?>
16
  <?php endif ?>
products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album.php CHANGED
@@ -8,8 +8,8 @@ class A_NextGen_Basic_Album extends Mixin
8
  function initialize()
9
  {
10
  $ngglegacy_albums = array(
11
- NEXTGEN_GALLERY_NEXTGEN_BASIC_COMPACT_ALBUM,
12
- NEXTGEN_GALLERY_NEXTGEN_BASIC_EXTENDED_ALBUM
13
  );
14
  if (in_array($this->object->name, $ngglegacy_albums)) {
15
  $this->object->add_pre_hook(
@@ -22,7 +22,7 @@ class A_NextGen_Basic_Album extends Mixin
22
 
23
  function get_order()
24
  {
25
- return NEXTGEN_DISPLAY_PRIORITY_BASE + NEXTGEN_DISPLAY_PRIORITY_STEP;
26
  }
27
  }
28
 
8
  function initialize()
9
  {
10
  $ngglegacy_albums = array(
11
+ NGG_BASIC_COMPACT_ALBUM,
12
+ NGG_BASIC_EXTENDED_ALBUM
13
  );
14
  if (in_array($this->object->name, $ngglegacy_albums)) {
15
  $this->object->add_pre_hook(
22
 
23
  function get_order()
24
  {
25
+ return NGG_DISPLAY_PRIORITY_BASE + NGG_DISPLAY_PRIORITY_STEP;
26
  }
27
  }
28
 
products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album_controller.php CHANGED
@@ -27,19 +27,21 @@ class A_NextGen_Basic_Album_Controller extends Mixin
27
  // /nggallery/album--id/gallery--id
28
 
29
  // Are we to display a gallery?
30
- if (($gallery = $this->param('gallery')))
31
  {
32
  // basic albums only support one per post
33
  if (isset($GLOBALS['nggShowGallery']))
34
  return;
35
  $GLOBALS['nggShowGallery'] = TRUE;
36
 
37
- if (!is_numeric($gallery))
38
- {
39
- $mapper = $this->object->get_registry()->get_utility('I_Gallery_Mapper');
40
- $result = reset($mapper->select()->where(array('slug = %s', $gallery))->limit(1)->run_query());
41
- $gallery = $result->{$result->id_field};
42
- }
 
 
43
 
44
  $renderer = $this->object->get_registry()->get_utility('I_Displayed_Gallery_Renderer');
45
  return $renderer->display_images(
@@ -57,11 +59,14 @@ class A_NextGen_Basic_Album_Controller extends Mixin
57
  else if (($album = $this->param('album'))) {
58
 
59
  // Are we to display a sub-album?
60
- if (!is_numeric($album))
61
  {
62
  $mapper = $this->object->get_registry()->get_utility('I_Album_Mapper');
63
  $result = array_pop($mapper->select()->where(array('slug = %s', $album))->limit(1)->run_query());
64
- $album = $result->{$result->id_field};
 
 
 
 
65
  }
66
  $displayed_gallery->entity_ids = array();
67
  $displayed_gallery->sortorder = array();
@@ -72,7 +77,7 @@ class A_NextGen_Basic_Album_Controller extends Mixin
72
  $this->albums = $displayed_gallery->get_albums();
73
 
74
  // None of the above: Display the main album. Get the settings required for display
75
- $current_page = (int)$this->param('page', 1);
76
  $offset = $display_settings['galleries_per_page'] * ($current_page - 1);
77
  $entities = $displayed_gallery->get_included_entities($display_settings['galleries_per_page'], $offset);
78
 
@@ -97,21 +102,22 @@ class A_NextGen_Basic_Album_Controller extends Mixin
97
 
98
  // Render legacy template
99
  $this->object->add_mixin('Mixin_NextGen_Basic_Templates');
100
- $display_settings = $this->prepare_legacy_album_params($display_settings);
101
  return $this->object->legacy_render($display_settings['template'], $display_settings, $return, 'album');
102
  }
103
  else {
104
  $params = $display_settings;
105
- $albums = $this->prepare_legacy_album_params(array('entities' => $entities));;
 
106
  $params['galleries'] = $albums['galleries'];
107
  $params['displayed_gallery'] = $displayed_gallery;
108
  $params = $this->object->prepare_display_parameters($displayed_gallery, $params);
109
 
110
  switch ($displayed_gallery->display_type) {
111
- case NEXTGEN_GALLERY_NEXTGEN_BASIC_COMPACT_ALBUM:
112
  $template = 'compact';
113
  break;
114
- case NEXTGEN_GALLERY_NEXTGEN_BASIC_EXTENDED_ALBUM:
115
  $template = 'extended';
116
  break;
117
  }
@@ -120,7 +126,7 @@ class A_NextGen_Basic_Album_Controller extends Mixin
120
  }
121
  }
122
  else {
123
- return $this->object->render_partial('photocrati-nextgen_gallery_display#no_images_found');
124
  }
125
  }
126
 
@@ -144,38 +150,59 @@ class A_NextGen_Basic_Album_Controller extends Mixin
144
  }
145
 
146
 
147
- function prepare_legacy_album_params($params)
148
  {
149
  $image_mapper = $this->object->get_registry()->get_utility('I_Image_Mapper');
150
  $storage = $this->object->get_registry()->get_utility('I_Gallery_Storage');
151
  $image_gen = $this->object->get_registry()->get_utility('I_Dynamic_Thumbnails_Manager');
152
 
153
- // legacy templates expect these dimensions
154
- $image_gen_params = array(
155
- 'width' => 91,
156
- 'height' => 68,
157
- 'crop' => TRUE
158
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  // Transform entities
161
- $params['galleries'] = $params['entities'];
162
  unset($params['entities']);
 
163
  foreach ($params['galleries'] as &$gallery) {
164
 
165
  // Get the preview image url
166
- $gallery->previewurl = '';
167
- if ($gallery->previewpic && $gallery->previewpic > 0) {
168
- if (($image = $image_mapper->find(intval($gallery->previewpic)))) {
169
- $gallery->previewurl = $storage->get_image_url($image, $image_gen->get_size_name($image_gen_params));
170
- $gallery->previewname = $gallery->name;
 
 
171
  }
172
  }
173
 
174
  // Get the page link. If the entity is an album, then the url will
175
  // look like /nggallery/album--slug.
176
  $id_field = $gallery->id_field;
177
- if ($gallery->is_album) {
178
- if ($gallery->pageid > 0) $gallery->pagelink = get_post_permalink($gallery->pageid);
 
 
179
  else {
180
  $gallery->pagelink = $this->object->set_param_for(
181
  $this->object->get_routed_url(TRUE),
@@ -188,8 +215,10 @@ class A_NextGen_Basic_Album_Controller extends Mixin
188
  // Otherwise, if it's a gallery then it will look like
189
  // /nggallery/album--slug/gallery--slug
190
  else {
191
- if ($gallery->pageid > 0) $gallery->pagelink = get_post_permalink($gallery->pageid);
192
- else {
 
 
193
  $pagelink = $this->object->get_routed_url(TRUE);
194
  $parent_album = $this->object->get_parent_album_for($gallery->$id_field);
195
  if ($parent_album) {
@@ -199,6 +228,14 @@ class A_NextGen_Basic_Album_Controller extends Mixin
199
  $parent_album->slug
200
  );
201
  }
 
 
 
 
 
 
 
 
202
  $gallery->pagelink = $this->object->set_param_for(
203
  $pagelink,
204
  'gallery',
@@ -207,15 +244,13 @@ class A_NextGen_Basic_Album_Controller extends Mixin
207
  }
208
  }
209
 
210
- // The router by default will generate param segments that look like,
211
- // /gallery--foobar. We need to convert these to the admittingly
212
- // nicer links that ngglegacy uses
213
- if ($gallery->pageid <= 0) $gallery->pagelink = $this->object->prettify_pagelink($gallery->pagelink);
214
-
215
  // Let plugins modify the gallery
216
  $gallery = apply_filters('ngg_album_galleryobject', $gallery);
217
  }
218
 
 
 
 
219
  // Clean up
220
  unset($storage);
221
  unset($image_mapper);
@@ -226,21 +261,6 @@ class A_NextGen_Basic_Album_Controller extends Mixin
226
  }
227
 
228
 
229
- function prettify_pagelink($pagelink)
230
- {
231
- $param_separator = C_NextGen_Global_Settings::get_instance()->get('router_param_separator');
232
- $regex = implode('', array(
233
- '#',
234
- '/(gallery|album)',
235
- preg_quote($param_separator),
236
- '([^/?]+)',
237
- '#'
238
- ));
239
-
240
- return preg_replace($regex, '/\2', $pagelink);
241
- }
242
-
243
-
244
  function _get_js_lib_url()
245
  {
246
  return $this->object->get_static_url('photocrati-nextgen_basic_album#init.js');
@@ -258,8 +278,7 @@ class A_NextGen_Basic_Album_Controller extends Mixin
258
  wp_enqueue_style('nextgen_basic_album_style', $this->object->get_static_url('photocrati-nextgen_basic_album#nextgen_basic_album.css'));
259
  wp_enqueue_script('jquery.dotdotdot', $this->object->get_static_url('photocrati-nextgen_basic_album#jquery.dotdotdot-1.5.7-packed.js'), array('jquery'));
260
 
261
- $cssfile = C_NextGen_Settings::get_instance()->get('CSSFile');
262
- wp_enqueue_style('nggallery', NEXTGEN_GALLERY_NGGLEGACY_MOD_URL.'/css/'.$cssfile);
263
 
264
  }
265
 
27
  // /nggallery/album--id/gallery--id
28
 
29
  // Are we to display a gallery?
30
+ if (($gallery = $gallery_slug = $this->param('gallery')))
31
  {
32
  // basic albums only support one per post
33
  if (isset($GLOBALS['nggShowGallery']))
34
  return;
35
  $GLOBALS['nggShowGallery'] = TRUE;
36
 
37
+ // Try finding the gallery by slug first. If nothing is found, we assume that
38
+ // the user passed in a gallery id instead
39
+ $mapper = $this->object->get_registry()->get_utility('I_Gallery_Mapper');
40
+ $result = reset($mapper->select()->where(array('slug = %s', $gallery))->limit(1)->run_query());
41
+ if ($result) {
42
+ $gallery = $result->{$result->id_field};
43
+ }
44
+
45
 
46
  $renderer = $this->object->get_registry()->get_utility('I_Displayed_Gallery_Renderer');
47
  return $renderer->display_images(
59
  else if (($album = $this->param('album'))) {
60
 
61
  // Are we to display a sub-album?
 
62
  {
63
  $mapper = $this->object->get_registry()->get_utility('I_Album_Mapper');
64
  $result = array_pop($mapper->select()->where(array('slug = %s', $album))->limit(1)->run_query());
65
+ $album_sub = $result ? $result->{$result->id_field} : null;
66
+
67
+ if ($album_sub != null) {
68
+ $album = $album_sub;
69
+ }
70
  }
71
  $displayed_gallery->entity_ids = array();
72
  $displayed_gallery->sortorder = array();
77
  $this->albums = $displayed_gallery->get_albums();
78
 
79
  // None of the above: Display the main album. Get the settings required for display
80
+ $current_page = (int)$this->param('nggpage', 1);
81
  $offset = $display_settings['galleries_per_page'] * ($current_page - 1);
82
  $entities = $displayed_gallery->get_included_entities($display_settings['galleries_per_page'], $offset);
83
 
102
 
103
  // Render legacy template
104
  $this->object->add_mixin('Mixin_NextGen_Basic_Templates');
105
+ $display_settings = $this->prepare_legacy_album_params($displayed_gallery->get_entity(), $display_settings);
106
  return $this->object->legacy_render($display_settings['template'], $display_settings, $return, 'album');
107
  }
108
  else {
109
  $params = $display_settings;
110
+ $albums = $this->prepare_legacy_album_params($displayed_gallery->get_entity(), array('entities' => $entities));;
111
+ $params['image_gen_params'] = $albums['image_gen_params'];
112
  $params['galleries'] = $albums['galleries'];
113
  $params['displayed_gallery'] = $displayed_gallery;
114
  $params = $this->object->prepare_display_parameters($displayed_gallery, $params);
115
 
116
  switch ($displayed_gallery->display_type) {
117
+ case NGG_BASIC_COMPACT_ALBUM:
118
  $template = 'compact';
119
  break;
120
+ case NGG_BASIC_EXTENDED_ALBUM:
121
  $template = 'extended';
122
  break;
123
  }
126
  }
127
  }
128
  else {
129
+ return $this->object->render_partial('photocrati-nextgen_gallery_display#no_images_found', array(), $return);
130
  }
131
  }
132
 
150
  }
151
 
152
 
153
+ function prepare_legacy_album_params($displayed_gallery, $params)
154
  {
155
  $image_mapper = $this->object->get_registry()->get_utility('I_Image_Mapper');
156
  $storage = $this->object->get_registry()->get_utility('I_Gallery_Storage');
157
  $image_gen = $this->object->get_registry()->get_utility('I_Dynamic_Thumbnails_Manager');
158
 
159
+ if (empty($displayed_gallery->display_settings['override_thumbnail_settings']))
160
+ {
161
+ // legacy templates expect these dimensions
162
+ $image_gen_params = array(
163
+ 'width' => 91,
164
+ 'height' => 68,
165
+ 'crop' => TRUE
166
+ );
167
+ }
168
+ else {
169
+ // use settings requested by user
170
+ $image_gen_params = array(
171
+ 'width' => $displayed_gallery->display_settings['thumbnail_width'],
172
+ 'height' => $displayed_gallery->display_settings['thumbnail_height'],
173
+ 'quality' => $displayed_gallery->display_settings['thumbnail_quality'],
174
+ 'crop' => $displayed_gallery->display_settings['thumbnail_crop'],
175
+ 'watermark' => $displayed_gallery->display_settings['thumbnail_watermark']
176
+ );
177
+ }
178
+
179
+ // so user templates can know how big the images are expected to be
180
+ $params['image_gen_params'] = $image_gen_params;
181
 
182
  // Transform entities
183
+ $params['galleries'] = $params['entities'];
184
  unset($params['entities']);
185
+
186
  foreach ($params['galleries'] as &$gallery) {
187
 
188
  // Get the preview image url
189
+ $gallery->previewurl = '';
190
+ if ($gallery->previewpic && $gallery->previewpic > 0)
191
+ {
192
+ if (($image = $image_mapper->find(intval($gallery->previewpic))))
193
+ {
194
+ $gallery->previewurl = $storage->get_image_url($image, $image_gen->get_size_name($image_gen_params), TRUE);
195
+ $gallery->previewname = $gallery->name;
196
  }
197
  }
198
 
199
  // Get the page link. If the entity is an album, then the url will
200
  // look like /nggallery/album--slug.
201
  $id_field = $gallery->id_field;
202
+ if ($gallery->is_album)
203
+ {
204
+ if ($gallery->pageid > 0)
205
+ $gallery->pagelink = @get_page_link($gallery->pageid);
206
  else {
207
  $gallery->pagelink = $this->object->set_param_for(
208
  $this->object->get_routed_url(TRUE),
215
  // Otherwise, if it's a gallery then it will look like
216
  // /nggallery/album--slug/gallery--slug
217
  else {
218
+ if ($gallery->pageid > 0) {
219
+ $gallery->pagelink = @get_page_link($gallery->pageid);
220
+ }
221
+ if (empty($gallery->pagelink)) {
222
  $pagelink = $this->object->get_routed_url(TRUE);
223
  $parent_album = $this->object->get_parent_album_for($gallery->$id_field);
224
  if ($parent_album) {
228
  $parent_album->slug
229
  );
230
  }
231
+ // Legacy compat: use an album slug of 'all' if we're missing a container_id
232
+ else if($displayed_gallery->container_ids === array('0')
233
+ || $displayed_gallery->container_ids === array('')) {
234
+ $pagelink = $this->object->set_param_for($pagelink, 'album', 'all');
235
+ }
236
+ else {
237
+ $pagelink = $this->object->set_param_for($pagelink, 'album', 'album');
238
+ }
239
  $gallery->pagelink = $this->object->set_param_for(
240
  $pagelink,
241
  'gallery',
244
  }
245
  }
246
 
 
 
 
 
 
247
  // Let plugins modify the gallery
248
  $gallery = apply_filters('ngg_album_galleryobject', $gallery);
249
  }
250
 
251
+ $params['album'] = reset($this->albums);
252
+ $params['albums'] = $this->albums;
253
+
254
  // Clean up
255
  unset($storage);
256
  unset($image_mapper);
261
  }
262
 
263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  function _get_js_lib_url()
265
  {
266
  return $this->object->get_static_url('photocrati-nextgen_basic_album#init.js');
278
  wp_enqueue_style('nextgen_basic_album_style', $this->object->get_static_url('photocrati-nextgen_basic_album#nextgen_basic_album.css'));
279
  wp_enqueue_script('jquery.dotdotdot', $this->object->get_static_url('photocrati-nextgen_basic_album#jquery.dotdotdot-1.5.7-packed.js'), array('jquery'));
280
 
281
+ $this->enqueue_ngg_styles();
 
282
 
283
  }
284
 
products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album_forms.php CHANGED
@@ -5,12 +5,12 @@ class A_NextGen_Basic_Album_Forms extends Mixin
5
  function initialize()
6
  {
7
  $this->add_form(
8
- NEXTGEN_DISPLAY_SETTINGS_SLUG,
9
- NEXTGEN_GALLERY_NEXTGEN_BASIC_COMPACT_ALBUM
10
  );
11
  $this->add_form(
12
- NEXTGEN_DISPLAY_SETTINGS_SLUG,
13
- NEXTGEN_GALLERY_NEXTGEN_BASIC_EXTENDED_ALBUM
14
  );
15
  }
16
  }
5
  function initialize()
6
  {
7
  $this->add_form(
8
+ NGG_DISPLAY_SETTINGS_SLUG,
9
+ NGG_BASIC_COMPACT_ALBUM
10
  );
11
  $this->add_form(
12
+ NGG_DISPLAY_SETTINGS_SLUG,
13
+ NGG_BASIC_EXTENDED_ALBUM
14
  );
15
  }
16
  }
products/photocrati_nextgen/modules/nextgen_basic_album/adapter.nextgen_basic_album_mapper.php CHANGED
@@ -21,17 +21,29 @@ class Hook_NextGen_Basic_Album_Defaults extends Hook
21
  {
22
  function set_defaults($entity)
23
  {
24
- if (in_array($entity->name, array(
25
- NEXTGEN_GALLERY_NEXTGEN_BASIC_COMPACT_ALBUM,
26
- NEXTGEN_GALLERY_NEXTGEN_BASIC_EXTENDED_ALBUM))) {
27
 
28
  // Set defaults for both display (album) types
29
  $settings = C_NextGen_Settings::get_instance();
30
  $this->object->_set_default_value($entity, 'settings', 'galleries_per_page', $settings->galPagedGalleries);
31
  $this->object->_set_default_value($entity, 'settings', 'disable_pagination', 0);
32
  $this->object->_set_default_value($entity, 'settings', 'template', '');
33
- if (defined('NEXTGEN_GALLERY_BASIC_THUMBNAILS'))
34
- $this->object->_set_default_value($entity, 'settings', 'gallery_display_type', NEXTGEN_GALLERY_BASIC_THUMBNAILS);
 
 
 
 
 
 
 
 
21
  {
22
  function set_defaults($entity)
23
  {
24
+ if (isset($entity->name) && in_array($entity->name, array(
25
+ NGG_BASIC_COMPACT_ALBUM,
26
+ NGG_BASIC_EXTENDED_ALBUM))) {
27
 
28
  // Set defaults for both display (album) types
29
  $settings = C_NextGen_Settings::get_instance();
30
  $this->object->_set_default_value($entity, 'settings', 'galleries_per_page', $settings->galPagedGalleries);
31
  $this->object->_set_default_value($entity, 'settings', 'disable_pagination', 0);
32
  $this->object->_set_default_value($entity, 'settings', 'template', '');
33
+
34
+ // Thumbnail dimensions -- only used by extended albums
35
+ if ($entity->name == NGG_BASIC_EXTENDED_ALBUM)
36
+ {
37
+ $this->_set_default_value($entity, 'settings', 'override_thumbnail_settings', 0);
38
+ $this->_set_default_value($entity, 'settings', 'thumbnail_width', $settings->thumbwidth);
39
+ $this->_set_default_value($entity, 'settings', 'thumbnail_height', $settings->thumbheight);
40
+ $this->_set_default_value($entity, 'settings', 'thumbnail_quality', $settings->thumbquality);
41
+ $this->_set_default_value($entity, 'settings', 'thumbnail_crop', $settings->thumbfix);
42
+ $this->_set_default_va