refinerycms-photo-gallery 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (226) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/Changelog.md +11 -0
  4. data/Gemfile +35 -17
  5. data/Gemfile.lock +301 -0
  6. data/LICENSE.md +0 -0
  7. data/README.md +63 -13
  8. data/Rakefile +3 -2
  9. data/app/assets/images/refinery/photo_gallery/admin/chosen-sprite.png +0 -0
  10. data/app/assets/images/refinery/photo_gallery/admin/icons/album.png +0 -0
  11. data/app/assets/images/refinery/photo_gallery/admin/icons/album_add.png +0 -0
  12. data/app/assets/images/refinery/photo_gallery/admin/icons/album_edit.png +0 -0
  13. data/app/assets/images/refinery/photo_gallery/admin/icons/cog.png +0 -0
  14. data/app/assets/images/refinery/photo_gallery/admin/icons/down.gif +0 -0
  15. data/app/assets/images/refinery/photo_gallery/admin/icons/folder.png +0 -0
  16. data/app/assets/images/refinery/photo_gallery/admin/icons/folder_add.png +0 -0
  17. data/app/assets/images/refinery/photo_gallery/admin/icons/folder_edit.png +0 -0
  18. data/app/assets/images/refinery/photo_gallery/admin/icons/loading.gif +0 -0
  19. data/app/assets/images/refinery/photo_gallery/admin/icons/page_copy.png +0 -0
  20. data/app/assets/images/refinery/photo_gallery/admin/icons/photo.png +0 -0
  21. data/app/assets/images/refinery/photo_gallery/admin/icons/photo_add.png +0 -0
  22. data/app/assets/images/refinery/photo_gallery/admin/icons/photo_edit.png +0 -0
  23. data/app/assets/images/refinery/photo_gallery/admin/icons/up.gif +0 -0
  24. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/backgrounds.gif +0 -0
  25. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/buttons-disabled.png +0 -0
  26. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/buttons.png +0 -0
  27. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/delete.gif +0 -0
  28. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/done.gif +0 -0
  29. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/error.gif +0 -0
  30. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/throbber.gif +0 -0
  31. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/transp50.png +0 -0
  32. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.ui.plupload/plupload-bw.png +0 -0
  33. data/app/assets/images/refinery/photo_gallery/admin/plupload/jquery.ui.plupload/plupload.png +0 -0
  34. data/app/assets/images/refinery/photo_gallery/fancybox/blank.gif +0 -0
  35. data/app/assets/images/refinery/photo_gallery/fancybox/fancybox_loading.gif +0 -0
  36. data/app/assets/images/refinery/photo_gallery/fancybox/fancybox_sprite.png +0 -0
  37. data/app/assets/images/refinery/photo_gallery/fancybox/helpers/fancybox_buttons.png +0 -0
  38. data/app/assets/javascripts/refinery/photo_gallery/admin/jquery.chosen.min.js +0 -0
  39. data/app/assets/javascripts/refinery/photo_gallery/admin/photo_gallery.js.erb +46 -46
  40. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/Moxie.swf +0 -0
  41. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/Moxie.xap +0 -0
  42. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/changelog.txt +0 -0
  43. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ar.js +2 -0
  44. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/az.js +2 -0
  45. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/bg.js +2 -0
  46. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/bs.js +2 -0
  47. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ca.js +2 -0
  48. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/cs.js +2 -14
  49. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/cy.js +2 -0
  50. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/da.js +2 -12
  51. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/de.js +2 -24
  52. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/el.js +2 -14
  53. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/en.js +2 -0
  54. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/es.js +2 -25
  55. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/et.js +2 -33
  56. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/fa.js +2 -0
  57. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/fi.js +2 -33
  58. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/fr-ca.js +0 -0
  59. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/fr.js +2 -25
  60. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/he.js +2 -0
  61. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/hr.js +2 -25
  62. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/hu.js +2 -33
  63. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/hy.js +2 -0
  64. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/id.js +2 -0
  65. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/it.js +2 -24
  66. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ja.js +2 -37
  67. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ka.js +2 -0
  68. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/kk.js +2 -0
  69. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/km.js +2 -0
  70. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ko.js +2 -36
  71. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ku_IQ.js +2 -0
  72. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/lt.js +2 -0
  73. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/lv.js +2 -33
  74. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ms.js +2 -0
  75. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/nl.js +2 -21
  76. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/pl.js +2 -24
  77. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/pt-br.js +0 -0
  78. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/pt.js +2 -0
  79. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/pt_BR.js +2 -0
  80. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ro.js +2 -24
  81. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/ru.js +2 -21
  82. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/sk.js +2 -37
  83. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/sl.js +2 -0
  84. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/sq.js +2 -0
  85. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/sr.js +2 -14
  86. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/sv.js +2 -12
  87. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/th_TH.js +2 -0
  88. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/tr.js +2 -0
  89. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/uk_UA.js +2 -0
  90. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/vi.js +2 -0
  91. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/zh_CN.js +2 -0
  92. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/i18n/zh_TW.js +2 -0
  93. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue.js +0 -0
  94. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/css/jquery.plupload.queue.css +185 -0
  95. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/backgrounds.gif +0 -0
  96. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/buttons-disabled.png +0 -0
  97. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/buttons.png +0 -0
  98. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/delete.gif +0 -0
  99. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/done.gif +0 -0
  100. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/error.gif +0 -0
  101. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/throbber.gif +0 -0
  102. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/img/transp50.png +0 -0
  103. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/jquery.plupload.queue.js +428 -0
  104. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.plupload.queue/jquery.plupload.queue.min.js +1 -0
  105. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.ui.plupload.js +0 -0
  106. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.ui.plupload/css/jquery.ui.plupload.css +375 -0
  107. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.ui.plupload/img/loading.gif +0 -0
  108. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.ui.plupload/img/plupload.png +0 -0
  109. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.ui.plupload/jquery.ui.plupload.js +1343 -0
  110. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/jquery.ui.plupload/jquery.ui.plupload.min.js +1 -0
  111. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/license.txt +0 -0
  112. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/moxie.js +11158 -0
  113. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/moxie.min.js +16 -0
  114. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.browserplus.js +0 -0
  115. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.dev.js +2381 -0
  116. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.flash.js +0 -0
  117. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.flash.swf +0 -0
  118. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.full.js +0 -0
  119. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.full.js.default +0 -0
  120. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.full.min.js +29 -0
  121. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.gears.js +0 -0
  122. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.html4.js +0 -0
  123. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.html5.js +0 -0
  124. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.html5.js.default +0 -0
  125. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.js +0 -0
  126. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.min.js +13 -0
  127. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.silverlight.js +0 -0
  128. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/plupload.silverlight.xap +0 -0
  129. data/app/assets/javascripts/refinery/photo_gallery/admin/plupload/readme.md +0 -0
  130. data/app/assets/javascripts/refinery/photo_gallery/fancybox/CHANGELOG.md +0 -0
  131. data/app/assets/javascripts/refinery/photo_gallery/fancybox/README.md +0 -0
  132. data/app/assets/javascripts/refinery/photo_gallery/fancybox/helpers/jquery.fancybox-buttons.js +0 -0
  133. data/app/assets/javascripts/refinery/photo_gallery/fancybox/helpers/jquery.fancybox-media.js +0 -0
  134. data/app/assets/javascripts/refinery/photo_gallery/fancybox/helpers/jquery.fancybox-thumbs.js +0 -0
  135. data/app/assets/javascripts/refinery/photo_gallery/fancybox/jquery.fancybox.js +0 -0
  136. data/app/assets/javascripts/refinery/photo_gallery/fancybox/jquery.fancybox.pack.js +0 -0
  137. data/app/assets/javascripts/refinery/photo_gallery/fancybox/lib/jquery.mousewheel-3.0.6.pack.js +0 -0
  138. data/app/assets/javascripts/refinery/photo_gallery/photo_gallery.js +0 -0
  139. data/app/assets/stylesheets/refinery/photo_gallery/admin/chosen.css.scss +262 -262
  140. data/app/assets/stylesheets/refinery/photo_gallery/admin/photo_gallery.css.scss +1 -13
  141. data/app/assets/stylesheets/refinery/photo_gallery/admin/plupload/jquery.plupload.queue.css.scss +0 -0
  142. data/app/assets/stylesheets/refinery/photo_gallery/admin/plupload/jquery.ui.plupload.css.scss +0 -0
  143. data/app/assets/stylesheets/refinery/photo_gallery/fancybox/helpers/jquery.fancybox-buttons.css.scss +0 -0
  144. data/app/assets/stylesheets/refinery/photo_gallery/fancybox/helpers/jquery.fancybox-thumbs.css +0 -0
  145. data/app/assets/stylesheets/refinery/photo_gallery/fancybox/jquery.fancybox.css.scss +0 -0
  146. data/app/controllers/refinery/photo_gallery/admin/albums_controller.rb +10 -3
  147. data/app/controllers/refinery/photo_gallery/admin/collections_controller.rb +8 -0
  148. data/app/controllers/refinery/photo_gallery/admin/photos_controller.rb +19 -8
  149. data/app/helpers/refinery/photo_gallery/admin/photos_helper.rb +5 -1
  150. data/app/helpers/refinery/photo_gallery/albums_helper.rb +0 -0
  151. data/app/helpers/refinery/photo_gallery/photo_gallery_helper.rb +0 -0
  152. data/app/models/refinery/album_page.rb +0 -1
  153. data/app/models/refinery/photo_gallery/album.rb +0 -2
  154. data/app/models/refinery/photo_gallery/collection.rb +0 -2
  155. data/app/models/refinery/photo_gallery/collection_album.rb +0 -0
  156. data/app/models/refinery/photo_gallery/photo.rb +14 -16
  157. data/app/sweepers/refinery/admin/album_page_sweeper.rb +0 -0
  158. data/app/sweepers/refinery/photo_gallery/admin/album_sweeper.rb +0 -0
  159. data/app/sweepers/refinery/photo_gallery/admin/photo_sweeper.rb +0 -0
  160. data/app/uploaders/refinery/photo_gallery/admin/file_uploader.rb +7 -1
  161. data/app/views/refinery/admin/pages/tabs/_form.html.erb +0 -0
  162. data/app/views/refinery/admin/pages/tabs/_photo_gallery.html.erb +0 -0
  163. data/app/views/refinery/admin/pages/tabs/_photo_pages_bar.html.erb +0 -0
  164. data/app/views/refinery/photo_gallery/admin/_submenu.html.erb +4 -30
  165. data/app/views/refinery/photo_gallery/admin/albums/_album.html.erb +0 -0
  166. data/app/views/refinery/photo_gallery/admin/albums/_albums.html.erb +0 -0
  167. data/app/views/refinery/photo_gallery/admin/albums/_form.html.erb +1 -2
  168. data/app/views/refinery/photo_gallery/admin/albums/edit.html.erb +0 -0
  169. data/app/views/refinery/photo_gallery/admin/albums/index.html.erb +0 -0
  170. data/app/views/refinery/photo_gallery/admin/albums/new.html.erb +0 -0
  171. data/app/views/refinery/photo_gallery/admin/collections/_collection.html.erb +0 -0
  172. data/app/views/refinery/photo_gallery/admin/collections/_collections.html.erb +0 -0
  173. data/app/views/refinery/photo_gallery/admin/collections/_form.html.erb +0 -0
  174. data/app/views/refinery/photo_gallery/admin/collections/edit.html.erb +0 -0
  175. data/app/views/refinery/photo_gallery/admin/collections/index.html.erb +1 -0
  176. data/app/views/refinery/photo_gallery/admin/collections/new.html.erb +0 -0
  177. data/app/views/refinery/photo_gallery/admin/photos/_destroy.js.erb +0 -0
  178. data/app/views/refinery/photo_gallery/admin/photos/_form.html.erb +0 -0
  179. data/app/views/refinery/photo_gallery/admin/photos/_form_actions.html.erb +0 -0
  180. data/app/views/refinery/photo_gallery/admin/photos/_form_fields.html.erb +1 -0
  181. data/app/views/refinery/photo_gallery/admin/photos/_form_fields_actions.html.erb +0 -0
  182. data/app/views/refinery/photo_gallery/admin/photos/edit_multiple.html.erb +0 -0
  183. data/app/views/refinery/photo_gallery/admin/photos/upload.html.erb +4 -3
  184. data/app/views/refinery/photo_gallery/albums/_photos.html.erb +6 -2
  185. data/app/views/refinery/photo_gallery/albums/_photos.js.erb +0 -0
  186. data/app/views/refinery/photo_gallery/albums/_show.html.erb +0 -0
  187. data/config/initializers/carrierwave.rb +0 -0
  188. data/config/initializers/form_builder.rb +0 -0
  189. data/config/initializers/refinery/core.rb +0 -0
  190. data/config/initializers/s3.rb +0 -0
  191. data/config/locales/en.yml +2 -2
  192. data/config/locales/pl.yml +110 -0
  193. data/config/locales/sk.yml +2 -2
  194. data/config/routes.rb +0 -0
  195. data/db/migrate/20120804063842_create_albums.rb +0 -0
  196. data/db/migrate/20120805131321_create_collections.rb +0 -0
  197. data/db/migrate/20120805131547_create_collection_albums.rb +0 -0
  198. data/db/migrate/20120805165238_create_photos.rb +0 -0
  199. data/db/migrate/20120805222125_add_indexes.rb +2 -2
  200. data/db/migrate/20120805222126_create_album_pages.rb +0 -0
  201. data/db/migrate/20130127175559_add_url_to_photos.rb +5 -0
  202. data/db/migrate/20130128173800_add_css_styles_and_show_original_fields_to_photos.rb +6 -0
  203. data/db/seeds.rb +0 -0
  204. data/lib/generators/refinery/photo_gallery_generator.rb +5 -2
  205. data/lib/generators/refinery/templates/config/initializers/refinery/photo_gallery.rb.erb +3 -2
  206. data/lib/refinery/photo_gallery.rb +0 -1
  207. data/lib/refinery/photo_gallery/configuration.rb +7 -1
  208. data/lib/refinery/photo_gallery/engine.rb +0 -1
  209. data/lib/refinery/photo_gallery/extensions/pages_controller_extension.rb +0 -0
  210. data/lib/refinery/photo_gallery/extensions/pages_extension.rb +4 -12
  211. data/lib/refinery/photo_gallery/version.rb +2 -2
  212. data/lib/refinerycms-photo-gallery.rb +0 -0
  213. data/refinerycms-photo-gallery.gemspec +2 -3
  214. data/spec/factories/album_photos.rb +5 -0
  215. data/spec/factories/albums.rb +23 -0
  216. data/spec/factories/collections.rb +6 -0
  217. data/spec/factories/photos.rb +12 -0
  218. data/spec/factories/user.rb +27 -0
  219. data/spec/features/manage_albums_spec.rb +93 -0
  220. data/spec/features/manage_collections_spec.rb +62 -0
  221. data/spec/features/manage_photos_spec.rb +47 -0
  222. data/spec/spec_helper.rb +32 -0
  223. data/spec/support/images/refinery-logo-trans.png +0 -0
  224. data/tasks/rspec.rake +6 -0
  225. data/tasks/testing.rake +8 -0
  226. metadata +110 -63
@@ -0,0 +1,1343 @@
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 {Object} [settings.filters={}] Set of file type filters.
79
+ @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`
80
+ @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`.
81
+ @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
82
+ @param {Number} [settings.filters.max_file_count=0] Limit the number of files that can reside in the queue at the same time (default is 0 - no limit).
83
+ @param {String} [settings.flash_swf_url] URL of the Flash swf.
84
+ @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs.
85
+ @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`.
86
+ @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event.
87
+ @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message.
88
+ @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload.
89
+ @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog.
90
+ @param {Boolean} [settings.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`.
91
+ @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess.
92
+ @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}`
93
+ @param {Number} [settings.resize.width] If image is bigger, it will be resized.
94
+ @param {Number} [settings.resize.height] If image is bigger, it will be resized.
95
+ @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100).
96
+ @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally.
97
+ @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.
98
+ @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap.
99
+ @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files.
100
+
101
+ @param {Boolean} [settings.autostart=false] Whether to auto start uploading right after file selection.
102
+ @param {Boolean} [settings.dragdrop=true] Enable ability to add file to the queue by drag'n'dropping them from the desktop.
103
+ @param {Boolean} [settings.rename=false] Enable ability to rename files in the queue.
104
+ @param {Boolean} [settings.sortable=false] Enable ability to sort files in the queue, changing their uploading priority.
105
+ @param {Object} [settings.buttons] Control the visibility of functional buttons.
106
+ @param {Boolean} [settings.buttons.browse=true] Display browse button.
107
+ @param {Boolean} [settings.buttons.start=true] Display start button.
108
+ @param {Boolean} [settings.buttons.stop=true] Display stop button.
109
+ @param {Object} [settings.views] Control various views of the file queue.
110
+ @param {Boolean} [settings.views.list=true] Enable list view.
111
+ @param {Boolean} [settings.views.thumbs=false] Enable thumbs view.
112
+ @param {String} [settings.views.default='list'] Default view.
113
+ @param {Boolean} [settings.views.remember=true] Whether to remember the current view (requires jQuery Cookie plugin).
114
+ @param {Boolean} [settings.multiple_queues=true] Re-activate the widget after each upload procedure.
115
+ */
116
+ ;(function(window, document, plupload, o, $) {
117
+
118
+ /**
119
+ Dispatched when the widget is initialized and ready.
120
+
121
+ @event ready
122
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
123
+ */
124
+
125
+ /**
126
+ Dispatched when file dialog is closed.
127
+
128
+ @event selected
129
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
130
+ @param {Array} files Array of selected files represented by plupload.File objects
131
+ */
132
+
133
+ /**
134
+ Dispatched when file dialog is closed.
135
+
136
+ @event removed
137
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
138
+ @param {Array} files Array of removed files represented by plupload.File objects
139
+ */
140
+
141
+ /**
142
+ Dispatched when upload is started.
143
+
144
+ @event started
145
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
146
+ */
147
+
148
+ /**
149
+ Dispatched when upload is stopped.
150
+
151
+ @event stopped
152
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
153
+ */
154
+
155
+ /**
156
+ Dispatched during the upload process.
157
+
158
+ @event progress
159
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
160
+ @param {plupload.File} file File that is being uploaded (includes loaded and percent properties among others).
161
+ @param {Number} size Total file size in bytes.
162
+ @param {Number} loaded Number of bytes uploaded of the files total size.
163
+ @param {Number} percent Number of percentage uploaded of the file.
164
+ */
165
+
166
+ /**
167
+ Dispatched when file is uploaded.
168
+
169
+ @event uploaded
170
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
171
+ @param {plupload.File} file File that was uploaded.
172
+ @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
173
+ */
174
+
175
+ /**
176
+ Dispatched when upload of the whole queue is complete.
177
+
178
+ @event complete
179
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
180
+ @param {Array} files Array of uploaded files represented by plupload.File objects
181
+ */
182
+
183
+ /**
184
+ Dispatched when the view is changed, e.g. from `list` to `thumbs` or vice versa.
185
+
186
+ @event viewchanged
187
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
188
+ @param {String} type Current view type.
189
+ */
190
+
191
+ /**
192
+ Dispatched when error of some kind is detected.
193
+
194
+ @event error
195
+ @param {plupload.Uploader} uploader Uploader instance sending the event.
196
+ @param {String} error Error message.
197
+ @param {plupload.File} file File that was uploaded.
198
+ @param {Enum} status Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE.
199
+ */
200
+
201
+ var uploaders = {};
202
+
203
+ function _(str) {
204
+ return plupload.translate(str) || str;
205
+ }
206
+
207
+ function renderUI(obj) {
208
+ obj.id = obj.attr('id');
209
+
210
+ obj.html(
211
+ '<div class="plupload_wrapper">' +
212
+ '<div class="ui-widget-content plupload_container">' +
213
+ '<div class="ui-state-default ui-widget-header plupload_header">' +
214
+ '<div class="plupload_header_content">' +
215
+ '<div class="plupload_logo"> </div>' +
216
+ '<div class="plupload_header_title">' + _("Select files") + '</div>' +
217
+ '<div class="plupload_header_text">' + _("Add files to the upload queue and click the start button.") + '</div>' +
218
+ '<div class="plupload_view_switch">' +
219
+ '<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>' +
220
+ '<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>' +
221
+ '</div>' +
222
+ '</div>' +
223
+ '</div>' +
224
+
225
+ '<table class="plupload_filelist plupload_filelist_header ui-widget-header">' +
226
+ '<tr>' +
227
+ '<td class="plupload_cell plupload_file_name">' + _('Filename') + '</td>' +
228
+ '<td class="plupload_cell plupload_file_status">' + _('Status') + '</td>' +
229
+ '<td class="plupload_cell plupload_file_size">' + _('Size') + '</td>' +
230
+ '<td class="plupload_cell plupload_file_action">&nbsp;</td>' +
231
+ '</tr>' +
232
+ '</table>' +
233
+
234
+ '<div class="plupload_content">' +
235
+ '<div class="plupload_droptext">' + _("Drag files here.") + '</div>' +
236
+ '<ul class="plupload_filelist_content"> </ul>' +
237
+ '<div class="plupload_clearer">&nbsp;</div>' +
238
+ '</div>' +
239
+
240
+ '<table class="plupload_filelist plupload_filelist_footer ui-widget-header">' +
241
+ '<tr>' +
242
+ '<td class="plupload_cell plupload_file_name">' +
243
+ '<div class="plupload_buttons"><!-- Visible -->' +
244
+ '<a class="plupload_button plupload_add">' + _("Add Files") + '</a>&nbsp;' +
245
+ '<a class="plupload_button plupload_start">' + _("Start Upload") + '</a>&nbsp;' +
246
+ '<a class="plupload_button plupload_stop plupload_hidden">'+_("Stop Upload") + '</a>&nbsp;' +
247
+ '</div>' +
248
+
249
+ '<div class="plupload_started plupload_hidden"><!-- Hidden -->' +
250
+ '<div class="plupload_progress plupload_right">' +
251
+ '<div class="plupload_progress_container"></div>' +
252
+ '</div>' +
253
+
254
+ '<div class="plupload_cell plupload_upload_status"></div>' +
255
+
256
+ '<div class="plupload_clearer">&nbsp;</div>' +
257
+ '</div>' +
258
+ '</td>' +
259
+ '<td class="plupload_file_status"><span class="plupload_total_status">0%</span></td>' +
260
+ '<td class="plupload_file_size"><span class="plupload_total_file_size">0 kb</span></td>' +
261
+ '<td class="plupload_file_action"></td>' +
262
+ '</tr>' +
263
+ '</table>' +
264
+
265
+ '</div>' +
266
+ '<input class="plupload_count" value="0" type="hidden">' +
267
+ '</div>'
268
+ );
269
+ }
270
+
271
+
272
+ $.widget("ui.plupload", {
273
+
274
+ widgetEventPrefix: '',
275
+
276
+ contents_bak: '',
277
+
278
+ options: {
279
+ browse_button_hover: 'ui-state-hover',
280
+ browse_button_active: 'ui-state-active',
281
+
282
+ filters: {},
283
+
284
+ // widget specific
285
+ buttons: {
286
+ browse: true,
287
+ start: true,
288
+ stop: true
289
+ },
290
+
291
+ views: {
292
+ list: true,
293
+ thumbs: false,
294
+ active: 'list',
295
+ remember: true // requires: https://github.com/carhartl/jquery-cookie, otherwise disabled even if set to true
296
+ },
297
+
298
+ thumb_width: 100,
299
+ thumb_height: 60,
300
+
301
+ multiple_queues: true, // re-use widget by default
302
+ dragdrop : true,
303
+ autostart: false,
304
+ sortable: false,
305
+ rename: false
306
+ },
307
+
308
+ FILE_COUNT_ERROR: -9001,
309
+
310
+ _create: function() {
311
+ var id = this.element.attr('id');
312
+ if (!id) {
313
+ id = plupload.guid();
314
+ this.element.attr('id', id);
315
+ }
316
+ this.id = id;
317
+
318
+ // backup the elements initial state
319
+ this.contents_bak = this.element.html();
320
+ renderUI(this.element);
321
+
322
+ // container, just in case
323
+ this.container = $('.plupload_container', this.element).attr('id', id + '_container');
324
+
325
+ this.content = $('.plupload_content', this.element);
326
+
327
+ if ($.fn.resizable) {
328
+ this.container.resizable({
329
+ handles: 's',
330
+ minHeight: 300
331
+ });
332
+ }
333
+
334
+ // list of files, may become sortable
335
+ this.filelist = $('.plupload_filelist_content', this.container)
336
+ .attr({
337
+ id: id + '_filelist',
338
+ unselectable: 'on'
339
+ });
340
+
341
+
342
+ // buttons
343
+ this.browse_button = $('.plupload_add', this.container).attr('id', id + '_browse');
344
+ this.start_button = $('.plupload_start', this.container).attr('id', id + '_start');
345
+ this.stop_button = $('.plupload_stop', this.container).attr('id', id + '_stop');
346
+ this.thumbs_switcher = $('#' + id + '_view_thumbs');
347
+ this.list_switcher = $('#' + id + '_view_list');
348
+
349
+ if ($.ui.button) {
350
+ this.browse_button.button({
351
+ icons: { primary: 'ui-icon-circle-plus' },
352
+ disabled: true
353
+ });
354
+
355
+ this.start_button.button({
356
+ icons: { primary: 'ui-icon-circle-arrow-e' },
357
+ disabled: true
358
+ });
359
+
360
+ this.stop_button.button({
361
+ icons: { primary: 'ui-icon-circle-close' }
362
+ });
363
+
364
+ this.list_switcher.button({
365
+ text: false,
366
+ icons: { secondary: "ui-icon-grip-dotted-horizontal" }
367
+ });
368
+
369
+ this.thumbs_switcher.button({
370
+ text: false,
371
+ icons: { secondary: "ui-icon-image" }
372
+ });
373
+ }
374
+
375
+ // progressbar
376
+ this.progressbar = $('.plupload_progress_container', this.container);
377
+
378
+ if ($.ui.progressbar) {
379
+ this.progressbar.progressbar();
380
+ }
381
+
382
+ // counter
383
+ this.counter = $('.plupload_count', this.element)
384
+ .attr({
385
+ id: id + '_count',
386
+ name: id + '_count'
387
+ });
388
+
389
+ // initialize uploader instance
390
+ this._initUploader();
391
+ },
392
+
393
+ _initUploader: function() {
394
+ var self = this
395
+ , id = this.id
396
+ , uploader
397
+ , options = {
398
+ container: id + '_buttons',
399
+ browse_button: id + '_browse'
400
+ }
401
+ ;
402
+
403
+ $('.plupload_buttons', this.element).attr('id', id + '_buttons');
404
+
405
+ if (self.options.dragdrop) {
406
+ this.filelist.parent().attr('id', this.id + '_dropbox');
407
+ options.drop_element = this.id + '_dropbox';
408
+ }
409
+
410
+ this.filelist.on('click', function(e) {
411
+ if ($(e.target).hasClass('plupload_action_icon')) {
412
+ self.removeFile($(e.target).closest('.plupload_file').attr('id'));
413
+ e.preventDefault();
414
+ }
415
+ });
416
+
417
+ uploader = this.uploader = uploaders[id] = new plupload.Uploader($.extend(this.options, options));
418
+
419
+ // retrieve full normalized set of options
420
+ this.options = uploader.getOption();
421
+
422
+ if (self.options.views.thumbs) {
423
+ uploader.settings.required_features.display_media = true;
424
+ }
425
+
426
+ // for backward compatibility
427
+ if (self.options.max_file_count) {
428
+ plupload.extend(uploader.getOption('filters'), {
429
+ max_file_count: self.options.max_file_count
430
+ });
431
+ }
432
+
433
+ plupload.addFileFilter('max_file_count', function(maxCount, file, cb) {
434
+ if (maxCount <= this.files.length - (this.total.uploaded + this.total.failed)) {
435
+ self.browse_button.button('disable');
436
+ this.disableBrowse();
437
+
438
+ this.trigger('Error', {
439
+ code : self.FILE_COUNT_ERROR,
440
+ message : _("File count error."),
441
+ file : file
442
+ });
443
+ cb(false);
444
+ } else {
445
+ cb(true);
446
+ }
447
+ });
448
+
449
+
450
+ uploader.bind('Error', function(up, err) {
451
+ var message, details = "";
452
+
453
+ message = '<strong>' + err.message + '</strong>';
454
+
455
+ switch (err.code) {
456
+ case plupload.FILE_EXTENSION_ERROR:
457
+ details = o.sprintf(_("File: %s"), err.file.name);
458
+ break;
459
+
460
+ case plupload.FILE_SIZE_ERROR:
461
+ details = o.sprintf(_("File: %s, size: %d, max file size: %d"), err.file.name, plupload.formatSize(err.file.size), plupload.formatSize(plupload.parseSize(up.getOption('filters').max_file_size)));
462
+ break;
463
+
464
+ case plupload.FILE_DUPLICATE_ERROR:
465
+ details = o.sprintf(_("%s already present in the queue."), err.file.name);
466
+ break;
467
+
468
+ case self.FILE_COUNT_ERROR:
469
+ details = o.sprintf(_("Upload element accepts only %d file(s) at a time. Extra files were stripped."), up.getOption('filters').max_file_count || 0);
470
+ break;
471
+
472
+ case plupload.IMAGE_FORMAT_ERROR :
473
+ details = _("Image format either wrong or not supported.");
474
+ break;
475
+
476
+ case plupload.IMAGE_MEMORY_ERROR :
477
+ details = _("Runtime ran out of available memory.");
478
+ break;
479
+
480
+ /* // This needs a review
481
+ case plupload.IMAGE_DIMENSIONS_ERROR :
482
+ 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);
483
+ break; */
484
+
485
+ case plupload.HTTP_ERROR:
486
+ details = _("Upload URL might be wrong or doesn't exist.");
487
+ break;
488
+ }
489
+
490
+ message += " <br /><i>" + details + "</i>";
491
+
492
+ self._trigger('error', null, { up: up, error: err } );
493
+
494
+ // do not show UI if no runtime can be initialized
495
+ if (err.code === plupload.INIT_ERROR) {
496
+ setTimeout(function() {
497
+ self.destroy();
498
+ }, 1);
499
+ } else {
500
+ self.notify('error', message);
501
+ }
502
+ });
503
+
504
+
505
+ uploader.bind('PostInit', function(up) {
506
+ // all buttons are optional, so they can be disabled and hidden
507
+ if (!self.options.buttons.browse) {
508
+ self.browse_button.button('disable').hide();
509
+ up.disableBrowse(true);
510
+ } else {
511
+ self.browse_button.button('enable');
512
+ }
513
+
514
+ if (!self.options.buttons.start) {
515
+ self.start_button.button('disable').hide();
516
+ }
517
+
518
+ if (!self.options.buttons.stop) {
519
+ self.stop_button.button('disable').hide();
520
+ }
521
+
522
+ if (!self.options.unique_names && self.options.rename) {
523
+ self._enableRenaming();
524
+ }
525
+
526
+ if (self.options.dragdrop && up.features.dragdrop) {
527
+ self.filelist.parent().addClass('plupload_dropbox');
528
+ }
529
+
530
+ self._enableViewSwitcher();
531
+
532
+ self.start_button.click(function(e) {
533
+ if (!$(this).button('option', 'disabled')) {
534
+ self.start();
535
+ }
536
+ e.preventDefault();
537
+ });
538
+
539
+ self.stop_button.click(function(e) {
540
+ self.stop();
541
+ e.preventDefault();
542
+ });
543
+
544
+ self._trigger('ready', null, { up: up });
545
+ });
546
+
547
+ // uploader internal events must run first
548
+ uploader.init();
549
+
550
+ uploader.bind('FileFiltered', function(up, file) {
551
+ self._addFiles(file);
552
+ });
553
+
554
+ uploader.bind('FilesAdded', function(up, files) {
555
+ self._trigger('selected', null, { up: up, files: files } );
556
+
557
+ // re-enable sortable
558
+ if (self.options.sortable && $.ui.sortable) {
559
+ self._enableSortingList();
560
+ }
561
+
562
+ self._trigger('updatelist', null, { filelist: self.filelist });
563
+
564
+ if (self.options.autostart) {
565
+ // set a little delay to make sure that QueueChanged triggered by the core has time to complete
566
+ setTimeout(function() {
567
+ self.start();
568
+ }, 10);
569
+ }
570
+ });
571
+
572
+ uploader.bind('FilesRemoved', function(up, files) {
573
+ // destroy sortable if enabled
574
+ if ($.ui.sortable && self.options.sortable) {
575
+ $('tbody', self.filelist).sortable('destroy');
576
+ }
577
+
578
+ $.each(files, function(i, file) {
579
+ $('#' + file.id).toggle("highlight", function() {
580
+ $(this).remove();
581
+ });
582
+ });
583
+
584
+ if (up.files.length) {
585
+ // re-initialize sortable
586
+ if (self.options.sortable && $.ui.sortable) {
587
+ self._enableSortingList();
588
+ }
589
+ }
590
+
591
+ self._trigger('updatelist', null, { filelist: self.filelist });
592
+ self._trigger('removed', null, { up: up, files: files } );
593
+ });
594
+
595
+ uploader.bind('QueueChanged', function() {
596
+ self._handleState();
597
+ });
598
+
599
+ uploader.bind('StateChanged', function(up) {
600
+ self._handleState();
601
+ if (plupload.STARTED === up.state) {
602
+ self._trigger('started', null, { up: this.uploader });
603
+ } else if (plupload.STOPPED === up.state) {
604
+ self._trigger('stopped', null, { up: this.uploader });
605
+ }
606
+ });
607
+
608
+ uploader.bind('UploadFile', function(up, file) {
609
+ self._handleFileStatus(file);
610
+ });
611
+
612
+ uploader.bind('FileUploaded', function(up, file, result) {
613
+ self._handleFileStatus(file);
614
+ self._trigger('uploaded', null, { up: up, file: file, result: result } );
615
+ });
616
+
617
+ uploader.bind('UploadProgress', function(up, file) {
618
+ self._handleFileStatus(file);
619
+ self._updateTotalProgress();
620
+ self._trigger('progress', null, { up: up, file: file } );
621
+ });
622
+
623
+ uploader.bind('UploadComplete', function(up, files) {
624
+ self._addFormFields();
625
+ self._trigger('complete', null, { up: up, files: files } );
626
+ });
627
+ },
628
+
629
+
630
+ _setOption: function(key, value) {
631
+ var self = this;
632
+
633
+ if (key == 'buttons' && typeof(value) == 'object') {
634
+ value = $.extend(self.options.buttons, value);
635
+
636
+ if (!value.browse) {
637
+ self.browse_button.button('disable').hide();
638
+ self.uploader.disableBrowse(true);
639
+ } else {
640
+ self.browse_button.button('enable').show();
641
+ self.uploader.disableBrowse(false);
642
+ }
643
+
644
+ if (!value.start) {
645
+ self.start_button.button('disable').hide();
646
+ } else {
647
+ self.start_button.button('enable').show();
648
+ }
649
+
650
+ if (!value.stop) {
651
+ self.stop_button.button('disable').hide();
652
+ } else {
653
+ self.start_button.button('enable').show();
654
+ }
655
+ }
656
+
657
+ self.uploader.setOption(key, value);
658
+ },
659
+
660
+
661
+ /**
662
+ Start upload. Triggers `start` event.
663
+
664
+ @method start
665
+ */
666
+ start: function() {
667
+ this.uploader.start();
668
+ },
669
+
670
+
671
+ /**
672
+ Stop upload. Triggers `stop` event.
673
+
674
+ @method stop
675
+ */
676
+ stop: function() {
677
+ this.uploader.stop();
678
+ },
679
+
680
+
681
+ /**
682
+ Enable browse button.
683
+
684
+ @method enable
685
+ */
686
+ enable: function() {
687
+ this.browse_button.button('enable');
688
+ this.uploader.disableBrowse(false);
689
+ },
690
+
691
+
692
+ /**
693
+ Disable browse button.
694
+
695
+ @method disable
696
+ */
697
+ disable: function() {
698
+ this.browse_button.button('disable');
699
+ this.uploader.disableBrowse(true);
700
+ },
701
+
702
+
703
+ /**
704
+ Retrieve file by its unique id.
705
+
706
+ @method getFile
707
+ @param {String} id Unique id of the file
708
+ @return {plupload.File}
709
+ */
710
+ getFile: function(id) {
711
+ var file;
712
+
713
+ if (typeof id === 'number') {
714
+ file = this.uploader.files[id];
715
+ } else {
716
+ file = this.uploader.getFile(id);
717
+ }
718
+ return file;
719
+ },
720
+
721
+ /**
722
+ Return array of files currently in the queue.
723
+
724
+ @method getFiles
725
+ @return {Array} Array of files in the queue represented by plupload.File objects
726
+ */
727
+ getFiles: function() {
728
+ return this.uploader.files;
729
+ },
730
+
731
+
732
+ /**
733
+ Remove the file from the queue.
734
+
735
+ @method removeFile
736
+ @param {plupload.File|String} file File to remove, might be specified directly or by its unique id
737
+ */
738
+ removeFile: function(file) {
739
+ if (plupload.typeOf(file) === 'string') {
740
+ file = this.getFile(file);
741
+ }
742
+ this.uploader.removeFile(file);
743
+ },
744
+
745
+
746
+ /**
747
+ Clear the file queue.
748
+
749
+ @method clearQueue
750
+ */
751
+ clearQueue: function() {
752
+ this.uploader.splice();
753
+ },
754
+
755
+
756
+ /**
757
+ Retrieve internal plupload.Uploader object (usually not required).
758
+
759
+ @method getUploader
760
+ @return {plupload.Uploader}
761
+ */
762
+ getUploader: function() {
763
+ return this.uploader;
764
+ },
765
+
766
+
767
+ /**
768
+ Trigger refresh procedure, specifically browse_button re-measure and re-position operations.
769
+ Might get handy, when UI Widget is placed within the popup, that is constantly hidden and shown
770
+ again - without calling this method after each show operation, dialog trigger might get displaced
771
+ and disfunctional.
772
+
773
+ @method refresh
774
+ */
775
+ refresh: function() {
776
+ this.uploader.refresh();
777
+ },
778
+
779
+
780
+ /**
781
+ Display a message in notification area.
782
+
783
+ @method notify
784
+ @param {Enum} type Type of the message, either `error` or `info`
785
+ @param {String} message The text message to display.
786
+ */
787
+ notify: function(type, message) {
788
+ var popup = $(
789
+ '<div class="plupload_message">' +
790
+ '<span class="plupload_message_close ui-icon ui-icon-circle-close" title="'+_('Close')+'"></span>' +
791
+ '<p><span class="ui-icon"></span>' + message + '</p>' +
792
+ '</div>'
793
+ );
794
+
795
+ popup
796
+ .addClass('ui-state-' + (type === 'error' ? 'error' : 'highlight'))
797
+ .find('p .ui-icon')
798
+ .addClass('ui-icon-' + (type === 'error' ? 'alert' : 'info'))
799
+ .end()
800
+ .find('.plupload_message_close')
801
+ .click(function() {
802
+ popup.remove();
803
+ })
804
+ .end();
805
+
806
+ $('.plupload_header', this.container).append(popup);
807
+ },
808
+
809
+
810
+ /**
811
+ Destroy the widget, the uploader, free associated resources and bring back original html.
812
+
813
+ @method destroy
814
+ */
815
+ destroy: function() {
816
+ // destroy uploader instance
817
+ this.uploader.destroy();
818
+
819
+ // unbind all button events
820
+ $('.plupload_button', this.element).unbind();
821
+
822
+ // destroy buttons
823
+ if ($.ui.button) {
824
+ $('.plupload_add, .plupload_start, .plupload_stop', this.container)
825
+ .button('destroy');
826
+ }
827
+
828
+ // destroy progressbar
829
+ if ($.ui.progressbar) {
830
+ this.progressbar.progressbar('destroy');
831
+ }
832
+
833
+ // destroy sortable behavior
834
+ if ($.ui.sortable && this.options.sortable) {
835
+ $('tbody', this.filelist).sortable('destroy');
836
+ }
837
+
838
+ // restore the elements initial state
839
+ this.element
840
+ .empty()
841
+ .html(this.contents_bak);
842
+ this.contents_bak = '';
843
+
844
+ $.Widget.prototype.destroy.apply(this);
845
+ },
846
+
847
+
848
+ _handleState: function() {
849
+ var up = this.uploader
850
+ , filesPending = up.files.length - (up.total.uploaded + up.total.failed)
851
+ , maxCount = up.getOption('filters').max_file_count || 0
852
+ ;
853
+
854
+ if (plupload.STARTED === up.state) {
855
+ $([])
856
+ .add(this.stop_button)
857
+ .add('.plupload_started')
858
+ .removeClass('plupload_hidden');
859
+
860
+ this.start_button.button('disable');
861
+
862
+ if (!this.options.multiple_queues) {
863
+ this.browse_button.button('disable');
864
+ up.disableBrowse();
865
+ }
866
+
867
+ $('.plupload_upload_status', this.element).html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
868
+ $('.plupload_header_content', this.element).addClass('plupload_header_content_bw');
869
+ }
870
+ else if (plupload.STOPPED === up.state) {
871
+ $([])
872
+ .add(this.stop_button)
873
+ .add('.plupload_started')
874
+ .addClass('plupload_hidden');
875
+
876
+ if (filesPending) {
877
+ this.start_button.button('enable');
878
+ } else {
879
+ this.start_button.button('disable');
880
+ }
881
+
882
+ if (this.options.multiple_queues) {
883
+ $('.plupload_header_content', this.element).removeClass('plupload_header_content_bw');
884
+ }
885
+
886
+ // if max_file_count defined, only that many files can be queued at once
887
+ if (this.options.multiple_queues && maxCount && maxCount > filesPending) {
888
+ this.browse_button.button('enable');
889
+ up.disableBrowse(false);
890
+ }
891
+
892
+ this._updateTotalProgress();
893
+ }
894
+
895
+ if (up.total.queued === 0) {
896
+ $('.ui-button-text', this.browse_button).html(_('Add Files'));
897
+ } else {
898
+ $('.ui-button-text', this.browse_button).html(o.sprintf(_('%d files queued'), up.total.queued));
899
+ }
900
+
901
+ up.refresh();
902
+ },
903
+
904
+
905
+ _handleFileStatus: function(file) {
906
+ var $file = $('#' + file.id), actionClass, iconClass;
907
+
908
+ // since this method might be called asynchronously, file row might not yet be rendered
909
+ if (!$file.length) {
910
+ return;
911
+ }
912
+
913
+ switch (file.status) {
914
+ case plupload.DONE:
915
+ actionClass = 'plupload_done';
916
+ iconClass = 'plupload_action_icon ui-icon ui-icon-circle-check';
917
+ break;
918
+
919
+ case plupload.FAILED:
920
+ actionClass = 'ui-state-error plupload_failed';
921
+ iconClass = 'plupload_action_icon ui-icon ui-icon-alert';
922
+ break;
923
+
924
+ case plupload.QUEUED:
925
+ actionClass = 'plupload_delete';
926
+ iconClass = 'plupload_action_icon ui-icon ui-icon-circle-minus';
927
+ break;
928
+
929
+ case plupload.UPLOADING:
930
+ actionClass = 'ui-state-highlight plupload_uploading';
931
+ iconClass = 'plupload_action_icon ui-icon ui-icon-circle-arrow-w';
932
+
933
+ // scroll uploading file into the view if its bottom boundary is out of it
934
+ var scroller = $('.plupload_scroll', this.container)
935
+ , scrollTop = scroller.scrollTop()
936
+ , scrollerHeight = scroller.height()
937
+ , rowOffset = $file.position().top + $file.height()
938
+ ;
939
+
940
+ if (scrollerHeight < rowOffset) {
941
+ scroller.scrollTop(scrollTop + rowOffset - scrollerHeight);
942
+ }
943
+
944
+ // Set file specific progress
945
+ $file
946
+ .find('.plupload_file_percent')
947
+ .html(file.percent + '%')
948
+ .end()
949
+ .find('.plupload_file_progress')
950
+ .css('width', file.percent + '%')
951
+ .end()
952
+ .find('.plupload_file_size')
953
+ .html(plupload.formatSize(file.size));
954
+ break;
955
+ }
956
+ actionClass += ' ui-state-default plupload_file';
957
+
958
+ $file
959
+ .attr('class', actionClass)
960
+ .find('.plupload_action_icon')
961
+ .attr('class', iconClass);
962
+ },
963
+
964
+
965
+ _updateTotalProgress: function() {
966
+ var up = this.uploader;
967
+
968
+ // Scroll to end of file list
969
+ this.filelist[0].scrollTop = this.filelist[0].scrollHeight;
970
+
971
+ this.progressbar.progressbar('value', up.total.percent);
972
+
973
+ this.element
974
+ .find('.plupload_total_status')
975
+ .html(up.total.percent + '%')
976
+ .end()
977
+ .find('.plupload_total_file_size')
978
+ .html(plupload.formatSize(up.total.size))
979
+ .end()
980
+ .find('.plupload_upload_status')
981
+ .html(o.sprintf(_('Uploaded %d/%d files'), up.total.uploaded, up.files.length));
982
+ },
983
+
984
+
985
+ _displayThumbs: function() {
986
+ var self = this
987
+ , tw, th // thumb width/height
988
+ , cols
989
+ , num = 0 // number of simultaneously visible thumbs
990
+ , thumbs = [] // array of thumbs to preload at any given moment
991
+ , loading = false
992
+ ;
993
+
994
+ if (!this.options.views.thumbs) {
995
+ return;
996
+ }
997
+
998
+
999
+ function onLast(el, eventName, cb) {
1000
+ var timer;
1001
+
1002
+ el.on(eventName, function() {
1003
+ clearTimeout(timer);
1004
+ timer = setTimeout(function() {
1005
+ clearTimeout(timer);
1006
+ cb();
1007
+ }, 300);
1008
+ });
1009
+ }
1010
+
1011
+
1012
+ // calculate number of simultaneously visible thumbs
1013
+ function measure() {
1014
+ if (!tw || !th) {
1015
+ var wrapper = $('.plupload_file:eq(0)', self.filelist);
1016
+ tw = wrapper.outerWidth(true);
1017
+ th = wrapper.outerHeight(true);
1018
+ }
1019
+
1020
+ var aw = self.content.width(), ah = self.content.height();
1021
+ cols = Math.floor(aw / tw);
1022
+ num = cols * (Math.ceil(ah / th) + 1);
1023
+ }
1024
+
1025
+
1026
+ function pickThumbsToLoad() {
1027
+ // calculate index of virst visible thumb
1028
+ var startIdx = Math.floor(self.content.scrollTop() / th) * cols;
1029
+ // get potentially visible thumbs that are not yet visible
1030
+ thumbs = $('.plupload_file .plupload_file_thumb', self.filelist)
1031
+ .slice(startIdx, startIdx + num)
1032
+ .filter('.plupload_thumb_toload')
1033
+ .get();
1034
+ }
1035
+
1036
+
1037
+ function init() {
1038
+ function mpl() { // measure, pick, load
1039
+ if (self.view_mode !== 'thumbs') {
1040
+ return;
1041
+ }
1042
+ measure();
1043
+ pickThumbsToLoad();
1044
+ lazyLoad();
1045
+ }
1046
+
1047
+ if ($.fn.resizable) {
1048
+ onLast(self.container, 'resize', mpl);
1049
+ }
1050
+
1051
+ onLast(self.window, 'resize', mpl);
1052
+ onLast(self.content, 'scroll', mpl);
1053
+
1054
+ self.element.on('viewchanged selected', mpl);
1055
+
1056
+ mpl();
1057
+ }
1058
+
1059
+
1060
+ function preloadThumb(file, cb) {
1061
+ var img = new o.Image();
1062
+
1063
+ img.onload = function() {
1064
+ var thumb = $('#' + file.id + ' .plupload_file_thumb', self.filelist);
1065
+ this.embed(thumb[0], {
1066
+ width: self.options.thumb_width,
1067
+ height: self.options.thumb_height,
1068
+ crop: true,
1069
+ preserveHeaders: false,
1070
+ swf_url: o.resolveUrl(self.options.flash_swf_url),
1071
+ xap_url: o.resolveUrl(self.options.silverlight_xap_url)
1072
+ });
1073
+ };
1074
+
1075
+ img.bind("embedded error", function(e) {
1076
+ $('#' + file.id, self.filelist)
1077
+ .find('.plupload_file_thumb')
1078
+ .removeClass('plupload_thumb_loading')
1079
+ .addClass('plupload_thumb_' + e.type)
1080
+ ;
1081
+ this.destroy();
1082
+ setTimeout(cb, 1); // detach, otherwise ui might hang (in SilverLight for example)
1083
+ });
1084
+
1085
+ $('#' + file.id, self.filelist)
1086
+ .find('.plupload_file_thumb')
1087
+ .removeClass('plupload_thumb_toload')
1088
+ .addClass('plupload_thumb_loading')
1089
+ ;
1090
+ img.load(file.getSource());
1091
+ }
1092
+
1093
+
1094
+ function lazyLoad() {
1095
+ if (self.view_mode !== 'thumbs' || loading) {
1096
+ return;
1097
+ }
1098
+
1099
+ pickThumbsToLoad();
1100
+ if (!thumbs.length) {
1101
+ return;
1102
+ }
1103
+
1104
+ loading = true;
1105
+
1106
+ preloadThumb(self.getFile($(thumbs.shift()).closest('.plupload_file').attr('id')), function() {
1107
+ loading = false;
1108
+ lazyLoad();
1109
+ });
1110
+ }
1111
+
1112
+ // this has to run only once to measure structures and bind listeners
1113
+ this.element.on('selected', function onselected() {
1114
+ self.element.off('selected', onselected);
1115
+ init();
1116
+ });
1117
+ },
1118
+
1119
+
1120
+ _addFiles: function(files) {
1121
+ var self = this, file_html, html = '';
1122
+
1123
+ file_html = '<li class="plupload_file ui-state-default plupload_delete" id="{id}" style="width:{thumb_width}px;">' +
1124
+ '<div class="plupload_file_thumb plupload_thumb_toload" style="width: {thumb_width}px; height: {thumb_height}px;">' +
1125
+ '<div class="plupload_file_dummy ui-widget-content" style="line-height: {thumb_height}px;"><span class="ui-state-disabled">{ext} </span></div>' +
1126
+ '</div>' +
1127
+ '<div class="plupload_file_status">' +
1128
+ '<div class="plupload_file_progress ui-widget-header" style="width: 0%"> </div>' +
1129
+ '<span class="plupload_file_percent">{percent} </span>' +
1130
+ '</div>' +
1131
+ '<div class="plupload_file_name" title="{name}">' +
1132
+ '<span class="plupload_file_name_wrapper">{name} </span>' +
1133
+ '</div>' +
1134
+ '<div class="plupload_file_action">' +
1135
+ '<div class="plupload_action_icon ui-icon ui-icon-circle-minus"> </div>' +
1136
+ '</div>' +
1137
+ '<div class="plupload_file_size">{size} </div>' +
1138
+ '<div class="plupload_file_fields"> </div>' +
1139
+ '</li>';
1140
+
1141
+ if (plupload.typeOf(files) !== 'array') {
1142
+ files = [files];
1143
+ }
1144
+
1145
+ $.each(files, function(i, file) {
1146
+ var ext = o.Mime.getFileExtension(file.name) || 'none';
1147
+
1148
+ html += file_html.replace(/\{(\w+)\}/g, function($0, $1) {
1149
+ switch ($1) {
1150
+ case 'thumb_width':
1151
+ case 'thumb_height':
1152
+ return self.options[$1];
1153
+
1154
+ case 'size':
1155
+ return plupload.formatSize(file.size);
1156
+
1157
+ case 'ext':
1158
+ return ext;
1159
+
1160
+ default:
1161
+ return file[$1] || '';
1162
+ }
1163
+ });
1164
+ });
1165
+
1166
+ self.filelist.append(html);
1167
+ },
1168
+
1169
+
1170
+ _addFormFields: function() {
1171
+ var self = this;
1172
+
1173
+ // re-add from fresh
1174
+ $('.plupload_file_fields', this.filelist).html('');
1175
+
1176
+ plupload.each(this.uploader.files, function(file, count) {
1177
+ var fields = ''
1178
+ , id = self.id + '_' + count
1179
+ ;
1180
+
1181
+ if (file.target_name) {
1182
+ fields += '<input type="hidden" name="' + id + '_tmpname" value="'+plupload.xmlEncode(file.target_name)+'" />';
1183
+ }
1184
+ fields += '<input type="hidden" name="' + id + '_name" value="'+plupload.xmlEncode(file.name)+'" />';
1185
+ fields += '<input type="hidden" name="' + id + '_status" value="' + (file.status === plupload.DONE ? 'done' : 'failed') + '" />';
1186
+
1187
+ $('#' + file.id).find('.plupload_file_fields').html(fields);
1188
+ });
1189
+
1190
+ this.counter.val(this.uploader.files.length);
1191
+ },
1192
+
1193
+
1194
+ _viewChanged: function(view) {
1195
+ // update or write a new cookie
1196
+ if (this.options.views.remember && $.cookie) {
1197
+ $.cookie('plupload_ui_view', view, { expires: 7, path: '/' });
1198
+ }
1199
+
1200
+ // ugly fix for IE6 - make content area stretchable
1201
+ if (o.Env.browser === 'IE' && o.Env.version < 7) {
1202
+ this.content.attr('style', 'height:expression(document.getElementById("' + this.id + '_container' + '").clientHeight - ' + (view === 'list' ? 132 : 102) + ')');
1203
+ }
1204
+
1205
+ this.container.removeClass('plupload_view_list plupload_view_thumbs').addClass('plupload_view_' + view);
1206
+ this.view_mode = view;
1207
+ this._trigger('viewchanged', null, { view: view });
1208
+ },
1209
+
1210
+
1211
+ _enableViewSwitcher: function() {
1212
+ var self = this
1213
+ , view
1214
+ , switcher = $('.plupload_view_switch', this.container)
1215
+ , buttons
1216
+ , button
1217
+ ;
1218
+
1219
+ plupload.each(['list', 'thumbs'], function(view) {
1220
+ if (!self.options.views[view]) {
1221
+ switcher.find('[for="' + self.id + '_view_' + view + '"], #'+ self.id +'_view_' + view).remove();
1222
+ }
1223
+ });
1224
+
1225
+ // check if any visible left
1226
+ buttons = switcher.find('.plupload_button');
1227
+
1228
+ if (buttons.length === 1) {
1229
+ switcher.hide();
1230
+ view = buttons.eq(0).data('view');
1231
+ this._viewChanged(view);
1232
+ } else if ($.ui.button && buttons.length > 1) {
1233
+ if (this.options.views.remember && $.cookie) {
1234
+ view = $.cookie('plupload_ui_view');
1235
+ }
1236
+
1237
+ // if wierd case, bail out to default
1238
+ if (!~plupload.inArray(view, ['list', 'thumbs'])) {
1239
+ view = this.options.views.active;
1240
+ }
1241
+
1242
+ switcher
1243
+ .show()
1244
+ .buttonset()
1245
+ .find('.ui-button')
1246
+ .click(function(e) {
1247
+ view = $(this).data('view');
1248
+ self._viewChanged(view);
1249
+ e.preventDefault(); // avoid auto scrolling to widget in IE and FF (see #850)
1250
+ });
1251
+
1252
+ // if view not active - happens when switcher wasn't clicked manually
1253
+ button = switcher.find('[for="' + self.id + '_view_'+view+'"]');
1254
+ if (button.length) {
1255
+ button.trigger('click');
1256
+ }
1257
+ } else {
1258
+ switcher.show();
1259
+ this._viewChanged(this.options.views.active);
1260
+ }
1261
+
1262
+ // initialize thumb viewer if requested
1263
+ if (this.options.views.thumbs) {
1264
+ this._displayThumbs();
1265
+ }
1266
+ },
1267
+
1268
+
1269
+ _enableRenaming: function() {
1270
+ var self = this;
1271
+
1272
+ this.filelist.dblclick(function(e) {
1273
+ var nameSpan = $(e.target), nameInput, file, parts, name, ext = "";
1274
+
1275
+ if (!nameSpan.hasClass('plupload_file_name_wrapper')) {
1276
+ return;
1277
+ }
1278
+
1279
+ // Get file name and split out name and extension
1280
+ file = self.uploader.getFile(nameSpan.closest('.plupload_file')[0].id);
1281
+ name = file.name;
1282
+ parts = /^(.+)(\.[^.]+)$/.exec(name);
1283
+ if (parts) {
1284
+ name = parts[1];
1285
+ ext = parts[2];
1286
+ }
1287
+
1288
+ // Display input element
1289
+ nameInput = $('<input class="plupload_file_rename" type="text" />').width(nameSpan.width()).insertAfter(nameSpan.hide());
1290
+ nameInput.val(name).blur(function() {
1291
+ nameSpan.show().parent().scrollLeft(0).end().next().remove();
1292
+ }).keydown(function(e) {
1293
+ var nameInput = $(this);
1294
+
1295
+ if ($.inArray(e.keyCode, [13, 27]) !== -1) {
1296
+ e.preventDefault();
1297
+
1298
+ // Rename file and glue extension back on
1299
+ if (e.keyCode === 13) {
1300
+ file.name = nameInput.val() + ext;
1301
+ nameSpan.html(file.name);
1302
+ }
1303
+ nameInput.blur();
1304
+ }
1305
+ })[0].focus();
1306
+ });
1307
+ },
1308
+
1309
+
1310
+ _enableSortingList: function() {
1311
+ var self = this;
1312
+
1313
+ if ($('.plupload_file', this.filelist).length < 2) {
1314
+ return;
1315
+ }
1316
+
1317
+ // destroy sortable if enabled
1318
+ $('tbody', this.filelist).sortable('destroy');
1319
+
1320
+ // enable
1321
+ this.filelist.sortable({
1322
+ items: '.plupload_delete',
1323
+
1324
+ cancel: 'object, .plupload_clearer',
1325
+
1326
+ stop: function() {
1327
+ var files = [];
1328
+
1329
+ $.each($(this).sortable('toArray'), function(i, id) {
1330
+ files[files.length] = self.uploader.getFile(id);
1331
+ });
1332
+
1333
+ files.unshift(files.length);
1334
+ files.unshift(0);
1335
+
1336
+ // re-populate files array
1337
+ Array.prototype.splice.apply(self.uploader.files, files);
1338
+ }
1339
+ });
1340
+ }
1341
+ });
1342
+
1343
+ } (window, document, plupload, mOxie, jQuery));