rails_ueditor 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (272) hide show
  1. checksums.yaml +8 -8
  2. data/lib/rails_ueditor/version.rb +1 -1
  3. data/vendor/assets/javascripts/ueditor/dialogs/anchor/anchor.html +40 -0
  4. data/vendor/assets/javascripts/ueditor/dialogs/attachment/attachment.css +681 -0
  5. data/vendor/assets/javascripts/ueditor/dialogs/attachment/attachment.html +60 -0
  6. data/vendor/assets/javascripts/ueditor/dialogs/attachment/attachment.js +754 -0
  7. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_chm.gif +0 -0
  8. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_default.png +0 -0
  9. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_doc.gif +0 -0
  10. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_exe.gif +0 -0
  11. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_jpg.gif +0 -0
  12. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_mp3.gif +0 -0
  13. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_mv.gif +0 -0
  14. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_pdf.gif +0 -0
  15. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_ppt.gif +0 -0
  16. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_psd.gif +0 -0
  17. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_rar.gif +0 -0
  18. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_txt.gif +0 -0
  19. data/vendor/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_xls.gif +0 -0
  20. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/alignicon.gif +0 -0
  21. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/alignicon.png +0 -0
  22. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/bg.png +0 -0
  23. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/file-icons.gif +0 -0
  24. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/file-icons.png +0 -0
  25. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/icons.gif +0 -0
  26. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/icons.png +0 -0
  27. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/image.png +0 -0
  28. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/progress.png +0 -0
  29. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/success.gif +0 -0
  30. data/vendor/assets/javascripts/ueditor/dialogs/attachment/images/success.png +0 -0
  31. data/vendor/assets/javascripts/ueditor/dialogs/background/background.css +94 -0
  32. data/vendor/assets/javascripts/ueditor/dialogs/background/background.html +56 -0
  33. data/vendor/assets/javascripts/ueditor/dialogs/background/background.js +376 -0
  34. data/vendor/assets/javascripts/ueditor/dialogs/background/images/bg.png +0 -0
  35. data/vendor/assets/javascripts/ueditor/dialogs/background/images/success.png +0 -0
  36. data/vendor/assets/javascripts/ueditor/dialogs/charts/chart.config.js +65 -0
  37. data/vendor/assets/javascripts/ueditor/dialogs/charts/charts.css +165 -0
  38. data/vendor/assets/javascripts/ueditor/dialogs/charts/charts.html +89 -0
  39. data/vendor/assets/javascripts/ueditor/dialogs/charts/charts.js +519 -0
  40. data/vendor/assets/javascripts/ueditor/dialogs/charts/images/charts0.png +0 -0
  41. data/vendor/assets/javascripts/ueditor/dialogs/charts/images/charts1.png +0 -0
  42. data/vendor/assets/javascripts/ueditor/dialogs/charts/images/charts2.png +0 -0
  43. data/vendor/assets/javascripts/ueditor/dialogs/charts/images/charts3.png +0 -0
  44. data/vendor/assets/javascripts/ueditor/dialogs/charts/images/charts4.png +0 -0
  45. data/vendor/assets/javascripts/ueditor/dialogs/charts/images/charts5.png +0 -0
  46. data/vendor/assets/javascripts/ueditor/dialogs/emotion/emotion.css +43 -0
  47. data/vendor/assets/javascripts/ueditor/dialogs/emotion/emotion.html +54 -0
  48. data/vendor/assets/javascripts/ueditor/dialogs/emotion/emotion.js +186 -0
  49. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/0.gif +0 -0
  50. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/bface.gif +0 -0
  51. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/cface.gif +0 -0
  52. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/fface.gif +0 -0
  53. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/jxface2.gif +0 -0
  54. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/neweditor-tab-bg.png +0 -0
  55. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/tface.gif +0 -0
  56. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/wface.gif +0 -0
  57. data/vendor/assets/javascripts/ueditor/dialogs/emotion/images/yface.gif +0 -0
  58. data/vendor/assets/javascripts/ueditor/dialogs/gmap/gmap.html +89 -0
  59. data/vendor/assets/javascripts/ueditor/dialogs/help/help.css +7 -0
  60. data/vendor/assets/javascripts/ueditor/dialogs/help/help.html +82 -0
  61. data/vendor/assets/javascripts/ueditor/dialogs/help/help.js +56 -0
  62. data/vendor/assets/javascripts/ueditor/dialogs/image/image.css +894 -0
  63. data/vendor/assets/javascripts/ueditor/dialogs/image/image.html +120 -0
  64. data/vendor/assets/javascripts/ueditor/dialogs/image/image.js +1139 -0
  65. data/vendor/assets/javascripts/ueditor/dialogs/image/images/alignicon.jpg +0 -0
  66. data/vendor/assets/javascripts/ueditor/dialogs/image/images/bg.png +0 -0
  67. data/vendor/assets/javascripts/ueditor/dialogs/image/images/icons.gif +0 -0
  68. data/vendor/assets/javascripts/ueditor/dialogs/image/images/icons.png +0 -0
  69. data/vendor/assets/javascripts/ueditor/dialogs/image/images/image.png +0 -0
  70. data/vendor/assets/javascripts/ueditor/dialogs/image/images/progress.png +0 -0
  71. data/vendor/assets/javascripts/ueditor/dialogs/image/images/success.gif +0 -0
  72. data/vendor/assets/javascripts/ueditor/dialogs/image/images/success.png +0 -0
  73. data/vendor/assets/javascripts/ueditor/dialogs/insertframe/insertframe.html +98 -0
  74. data/vendor/assets/javascripts/ueditor/dialogs/internal.js +81 -0
  75. data/vendor/assets/javascripts/ueditor/dialogs/link/link.html +126 -0
  76. data/vendor/assets/javascripts/ueditor/dialogs/map/map.html +135 -0
  77. data/vendor/assets/javascripts/ueditor/dialogs/map/show.html +118 -0
  78. data/vendor/assets/javascripts/ueditor/dialogs/music/music.css +30 -0
  79. data/vendor/assets/javascripts/ueditor/dialogs/music/music.html +32 -0
  80. data/vendor/assets/javascripts/ueditor/dialogs/music/music.js +192 -0
  81. data/vendor/assets/javascripts/ueditor/dialogs/preview/preview.html +40 -0
  82. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/addimg.png +0 -0
  83. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/brush.png +0 -0
  84. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/delimg.png +0 -0
  85. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/delimgH.png +0 -0
  86. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/empty.png +0 -0
  87. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/emptyH.png +0 -0
  88. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/eraser.png +0 -0
  89. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/redo.png +0 -0
  90. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/redoH.png +0 -0
  91. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/scale.png +0 -0
  92. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/scaleH.png +0 -0
  93. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/size.png +0 -0
  94. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/undo.png +0 -0
  95. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/images/undoH.png +0 -0
  96. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/scrawl.css +72 -0
  97. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/scrawl.html +95 -0
  98. data/vendor/assets/javascripts/ueditor/dialogs/scrawl/scrawl.js +671 -0
  99. data/vendor/assets/javascripts/ueditor/dialogs/searchreplace/searchreplace.html +102 -0
  100. data/vendor/assets/javascripts/ueditor/dialogs/searchreplace/searchreplace.js +164 -0
  101. data/vendor/assets/javascripts/ueditor/dialogs/snapscreen/snapscreen.html +58 -0
  102. data/vendor/assets/javascripts/ueditor/dialogs/spechars/spechars.html +21 -0
  103. data/vendor/assets/javascripts/ueditor/dialogs/spechars/spechars.js +57 -0
  104. data/vendor/assets/javascripts/ueditor/dialogs/table/dragicon.png +0 -0
  105. data/vendor/assets/javascripts/ueditor/dialogs/table/edittable.css +84 -0
  106. data/vendor/assets/javascripts/ueditor/dialogs/table/edittable.html +64 -0
  107. data/vendor/assets/javascripts/ueditor/dialogs/table/edittable.js +237 -0
  108. data/vendor/assets/javascripts/ueditor/dialogs/table/edittd.html +61 -0
  109. data/vendor/assets/javascripts/ueditor/dialogs/table/edittip.html +33 -0
  110. data/vendor/assets/javascripts/ueditor/dialogs/template/config.js +42 -0
  111. data/vendor/assets/javascripts/ueditor/dialogs/template/images/bg.gif +0 -0
  112. data/vendor/assets/javascripts/ueditor/dialogs/template/images/pre0.png +0 -0
  113. data/vendor/assets/javascripts/ueditor/dialogs/template/images/pre1.png +0 -0
  114. data/vendor/assets/javascripts/ueditor/dialogs/template/images/pre2.png +0 -0
  115. data/vendor/assets/javascripts/ueditor/dialogs/template/images/pre3.png +0 -0
  116. data/vendor/assets/javascripts/ueditor/dialogs/template/images/pre4.png +0 -0
  117. data/vendor/assets/javascripts/ueditor/dialogs/template/template.css +18 -0
  118. data/vendor/assets/javascripts/ueditor/dialogs/template/template.html +26 -0
  119. data/vendor/assets/javascripts/ueditor/dialogs/template/template.js +53 -0
  120. data/vendor/assets/javascripts/ueditor/dialogs/video/images/bg.png +0 -0
  121. data/vendor/assets/javascripts/ueditor/dialogs/video/images/center_focus.jpg +0 -0
  122. data/vendor/assets/javascripts/ueditor/dialogs/video/images/file-icons.gif +0 -0
  123. data/vendor/assets/javascripts/ueditor/dialogs/video/images/file-icons.png +0 -0
  124. data/vendor/assets/javascripts/ueditor/dialogs/video/images/icons.gif +0 -0
  125. data/vendor/assets/javascripts/ueditor/dialogs/video/images/icons.png +0 -0
  126. data/vendor/assets/javascripts/ueditor/dialogs/video/images/image.png +0 -0
  127. data/vendor/assets/javascripts/ueditor/dialogs/video/images/left_focus.jpg +0 -0
  128. data/vendor/assets/javascripts/ueditor/dialogs/video/images/none_focus.jpg +0 -0
  129. data/vendor/assets/javascripts/ueditor/dialogs/video/images/progress.png +0 -0
  130. data/vendor/assets/javascripts/ueditor/dialogs/video/images/right_focus.jpg +0 -0
  131. data/vendor/assets/javascripts/ueditor/dialogs/video/images/success.gif +0 -0
  132. data/vendor/assets/javascripts/ueditor/dialogs/video/images/success.png +0 -0
  133. data/vendor/assets/javascripts/ueditor/dialogs/video/video.css +635 -0
  134. data/vendor/assets/javascripts/ueditor/dialogs/video/video.html +86 -0
  135. data/vendor/assets/javascripts/ueditor/dialogs/video/video.js +789 -0
  136. data/vendor/assets/javascripts/ueditor/dialogs/webapp/webapp.html +53 -0
  137. data/vendor/assets/javascripts/ueditor/dialogs/wordimage/fClipboard_ueditor.swf +0 -0
  138. data/vendor/assets/javascripts/ueditor/dialogs/wordimage/imageUploader.swf +0 -0
  139. data/vendor/assets/javascripts/ueditor/dialogs/wordimage/tangram.js +1495 -0
  140. data/vendor/assets/javascripts/ueditor/dialogs/wordimage/wordimage.html +111 -0
  141. data/vendor/assets/javascripts/ueditor/dialogs/wordimage/wordimage.js +157 -0
  142. data/vendor/assets/javascripts/ueditor/lang/en/en.js +684 -0
  143. data/vendor/assets/javascripts/ueditor/lang/en/images/addimage.png +0 -0
  144. data/vendor/assets/javascripts/ueditor/lang/en/images/alldeletebtnhoverskin.png +0 -0
  145. data/vendor/assets/javascripts/ueditor/lang/en/images/alldeletebtnupskin.png +0 -0
  146. data/vendor/assets/javascripts/ueditor/lang/en/images/background.png +0 -0
  147. data/vendor/assets/javascripts/ueditor/lang/en/images/button.png +0 -0
  148. data/vendor/assets/javascripts/ueditor/lang/en/images/copy.png +0 -0
  149. data/vendor/assets/javascripts/ueditor/lang/en/images/deletedisable.png +0 -0
  150. data/vendor/assets/javascripts/ueditor/lang/en/images/deleteenable.png +0 -0
  151. data/vendor/assets/javascripts/ueditor/lang/en/images/listbackground.png +0 -0
  152. data/vendor/assets/javascripts/ueditor/lang/en/images/localimage.png +0 -0
  153. data/vendor/assets/javascripts/ueditor/lang/en/images/music.png +0 -0
  154. data/vendor/assets/javascripts/ueditor/lang/en/images/rotateleftdisable.png +0 -0
  155. data/vendor/assets/javascripts/ueditor/lang/en/images/rotateleftenable.png +0 -0
  156. data/vendor/assets/javascripts/ueditor/lang/en/images/rotaterightdisable.png +0 -0
  157. data/vendor/assets/javascripts/ueditor/lang/en/images/rotaterightenable.png +0 -0
  158. data/vendor/assets/javascripts/ueditor/lang/en/images/upload.png +0 -0
  159. data/vendor/assets/javascripts/ueditor/lang/zh-cn/images/copy.png +0 -0
  160. data/vendor/assets/javascripts/ueditor/lang/zh-cn/images/localimage.png +0 -0
  161. data/vendor/assets/javascripts/ueditor/lang/zh-cn/images/music.png +0 -0
  162. data/vendor/assets/javascripts/ueditor/lang/zh-cn/images/upload.png +0 -0
  163. data/vendor/assets/javascripts/ueditor/lang/zh-cn/zh-cn.js +669 -0
  164. data/vendor/assets/javascripts/ueditor/themes/default/css/ueditor.css +1903 -0
  165. data/vendor/assets/javascripts/ueditor/themes/default/css/ueditor.min.css +8 -0
  166. data/vendor/assets/javascripts/ueditor/themes/default/dialogbase.css +100 -0
  167. data/vendor/assets/javascripts/ueditor/themes/default/images/anchor.gif +0 -0
  168. data/vendor/assets/javascripts/ueditor/themes/default/images/arrow.png +0 -0
  169. data/vendor/assets/javascripts/ueditor/themes/default/images/arrow_down.png +0 -0
  170. data/vendor/assets/javascripts/ueditor/themes/default/images/arrow_up.png +0 -0
  171. data/vendor/assets/javascripts/ueditor/themes/default/images/button-bg.gif +0 -0
  172. data/vendor/assets/javascripts/ueditor/themes/default/images/cancelbutton.gif +0 -0
  173. data/vendor/assets/javascripts/ueditor/themes/default/images/charts.png +0 -0
  174. data/vendor/assets/javascripts/ueditor/themes/default/images/cursor_h.gif +0 -0
  175. data/vendor/assets/javascripts/ueditor/themes/default/images/cursor_h.png +0 -0
  176. data/vendor/assets/javascripts/ueditor/themes/default/images/cursor_v.gif +0 -0
  177. data/vendor/assets/javascripts/ueditor/themes/default/images/cursor_v.png +0 -0
  178. data/vendor/assets/javascripts/ueditor/themes/default/images/dialog-title-bg.png +0 -0
  179. data/vendor/assets/javascripts/ueditor/themes/default/images/filescan.png +0 -0
  180. data/vendor/assets/javascripts/ueditor/themes/default/images/highlighted.gif +0 -0
  181. data/vendor/assets/javascripts/ueditor/themes/default/images/icons-all.gif +0 -0
  182. data/vendor/assets/javascripts/ueditor/themes/default/images/icons.gif +0 -0
  183. data/vendor/assets/javascripts/ueditor/themes/default/images/icons.png +0 -0
  184. data/vendor/assets/javascripts/ueditor/themes/default/images/loaderror.png +0 -0
  185. data/vendor/assets/javascripts/ueditor/themes/default/images/loading.gif +0 -0
  186. data/vendor/assets/javascripts/ueditor/themes/default/images/lock.gif +0 -0
  187. data/vendor/assets/javascripts/ueditor/themes/default/images/neweditor-tab-bg.png +0 -0
  188. data/vendor/assets/javascripts/ueditor/themes/default/images/pagebreak.gif +0 -0
  189. data/vendor/assets/javascripts/ueditor/themes/default/images/scale.png +0 -0
  190. data/vendor/assets/javascripts/ueditor/themes/default/images/sortable.png +0 -0
  191. data/vendor/assets/javascripts/ueditor/themes/default/images/spacer.gif +0 -0
  192. data/vendor/assets/javascripts/ueditor/themes/default/images/sparator_v.png +0 -0
  193. data/vendor/assets/javascripts/ueditor/themes/default/images/table-cell-align.png +0 -0
  194. data/vendor/assets/javascripts/ueditor/themes/default/images/tangram-colorpicker.png +0 -0
  195. data/vendor/assets/javascripts/ueditor/themes/default/images/toolbar_bg.png +0 -0
  196. data/vendor/assets/javascripts/ueditor/themes/default/images/unhighlighted.gif +0 -0
  197. data/vendor/assets/javascripts/ueditor/themes/default/images/upload.png +0 -0
  198. data/vendor/assets/javascripts/ueditor/themes/default/images/videologo.gif +0 -0
  199. data/vendor/assets/javascripts/ueditor/themes/default/images/word.gif +0 -0
  200. data/vendor/assets/javascripts/ueditor/themes/default/images/wordpaste.png +0 -0
  201. data/vendor/assets/javascripts/ueditor/themes/iframe.css +1 -0
  202. data/vendor/assets/javascripts/ueditor/third-party/SyntaxHighlighter/shCore.js +3655 -0
  203. data/vendor/assets/javascripts/ueditor/third-party/SyntaxHighlighter/shCoreDefault.css +1 -0
  204. data/vendor/assets/javascripts/ueditor/third-party/codemirror/codemirror.css +104 -0
  205. data/vendor/assets/javascripts/ueditor/third-party/codemirror/codemirror.js +3581 -0
  206. data/vendor/assets/javascripts/ueditor/third-party/highcharts/adapters/mootools-adapter.js +13 -0
  207. data/vendor/assets/javascripts/ueditor/third-party/highcharts/adapters/mootools-adapter.src.js +313 -0
  208. data/vendor/assets/javascripts/ueditor/third-party/highcharts/adapters/prototype-adapter.js +15 -0
  209. data/vendor/assets/javascripts/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js +316 -0
  210. data/vendor/assets/javascripts/ueditor/third-party/highcharts/adapters/standalone-framework.js +17 -0
  211. data/vendor/assets/javascripts/ueditor/third-party/highcharts/adapters/standalone-framework.src.js +583 -0
  212. data/vendor/assets/javascripts/ueditor/third-party/highcharts/highcharts-more.js +50 -0
  213. data/vendor/assets/javascripts/ueditor/third-party/highcharts/highcharts-more.src.js +2430 -0
  214. data/vendor/assets/javascripts/ueditor/third-party/highcharts/highcharts.js +283 -0
  215. data/vendor/assets/javascripts/ueditor/third-party/highcharts/highcharts.src.js +16974 -0
  216. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/annotations.js +7 -0
  217. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/annotations.src.js +401 -0
  218. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/canvas-tools.js +133 -0
  219. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/canvas-tools.src.js +3113 -0
  220. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/data.js +17 -0
  221. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/data.src.js +582 -0
  222. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/drilldown.js +11 -0
  223. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/drilldown.src.js +447 -0
  224. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/exporting.js +22 -0
  225. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/exporting.src.js +709 -0
  226. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/funnel.js +12 -0
  227. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/funnel.src.js +289 -0
  228. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/heatmap.js +1 -0
  229. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/heatmap.src.js +53 -0
  230. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/map.js +27 -0
  231. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/map.src.js +1002 -0
  232. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/no-data-to-display.js +12 -0
  233. data/vendor/assets/javascripts/ueditor/third-party/highcharts/modules/no-data-to-display.src.js +128 -0
  234. data/vendor/assets/javascripts/ueditor/third-party/highcharts/themes/dark-blue.js +254 -0
  235. data/vendor/assets/javascripts/ueditor/third-party/highcharts/themes/dark-green.js +255 -0
  236. data/vendor/assets/javascripts/ueditor/third-party/highcharts/themes/gray.js +257 -0
  237. data/vendor/assets/javascripts/ueditor/third-party/highcharts/themes/grid.js +103 -0
  238. data/vendor/assets/javascripts/ueditor/third-party/highcharts/themes/skies.js +89 -0
  239. data/vendor/assets/javascripts/ueditor/third-party/jquery-1.10.2.js +9789 -0
  240. data/vendor/assets/javascripts/ueditor/third-party/jquery-1.10.2.min.js +6 -0
  241. data/vendor/assets/javascripts/ueditor/third-party/jquery-1.10.2.min.map +1 -0
  242. data/vendor/assets/javascripts/ueditor/third-party/snapscreen/UEditorSnapscreen.exe +0 -0
  243. data/vendor/assets/javascripts/ueditor/third-party/video-js/font/vjs.eot +0 -0
  244. data/vendor/assets/javascripts/ueditor/third-party/video-js/font/vjs.svg +65 -0
  245. data/vendor/assets/javascripts/ueditor/third-party/video-js/font/vjs.ttf +0 -0
  246. data/vendor/assets/javascripts/ueditor/third-party/video-js/font/vjs.woff +0 -0
  247. data/vendor/assets/javascripts/ueditor/third-party/video-js/video-js.css +766 -0
  248. data/vendor/assets/javascripts/ueditor/third-party/video-js/video-js.min.css +5 -0
  249. data/vendor/assets/javascripts/ueditor/third-party/video-js/video-js.swf +0 -0
  250. data/vendor/assets/javascripts/ueditor/third-party/video-js/video.dev.js +7108 -0
  251. data/vendor/assets/javascripts/ueditor/third-party/video-js/video.js +129 -0
  252. data/vendor/assets/javascripts/ueditor/third-party/webuploader/Uploader.swf +0 -0
  253. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.css +28 -0
  254. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.custom.js +5670 -0
  255. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.custom.min.js +2 -0
  256. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.flashonly.js +4176 -0
  257. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.flashonly.min.js +2 -0
  258. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.html5only.js +5559 -0
  259. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.html5only.min.js +2 -0
  260. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.js +6733 -0
  261. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.min.js +2 -0
  262. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.withoutimage.js +4593 -0
  263. data/vendor/assets/javascripts/ueditor/third-party/webuploader/webuploader.withoutimage.min.js +2 -0
  264. data/vendor/assets/javascripts/ueditor/third-party/zeroclipboard/ZeroClipboard.js +1256 -0
  265. data/vendor/assets/javascripts/ueditor/third-party/zeroclipboard/ZeroClipboard.min.js +9 -0
  266. data/vendor/assets/javascripts/ueditor/third-party/zeroclipboard/ZeroClipboard.swf +0 -0
  267. data/vendor/assets/javascripts/ueditor/ueditor.all.js +29429 -0
  268. data/vendor/assets/javascripts/ueditor/ueditor.all.min.js +709 -0
  269. data/vendor/assets/javascripts/ueditor/ueditor.config.js +413 -0
  270. data/vendor/assets/javascripts/ueditor/ueditor.parse.js +1022 -0
  271. data/vendor/assets/javascripts/ueditor/ueditor.parse.min.js +28 -0
  272. metadata +270 -1
@@ -0,0 +1,2 @@
1
+ /* WebUploader 0.1.2 */!function(a,b){var c,d={},e=function(a,b){var c,d,e;if("string"==typeof a)return h(a);for(c=[],d=a.length,e=0;d>e;e++)c.push(h(a[e]));return b.apply(null,c)},f=function(a,b,c){2===arguments.length&&(c=b,b=null),e(b||[],function(){g(a,c,arguments)})},g=function(a,b,c){var f,g={exports:b};"function"==typeof b&&(c.length||(c=[e,g.exports,g]),f=b.apply(null,c),void 0!==f&&(g.exports=f)),d[a]=g.exports},h=function(b){var c=d[b]||a[b];if(!c)throw new Error("`"+b+"` is undefined");return c},i=function(a){var b,c,e,f,g,h;h=function(a){return a&&a.charAt(0).toUpperCase()+a.substr(1)};for(b in d)if(c=a,d.hasOwnProperty(b)){for(e=b.split("/"),g=h(e.pop());f=h(e.shift());)c[f]=c[f]||{},c=c[f];c[g]=d[b]}},j=b(a,f,e);i(j),"object"==typeof module&&"object"==typeof module.exports?module.exports=j:"function"==typeof define&&define.amd?define([],j):(c=a.WebUploader,a.WebUploader=j,a.WebUploader.noConflict=function(){a.WebUploader=c})}(this,function(a,b,c){return b("dollar-third",[],function(){return a.jQuery||a.Zepto}),b("dollar",["dollar-third"],function(a){return a}),b("promise-third",["dollar"],function(a){return{Deferred:a.Deferred,when:a.when,isPromise:function(a){return a&&"function"==typeof a.then}}}),b("promise",["promise-third"],function(a){return a}),b("base",["dollar","promise"],function(b,c){function d(a){return function(){return h.apply(a,arguments)}}function e(a,b){return function(){return a.apply(b,arguments)}}function f(a){var b;return Object.create?Object.create(a):(b=function(){},b.prototype=a,new b)}var g=function(){},h=Function.call;return{version:"0.1.2",$:b,Deferred:c.Deferred,isPromise:c.isPromise,when:c.when,browser:function(a){var b={},c=a.match(/WebKit\/([\d.]+)/),d=a.match(/Chrome\/([\d.]+)/)||a.match(/CriOS\/([\d.]+)/),e=a.match(/MSIE\s([\d\.]+)/)||a.match(/(?:trident)(?:.*rv:([\w.]+))?/i),f=a.match(/Firefox\/([\d.]+)/),g=a.match(/Safari\/([\d.]+)/),h=a.match(/OPR\/([\d.]+)/);return c&&(b.webkit=parseFloat(c[1])),d&&(b.chrome=parseFloat(d[1])),e&&(b.ie=parseFloat(e[1])),f&&(b.firefox=parseFloat(f[1])),g&&(b.safari=parseFloat(g[1])),h&&(b.opera=parseFloat(h[1])),b}(navigator.userAgent),os:function(a){var b={},c=a.match(/(?:Android);?[\s\/]+([\d.]+)?/),d=a.match(/(?:iPad|iPod|iPhone).*OS\s([\d_]+)/);return c&&(b.android=parseFloat(c[1])),d&&(b.ios=parseFloat(d[1].replace(/_/g,"."))),b}(navigator.userAgent),inherits:function(a,c,d){var e;return"function"==typeof c?(e=c,c=null):e=c&&c.hasOwnProperty("constructor")?c.constructor:function(){return a.apply(this,arguments)},b.extend(!0,e,a,d||{}),e.__super__=a.prototype,e.prototype=f(a.prototype),c&&b.extend(!0,e.prototype,c),e},noop:g,bindFn:e,log:function(){return a.console?e(console.log,console):g}(),nextTick:function(){return function(a){setTimeout(a,1)}}(),slice:d([].slice),guid:function(){var a=0;return function(b){for(var c=(+new Date).toString(32),d=0;5>d;d++)c+=Math.floor(65535*Math.random()).toString(32);return(b||"wu_")+c+(a++).toString(32)}}(),formatSize:function(a,b,c){var d;for(c=c||["B","K","M","G","TB"];(d=c.shift())&&a>1024;)a/=1024;return("B"===d?a:a.toFixed(b||2))+d}}}),b("mediator",["base"],function(a){function b(a,b,c,d){return f.grep(a,function(a){return!(!a||b&&a.e!==b||c&&a.cb!==c&&a.cb._cb!==c||d&&a.ctx!==d)})}function c(a,b,c){f.each((a||"").split(h),function(a,d){c(d,b)})}function d(a,b){for(var c,d=!1,e=-1,f=a.length;++e<f;)if(c=a[e],c.cb.apply(c.ctx2,b)===!1){d=!0;break}return!d}var e,f=a.$,g=[].slice,h=/\s+/;return e={on:function(a,b,d){var e,f=this;return b?(e=this._events||(this._events=[]),c(a,b,function(a,b){var c={e:a};c.cb=b,c.ctx=d,c.ctx2=d||f,c.id=e.length,e.push(c)}),this):this},once:function(a,b,d){var e=this;return b?(c(a,b,function(a,b){var c=function(){return e.off(a,c),b.apply(d||e,arguments)};c._cb=b,e.on(a,c,d)}),e):e},off:function(a,d,e){var g=this._events;return g?a||d||e?(c(a,d,function(a,c){f.each(b(g,a,c,e),function(){delete g[this.id]})}),this):(this._events=[],this):this},trigger:function(a){var c,e,f;return this._events&&a?(c=g.call(arguments,1),e=b(this._events,a),f=b(this._events,"all"),d(e,c)&&d(f,arguments)):this}},f.extend({installTo:function(a){return f.extend(a,e)}},e)}),b("uploader",["base","mediator"],function(a,b){function c(a){this.options=d.extend(!0,{},c.options,a),this._init(this.options)}var d=a.$;return c.options={},b.installTo(c.prototype),d.each({upload:"start-upload",stop:"stop-upload",getFile:"get-file",getFiles:"get-files",addFile:"add-file",addFiles:"add-file",sort:"sort-files",removeFile:"remove-file",skipFile:"skip-file",retry:"retry",isInProgress:"is-in-progress",makeThumb:"make-thumb",getDimension:"get-dimension",addButton:"add-btn",getRuntimeType:"get-runtime-type",refresh:"refresh",disable:"disable",enable:"enable",reset:"reset"},function(a,b){c.prototype[a]=function(){return this.request(b,arguments)}}),d.extend(c.prototype,{state:"pending",_init:function(a){var b=this;b.request("init",a,function(){b.state="ready",b.trigger("ready")})},option:function(a,b){var c=this.options;return arguments.length>1?void(d.isPlainObject(b)&&d.isPlainObject(c[a])?d.extend(c[a],b):c[a]=b):a?c[a]:c},getStats:function(){var a=this.request("get-stats");return{successNum:a.numOfSuccess,cancelNum:a.numOfCancel,invalidNum:a.numOfInvalid,uploadFailNum:a.numOfUploadFailed,queueNum:a.numOfQueue}},trigger:function(a){var c=[].slice.call(arguments,1),e=this.options,f="on"+a.substring(0,1).toUpperCase()+a.substring(1);return b.trigger.apply(this,arguments)===!1||d.isFunction(e[f])&&e[f].apply(this,c)===!1||d.isFunction(this[f])&&this[f].apply(this,c)===!1||b.trigger.apply(b,[this,a].concat(c))===!1?!1:!0},request:a.noop}),a.create=c.create=function(a){return new c(a)},a.Uploader=c,c}),b("runtime/runtime",["base","mediator"],function(a,b){function c(b){this.options=d.extend({container:document.body},b),this.uid=a.guid("rt_")}var d=a.$,e={},f=function(a){for(var b in a)if(a.hasOwnProperty(b))return b;return null};return d.extend(c.prototype,{getContainer:function(){var a,b,c=this.options;return this._container?this._container:(a=d(c.container||document.body),b=d(document.createElement("div")),b.attr("id","rt_"+this.uid),b.css({position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),a.append(b),a.addClass("webuploader-container"),this._container=b,b)},init:a.noop,exec:a.noop,destroy:function(){this._container&&this._container.parentNode.removeChild(this.__container),this.off()}}),c.orders="html5,flash",c.addRuntime=function(a,b){e[a]=b},c.hasRuntime=function(a){return!!(a?e[a]:f(e))},c.create=function(a,b){var g,h;if(b=b||c.orders,d.each(b.split(/\s*,\s*/g),function(){return e[this]?(g=this,!1):void 0}),g=g||f(e),!g)throw new Error("Runtime Error");return h=new e[g](a)},b.installTo(c.prototype),c}),b("runtime/client",["base","mediator","runtime/runtime"],function(a,b,c){function d(b,d){var f,g=a.Deferred();this.uid=a.guid("client_"),this.runtimeReady=function(a){return g.done(a)},this.connectRuntime=function(b,h){if(f)throw new Error("already connected!");return g.done(h),"string"==typeof b&&e.get(b)&&(f=e.get(b)),f=f||e.get(null,d),f?(a.$.extend(f.options,b),f.__promise.then(g.resolve),f.__client++):(f=c.create(b,b.runtimeOrder),f.__promise=g.promise(),f.once("ready",g.resolve),f.init(),e.add(f),f.__client=1),d&&(f.__standalone=d),f},this.getRuntime=function(){return f},this.disconnectRuntime=function(){f&&(f.__client--,f.__client<=0&&(e.remove(f),delete f.__promise,f.destroy()),f=null)},this.exec=function(){if(f){var c=a.slice(arguments);return b&&c.unshift(b),f.exec.apply(this,c)}},this.getRuid=function(){return f&&f.uid},this.destroy=function(a){return function(){a&&a.apply(this,arguments),this.trigger("destroy"),this.off(),this.exec("destroy"),this.disconnectRuntime()}}(this.destroy)}var e;return e=function(){var a={};return{add:function(b){a[b.uid]=b},get:function(b,c){var d;if(b)return a[b];for(d in a)if(!c||!a[d].__standalone)return a[d];return null},remove:function(b){delete a[b.uid]}}}(),b.installTo(d.prototype),d}),b("lib/dnd",["base","mediator","runtime/client"],function(a,b,c){function d(a){a=this.options=e.extend({},d.options,a),a.container=e(a.container),a.container.length&&c.call(this,"DragAndDrop")}var e=a.$;return d.options={accept:null,disableGlobalDnd:!1},a.inherits(c,{constructor:d,init:function(){var a=this;a.connectRuntime(a.options,function(){a.exec("init"),a.trigger("ready")})},destroy:function(){this.disconnectRuntime()}}),b.installTo(d.prototype),d}),b("widgets/widget",["base","uploader"],function(a,b){function c(a){if(!a)return!1;var b=a.length,c=e.type(a);return 1===a.nodeType&&b?!0:"array"===c||"function"!==c&&"string"!==c&&(0===b||"number"==typeof b&&b>0&&b-1 in a)}function d(a){this.owner=a,this.options=a.options}var e=a.$,f=b.prototype._init,g={},h=[];return e.extend(d.prototype,{init:a.noop,invoke:function(a,b){var c=this.responseMap;return c&&a in c&&c[a]in this&&e.isFunction(this[c[a]])?this[c[a]].apply(this,b):g},request:function(){return this.owner.request.apply(this.owner,arguments)}}),e.extend(b.prototype,{_init:function(){var a=this,b=a._widgets=[];return e.each(h,function(c,d){b.push(new d(a))}),f.apply(a,arguments)},request:function(b,d,e){var f,h,i,j,k=0,l=this._widgets,m=l.length,n=[],o=[];for(d=c(d)?d:[d];m>k;k++)f=l[k],h=f.invoke(b,d),h!==g&&(a.isPromise(h)?o.push(h):n.push(h));return e||o.length?(i=a.when.apply(a,o),j=i.pipe?"pipe":"then",i[j](function(){var b=a.Deferred(),c=arguments;return setTimeout(function(){b.resolve.apply(b,c)},1),b.promise()})[j](e||a.noop)):n[0]}}),b.register=d.register=function(b,c){var f,g={init:"init"};return 1===arguments.length?(c=b,c.responseMap=g):c.responseMap=e.extend(g,b),f=a.inherits(d,c),h.push(f),f},d}),b("widgets/filednd",["base","uploader","lib/dnd","widgets/widget"],function(a,b,c){var d=a.$;return b.options.dnd="",b.register({init:function(b){if(b.dnd&&"html5"===this.request("predict-runtime-type")){var e,f=this,g=a.Deferred(),h=d.extend({},{disableGlobalDnd:b.disableGlobalDnd,container:b.dnd,accept:b.accept});return e=new c(h),e.once("ready",g.resolve),e.on("drop",function(a){f.request("add-file",[a])}),e.on("accept",function(a){return f.owner.trigger("dndAccept",a)}),e.init(),g.promise()}}})}),b("lib/filepaste",["base","mediator","runtime/client"],function(a,b,c){function d(a){a=this.options=e.extend({},a),a.container=e(a.container||document.body),c.call(this,"FilePaste")}var e=a.$;return a.inherits(c,{constructor:d,init:function(){var a=this;a.connectRuntime(a.options,function(){a.exec("init"),a.trigger("ready")})},destroy:function(){this.exec("destroy"),this.disconnectRuntime(),this.off()}}),b.installTo(d.prototype),d}),b("widgets/filepaste",["base","uploader","lib/filepaste","widgets/widget"],function(a,b,c){var d=a.$;return b.register({init:function(b){if(b.paste&&"html5"===this.request("predict-runtime-type")){var e,f=this,g=a.Deferred(),h=d.extend({},{container:b.paste,accept:b.accept});return e=new c(h),e.once("ready",g.resolve),e.on("paste",function(a){f.owner.request("add-file",[a])}),e.init(),g.promise()}}})}),b("lib/blob",["base","runtime/client"],function(a,b){function c(a,c){var d=this;d.source=c,d.ruid=a,b.call(d,"Blob"),this.uid=c.uid||this.uid,this.type=c.type||"",this.size=c.size||0,a&&d.connectRuntime(a)}return a.inherits(b,{constructor:c,slice:function(a,b){return this.exec("slice",a,b)},getSource:function(){return this.source}}),c}),b("lib/file",["base","lib/blob"],function(a,b){function c(a,c){var f;b.apply(this,arguments),this.name=c.name||"untitled"+d++,f=e.exec(c.name)?RegExp.$1.toLowerCase():"",!f&&this.type&&(f=/\/(jpg|jpeg|png|gif|bmp)$/i.exec(this.type)?RegExp.$1.toLowerCase():"",this.name+="."+f),!this.type&&~"jpg,jpeg,png,gif,bmp".indexOf(f)&&(this.type="image/"+("jpg"===f?"jpeg":f)),this.ext=f,this.lastModifiedDate=c.lastModifiedDate||(new Date).toLocaleString()}var d=1,e=/\.([^.]+)$/;return a.inherits(b,c)}),b("lib/filepicker",["base","runtime/client","lib/file"],function(b,c,d){function e(a){if(a=this.options=f.extend({},e.options,a),a.container=f(a.id),!a.container.length)throw new Error("按钮指定错误");a.innerHTML=a.innerHTML||a.label||a.container.html()||"",a.button=f(a.button||document.createElement("div")),a.button.html(a.innerHTML),a.container.html(a.button),c.call(this,"FilePicker",!0)}var f=b.$;return e.options={button:null,container:null,label:null,innerHTML:null,multiple:!0,accept:null,name:"file"},b.inherits(c,{constructor:e,init:function(){var b=this,c=b.options,e=c.button;e.addClass("webuploader-pick"),b.on("all",function(a){var g;switch(a){case"mouseenter":e.addClass("webuploader-pick-hover");break;case"mouseleave":e.removeClass("webuploader-pick-hover");break;case"change":g=b.exec("getFiles"),b.trigger("select",f.map(g,function(a){return a=new d(b.getRuid(),a),a._refer=c.container,a}),c.container)}}),b.connectRuntime(c,function(){b.refresh(),b.exec("init",c),b.trigger("ready")}),f(a).on("resize",function(){b.refresh()})},refresh:function(){var a=this.getRuntime().getContainer(),b=this.options.button,c=b.outerWidth?b.outerWidth():b.width(),d=b.outerHeight?b.outerHeight():b.height(),e=b.offset();c&&d&&a.css({bottom:"auto",right:"auto",width:c+"px",height:d+"px"}).offset(e)},enable:function(){var a=this.options.button;a.removeClass("webuploader-pick-disable"),this.refresh()},disable:function(){var a=this.options.button;this.getRuntime().getContainer().css({top:"-99999px"}),a.addClass("webuploader-pick-disable")},destroy:function(){this.runtime&&(this.exec("destroy"),this.disconnectRuntime())}}),e}),b("widgets/filepicker",["base","uploader","lib/filepicker","widgets/widget"],function(a,b,c){var d=a.$;return d.extend(b.options,{pick:null,accept:null}),b.register({"add-btn":"addButton",refresh:"refresh",disable:"disable",enable:"enable"},{init:function(a){return this.pickers=[],a.pick&&this.addButton(a.pick)},refresh:function(){d.each(this.pickers,function(){this.refresh()})},addButton:function(b){var e,f,g,h=this,i=h.options,j=i.accept;if(b)return g=a.Deferred(),d.isPlainObject(b)||(b={id:b}),e=d.extend({},b,{accept:d.isPlainObject(j)?[j]:j,swf:i.swf,runtimeOrder:i.runtimeOrder}),f=new c(e),f.once("ready",g.resolve),f.on("select",function(a){h.owner.request("add-file",[a])}),f.init(),this.pickers.push(f),g.promise()},disable:function(){d.each(this.pickers,function(){this.disable()})},enable:function(){d.each(this.pickers,function(){this.enable()})}})}),b("lib/image",["base","runtime/client","lib/blob"],function(a,b,c){function d(a){this.options=e.extend({},d.options,a),b.call(this,"Image"),this.on("load",function(){this._info=this.exec("info"),this._meta=this.exec("meta")})}var e=a.$;return d.options={quality:90,crop:!1,preserveHeaders:!0,allowMagnify:!0},a.inherits(b,{constructor:d,info:function(a){return a?(this._info=a,this):this._info},meta:function(a){return a?(this._meta=a,this):this._meta},loadFromBlob:function(a){var b=this,c=a.getRuid();this.connectRuntime(c,function(){b.exec("init",b.options),b.exec("loadFromBlob",a)})},resize:function(){var b=a.slice(arguments);return this.exec.apply(this,["resize"].concat(b))},getAsDataUrl:function(a){return this.exec("getAsDataUrl",a)},getAsBlob:function(a){var b=this.exec("getAsBlob",a);return new c(this.getRuid(),b)}}),d}),b("widgets/image",["base","uploader","lib/image","widgets/widget"],function(a,b,c){var d,e=a.$;return d=function(a){var b=0,c=[],d=function(){for(var d;c.length&&a>b;)d=c.shift(),b+=d[0],d[1]()};return function(a,e,f){c.push([e,f]),a.once("destroy",function(){b-=e,setTimeout(d,1)}),setTimeout(d,1)}}(5242880),e.extend(b.options,{thumb:{width:110,height:110,quality:70,allowMagnify:!0,crop:!0,preserveHeaders:!1,type:"image/jpeg"},compress:{width:1600,height:1600,quality:90,allowMagnify:!1,crop:!1,preserveHeaders:!0}}),b.register({"make-thumb":"makeThumb","before-send-file":"compressImage"},{makeThumb:function(a,b,f,g){var h,i;return a=this.request("get-file",a),a.type.match(/^image/)?(h=e.extend({},this.options.thumb),e.isPlainObject(f)&&(h=e.extend(h,f),f=null),f=f||h.width,g=g||h.height,i=new c(h),i.once("load",function(){a._info=a._info||i.info(),a._meta=a._meta||i.meta(),i.resize(f,g)}),i.once("complete",function(){b(!1,i.getAsDataUrl(h.type)),i.destroy()}),i.once("error",function(){b(!0),i.destroy()}),void d(i,a.source.size,function(){a._info&&i.info(a._info),a._meta&&i.meta(a._meta),i.loadFromBlob(a.source)})):void b(!0)},compressImage:function(b){var d,f,g=this.options.compress||this.options.resize,h=g&&g.compressSize||307200;return b=this.request("get-file",b),!g||!~"image/jpeg,image/jpg".indexOf(b.type)||b.size<h||b._compressed?void 0:(g=e.extend({},g),f=a.Deferred(),d=new c(g),f.always(function(){d.destroy(),d=null}),d.once("error",f.reject),d.once("load",function(){b._info=b._info||d.info(),b._meta=b._meta||d.meta(),d.resize(g.width,g.height)}),d.once("complete",function(){var a,c;try{a=d.getAsBlob(g.type),c=b.size,a.size<c&&(b.source=a,b.size=a.size,b.trigger("resize",a.size,c)),b._compressed=!0,f.resolve()}catch(e){f.resolve()}}),b._info&&d.info(b._info),b._meta&&d.meta(b._meta),d.loadFromBlob(b.source),f.promise())}})}),b("file",["base","mediator"],function(a,b){function c(){return f+g++}function d(a){this.name=a.name||"Untitled",this.size=a.size||0,this.type=a.type||"application",this.lastModifiedDate=a.lastModifiedDate||1*new Date,this.id=c(),this.ext=h.exec(this.name)?RegExp.$1:"",this.statusText="",i[this.id]=d.Status.INITED,this.source=a,this.loaded=0,this.on("error",function(a){this.setStatus(d.Status.ERROR,a)})}var e=a.$,f="WU_FILE_",g=0,h=/\.([^.]+)$/,i={};return e.extend(d.prototype,{setStatus:function(a,b){var c=i[this.id];"undefined"!=typeof b&&(this.statusText=b),a!==c&&(i[this.id]=a,this.trigger("statuschange",a,c))},getStatus:function(){return i[this.id]},getSource:function(){return this.source},destory:function(){delete i[this.id]}}),b.installTo(d.prototype),d.Status={INITED:"inited",QUEUED:"queued",PROGRESS:"progress",ERROR:"error",COMPLETE:"complete",CANCELLED:"cancelled",INTERRUPT:"interrupt",INVALID:"invalid"},d}),b("queue",["base","mediator","file"],function(a,b,c){function d(){this.stats={numOfQueue:0,numOfSuccess:0,numOfCancel:0,numOfProgress:0,numOfUploadFailed:0,numOfInvalid:0},this._queue=[],this._map={}}var e=a.$,f=c.Status;return e.extend(d.prototype,{append:function(a){return this._queue.push(a),this._fileAdded(a),this},prepend:function(a){return this._queue.unshift(a),this._fileAdded(a),this},getFile:function(a){return"string"!=typeof a?a:this._map[a]},fetch:function(a){var b,c,d=this._queue.length;for(a=a||f.QUEUED,b=0;d>b;b++)if(c=this._queue[b],a===c.getStatus())return c;return null},sort:function(a){"function"==typeof a&&this._queue.sort(a)},getFiles:function(){for(var a,b=[].slice.call(arguments,0),c=[],d=0,f=this._queue.length;f>d;d++)a=this._queue[d],(!b.length||~e.inArray(a.getStatus(),b))&&c.push(a);return c},_fileAdded:function(a){var b=this,c=this._map[a.id];c||(this._map[a.id]=a,a.on("statuschange",function(a,c){b._onFileStatusChange(a,c)})),a.setStatus(f.QUEUED)},_onFileStatusChange:function(a,b){var c=this.stats;switch(b){case f.PROGRESS:c.numOfProgress--;break;case f.QUEUED:c.numOfQueue--;break;case f.ERROR:c.numOfUploadFailed--;break;case f.INVALID:c.numOfInvalid--}switch(a){case f.QUEUED:c.numOfQueue++;break;case f.PROGRESS:c.numOfProgress++;break;case f.ERROR:c.numOfUploadFailed++;break;case f.COMPLETE:c.numOfSuccess++;break;case f.CANCELLED:c.numOfCancel++;break;case f.INVALID:c.numOfInvalid++}}}),b.installTo(d.prototype),d}),b("widgets/queue",["base","uploader","queue","file","lib/file","runtime/client","widgets/widget"],function(a,b,c,d,e,f){var g=a.$,h=/\.\w+$/,i=d.Status;return b.register({"sort-files":"sortFiles","add-file":"addFiles","get-file":"getFile","fetch-file":"fetchFile","get-stats":"getStats","get-files":"getFiles","remove-file":"removeFile",retry:"retry",reset:"reset","accept-file":"acceptFile"},{init:function(b){var d,e,h,i,j,k,l,m=this;if(g.isPlainObject(b.accept)&&(b.accept=[b.accept]),b.accept){for(j=[],h=0,e=b.accept.length;e>h;h++)i=b.accept[h].extensions,i&&j.push(i);j.length&&(k="\\."+j.join(",").replace(/,/g,"$|\\.").replace(/\*/g,".*")+"$"),m.accept=new RegExp(k,"i")}return m.queue=new c,m.stats=m.queue.stats,"html5"===this.request("predict-runtime-type")?(d=a.Deferred(),l=new f("Placeholder"),l.connectRuntime({runtimeOrder:"html5"},function(){m._ruid=l.getRuid(),d.resolve()}),d.promise()):void 0},_wrapFile:function(a){if(!(a instanceof d)){if(!(a instanceof e)){if(!this._ruid)throw new Error("Can't add external files.");a=new e(this._ruid,a)}a=new d(a)}return a},acceptFile:function(a){var b=!a||a.size<6||this.accept&&h.exec(a.name)&&!this.accept.test(a.name);return!b},_addFile:function(a){var b=this;return a=b._wrapFile(a),b.owner.trigger("beforeFileQueued",a)?b.acceptFile(a)?(b.queue.append(a),b.owner.trigger("fileQueued",a),a):void b.owner.trigger("error","Q_TYPE_DENIED",a):void 0},getFile:function(a){return this.queue.getFile(a)},addFiles:function(a){var b=this;a.length||(a=[a]),a=g.map(a,function(a){return b._addFile(a)}),b.owner.trigger("filesQueued",a),b.options.auto&&b.request("start-upload")},getStats:function(){return this.stats},removeFile:function(a){var b=this;a=a.id?a:b.queue.getFile(a),a.setStatus(i.CANCELLED),b.owner.trigger("fileDequeued",a)},getFiles:function(){return this.queue.getFiles.apply(this.queue,arguments)},fetchFile:function(){return this.queue.fetch.apply(this.queue,arguments)},retry:function(a,b){var c,d,e,f=this;if(a)return a=a.id?a:f.queue.getFile(a),a.setStatus(i.QUEUED),void(b||f.request("start-upload"));for(c=f.queue.getFiles(i.ERROR),d=0,e=c.length;e>d;d++)a=c[d],a.setStatus(i.QUEUED);f.request("start-upload")},sortFiles:function(){return this.queue.sort.apply(this.queue,arguments)},reset:function(){this.queue=new c,this.stats=this.queue.stats}})}),b("widgets/runtime",["uploader","runtime/runtime","widgets/widget"],function(a,b){return a.support=function(){return b.hasRuntime.apply(b,arguments)},a.register({"predict-runtime-type":"predictRuntmeType"},{init:function(){if(!this.predictRuntmeType())throw Error("Runtime Error")},predictRuntmeType:function(){var a,c,d=this.options.runtimeOrder||b.orders,e=this.type;if(!e)for(d=d.split(/\s*,\s*/g),a=0,c=d.length;c>a;a++)if(b.hasRuntime(d[a])){this.type=e=d[a];break}return e}})}),b("lib/transport",["base","runtime/client","mediator"],function(a,b,c){function d(a){var c=this;a=c.options=e.extend(!0,{},d.options,a||{}),b.call(this,"Transport"),this._blob=null,this._formData=a.formData||{},this._headers=a.headers||{},this.on("progress",this._timeout),this.on("load error",function(){c.trigger("progress",1),clearTimeout(c._timer)})}var e=a.$;return d.options={server:"",method:"POST",withCredentials:!1,fileVal:"file",timeout:12e4,formData:{},headers:{},sendAsBinary:!1},e.extend(d.prototype,{appendBlob:function(a,b,c){var d=this,e=d.options;d.getRuid()&&d.disconnectRuntime(),d.connectRuntime(b.ruid,function(){d.exec("init")}),d._blob=b,e.fileVal=a||e.fileVal,e.filename=c||e.filename},append:function(a,b){"object"==typeof a?e.extend(this._formData,a):this._formData[a]=b},setRequestHeader:function(a,b){"object"==typeof a?e.extend(this._headers,a):this._headers[a]=b},send:function(a){this.exec("send",a),this._timeout()},abort:function(){return clearTimeout(this._timer),this.exec("abort")},destroy:function(){this.trigger("destroy"),this.off(),this.exec("destroy"),this.disconnectRuntime()},getResponse:function(){return this.exec("getResponse")},getResponseAsJson:function(){return this.exec("getResponseAsJson")},getStatus:function(){return this.exec("getStatus")},_timeout:function(){var a=this,b=a.options.timeout;b&&(clearTimeout(a._timer),a._timer=setTimeout(function(){a.abort(),a.trigger("error","timeout")},b))}}),c.installTo(d.prototype),d}),b("widgets/upload",["base","uploader","file","lib/transport","widgets/widget"],function(a,b,c,d){function e(a,b){for(var c,d=[],e=a.source,f=e.size,g=b?Math.ceil(f/b):1,h=0,i=0;g>i;)c=Math.min(b,f-h),d.push({file:a,start:h,end:b?h+c:f,total:f,chunks:g,chunk:i++}),h+=c;return a.blocks=d.concat(),a.remaning=d.length,{file:a,has:function(){return!!d.length},fetch:function(){return d.shift()}}}var f=a.$,g=a.isPromise,h=c.Status;f.extend(b.options,{prepareNextFile:!1,chunked:!1,chunkSize:5242880,chunkRetry:2,threads:3,formData:null}),b.register({"start-upload":"start","stop-upload":"stop","skip-file":"skipFile","is-in-progress":"isInProgress"},{init:function(){var b=this.owner;this.runing=!1,this.pool=[],this.pending=[],this.remaning=0,this.__tick=a.bindFn(this._tick,this),b.on("uploadComplete",function(a){a.blocks&&f.each(a.blocks,function(a,b){b.transport&&(b.transport.abort(),b.transport.destroy()),delete b.transport}),delete a.blocks,delete a.remaning})},start:function(){var b=this;f.each(b.request("get-files",h.INVALID),function(){b.request("remove-file",this)}),b.runing||(b.runing=!0,f.each(b.pool,function(a,c){var d=c.file;d.getStatus()===h.INTERRUPT&&(d.setStatus(h.PROGRESS),b._trigged=!1,c.transport&&c.transport.send())}),b._trigged=!1,b.owner.trigger("startUpload"),a.nextTick(b.__tick))},stop:function(a){var b=this;b.runing!==!1&&(b.runing=!1,a&&f.each(b.pool,function(a,b){b.transport&&b.transport.abort(),b.file.setStatus(h.INTERRUPT)}),b.owner.trigger("stopUpload"))},isInProgress:function(){return!!this.runing},getStats:function(){return this.request("get-stats")},skipFile:function(a,b){a=this.request("get-file",a),a.setStatus(b||h.COMPLETE),a.skipped=!0,a.blocks&&f.each(a.blocks,function(a,b){var c=b.transport;c&&(c.abort(),c.destroy(),delete b.transport)}),this.owner.trigger("uploadSkip",a)},_tick:function(){var b,c,d=this,e=d.options;return d._promise?d._promise.always(d.__tick):void(d.pool.length<e.threads&&(c=d._nextBlock())?(d._trigged=!1,b=function(b){d._promise=null,b&&b.file&&d._startSend(b),a.nextTick(d.__tick)},d._promise=g(c)?c.always(b):b(c)):d.remaning||d.getStats().numOfQueue||(d.runing=!1,d._trigged||a.nextTick(function(){d.owner.trigger("uploadFinished")}),d._trigged=!0))},_nextBlock:function(){var a,b,c=this,d=c._act,f=c.options;return d&&d.has()&&d.file.getStatus()===h.PROGRESS?(f.prepareNextFile&&!c.pending.length&&c._prepareNextFile(),d.fetch()):c.runing?(!c.pending.length&&c.getStats().numOfQueue&&c._prepareNextFile(),a=c.pending.shift(),b=function(a){return a?(d=e(a,f.chunked?f.chunkSize:0),c._act=d,d.fetch()):null},g(a)?a[a.pipe?"pipe":"then"](b):b(a)):void 0},_prepareNextFile:function(){var a,b=this,c=b.request("fetch-file"),d=b.pending;c&&(a=b.request("before-send-file",c,function(){return c.getStatus()===h.QUEUED?(b.owner.trigger("uploadStart",c),c.setStatus(h.PROGRESS),c):b._finishFile(c)}),a.done(function(){var b=f.inArray(a,d);~b&&d.splice(b,1,c)}),a.fail(function(a){c.setStatus(h.ERROR,a),b.owner.trigger("uploadError",c,a),b.owner.trigger("uploadComplete",c)}),d.push(a))},_popBlock:function(a){var b=f.inArray(a,this.pool);this.pool.splice(b,1),a.file.remaning--,this.remaning--},_startSend:function(b){var c,d=this,e=b.file;d.pool.push(b),d.remaning++,b.blob=1===b.chunks?e.source:e.source.slice(b.start,b.end),c=d.request("before-send",b,function(){e.getStatus()===h.PROGRESS?d._doSend(b):(d._popBlock(b),a.nextTick(d.__tick))}),c.fail(function(){1===e.remaning?d._finishFile(e).always(function(){b.percentage=1,d._popBlock(b),d.owner.trigger("uploadComplete",e),a.nextTick(d.__tick)}):(b.percentage=1,d._popBlock(b),a.nextTick(d.__tick))})},_doSend:function(b){var c,e,g=this,i=g.owner,j=g.options,k=b.file,l=new d(j),m=f.extend({},j.formData),n=f.extend({},j.headers);b.transport=l,l.on("destroy",function(){delete b.transport,g._popBlock(b),a.nextTick(g.__tick)}),l.on("progress",function(a){var c=0,d=0;c=b.percentage=a,b.chunks>1&&(f.each(k.blocks,function(a,b){d+=(b.percentage||0)*(b.end-b.start)}),c=d/k.size),i.trigger("uploadProgress",k,c||0)}),c=function(a){var c;return e=l.getResponseAsJson()||{},e._raw=l.getResponse(),c=function(b){a=b},i.trigger("uploadAccept",b,e,c)||(a=a||"server"),a},l.on("error",function(a,d){b.retried=b.retried||0,b.chunks>1&&~"http,abort".indexOf(a)&&b.retried<j.chunkRetry?(b.retried++,l.send()):(d||"server"!==a||(a=c(a)),k.setStatus(h.ERROR,a),i.trigger("uploadError",k,a),i.trigger("uploadComplete",k))}),l.on("load",function(){var a;return(a=c())?void l.trigger("error",a,!0):void(1===k.remaning?g._finishFile(k,e):l.destroy())}),m=f.extend(m,{id:k.id,name:k.name,type:k.type,lastModifiedDate:k.lastModifiedDate,size:k.size}),b.chunks>1&&f.extend(m,{chunks:b.chunks,chunk:b.chunk}),i.trigger("uploadBeforeSend",b,m,n),l.appendBlob(j.fileVal,b.blob,k.name),l.append(m),l.setRequestHeader(n),l.send()},_finishFile:function(a,b,c){var d=this.owner;return d.request("after-send-file",arguments,function(){a.setStatus(h.COMPLETE),d.trigger("uploadSuccess",a,b,c)}).fail(function(b){a.getStatus()===h.PROGRESS&&a.setStatus(h.ERROR,b),d.trigger("uploadError",a,b)}).always(function(){d.trigger("uploadComplete",a)})}})}),b("widgets/validator",["base","uploader","file","widgets/widget"],function(a,b,c){var d,e=a.$,f={};return d={addValidator:function(a,b){f[a]=b},removeValidator:function(a){delete f[a]}},b.register({init:function(){var a=this;e.each(f,function(){this.call(a.owner)})}}),d.addValidator("fileNumLimit",function(){var a=this,b=a.options,c=0,d=b.fileNumLimit>>0,e=!0;d&&(a.on("beforeFileQueued",function(a){return c>=d&&e&&(e=!1,this.trigger("error","Q_EXCEED_NUM_LIMIT",d,a),setTimeout(function(){e=!0},1)),c>=d?!1:!0}),a.on("fileQueued",function(){c++}),a.on("fileDequeued",function(){c--}),a.on("uploadFinished",function(){c=0}))}),d.addValidator("fileSizeLimit",function(){var a=this,b=a.options,c=0,d=b.fileSizeLimit>>0,e=!0;d&&(a.on("beforeFileQueued",function(a){var b=c+a.size>d;return b&&e&&(e=!1,this.trigger("error","Q_EXCEED_SIZE_LIMIT",d,a),setTimeout(function(){e=!0},1)),b?!1:!0}),a.on("fileQueued",function(a){c+=a.size}),a.on("fileDequeued",function(a){c-=a.size}),a.on("uploadFinished",function(){c=0}))}),d.addValidator("fileSingleSizeLimit",function(){var a=this,b=a.options,d=b.fileSingleSizeLimit;d&&a.on("beforeFileQueued",function(a){return a.size>d?(a.setStatus(c.Status.INVALID,"exceed_size"),this.trigger("error","F_EXCEED_SIZE",a),!1):void 0})}),d.addValidator("duplicate",function(){function a(a){for(var b,c=0,d=0,e=a.length;e>d;d++)b=a.charCodeAt(d),c=b+(c<<6)+(c<<16)-c;return c}var b=this,c=b.options,d={};c.duplicate||(b.on("beforeFileQueued",function(b){var c=b.__hash||(b.__hash=a(b.name+b.size+b.lastModifiedDate));return d[c]?(this.trigger("error","F_DUPLICATE",b),!1):void 0}),b.on("fileQueued",function(a){var b=a.__hash;b&&(d[b]=!0)}),b.on("fileDequeued",function(a){var b=a.__hash;b&&delete d[b]}))}),d}),b("runtime/compbase",[],function(){function a(a,b){this.owner=a,this.options=a.options,this.getRuntime=function(){return b},this.getRuid=function(){return b.uid},this.trigger=function(){return a.trigger.apply(a,arguments)}}return a}),b("runtime/html5/runtime",["base","runtime/runtime","runtime/compbase"],function(b,c,d){function e(){var a={},d=this,e=this.destory;c.apply(d,arguments),d.type=f,d.exec=function(c,e){var f,h=this,i=h.uid,j=b.slice(arguments,2);return g[c]&&(f=a[i]=a[i]||new g[c](h,d),f[e])?f[e].apply(f,j):void 0},d.destory=function(){return e&&e.apply(this,arguments)}}var f="html5",g={};return b.inherits(c,{constructor:e,init:function(){var a=this;setTimeout(function(){a.trigger("ready")},1)}}),e.register=function(a,c){var e=g[a]=b.inherits(d,c);return e},a.Blob&&a.FileReader&&a.DataView&&c.addRuntime(f,e),e}),b("runtime/html5/blob",["runtime/html5/runtime","lib/blob"],function(a,b){return a.register("Blob",{slice:function(a,c){var d=this.owner.source,e=d.slice||d.webkitSlice||d.mozSlice;return d=e.call(d,a,c),new b(this.getRuid(),d)}})}),b("runtime/html5/dnd",["base","runtime/html5/runtime","lib/file"],function(a,b,c){var d=a.$,e="webuploader-dnd-";return b.register("DragAndDrop",{init:function(){var b=this.elem=this.options.container;this.dragEnterHandler=a.bindFn(this._dragEnterHandler,this),this.dragOverHandler=a.bindFn(this._dragOverHandler,this),this.dragLeaveHandler=a.bindFn(this._dragLeaveHandler,this),this.dropHandler=a.bindFn(this._dropHandler,this),this.dndOver=!1,b.on("dragenter",this.dragEnterHandler),b.on("dragover",this.dragOverHandler),b.on("dragleave",this.dragLeaveHandler),b.on("drop",this.dropHandler),this.options.disableGlobalDnd&&(d(document).on("dragover",this.dragOverHandler),d(document).on("drop",this.dropHandler))
2
+ },_dragEnterHandler:function(a){var b,c=this,d=c._denied||!1;return a=a.originalEvent||a,c.dndOver||(c.dndOver=!0,b=a.dataTransfer.items,b&&b.length&&(c._denied=d=!c.trigger("accept",b)),c.elem.addClass(e+"over"),c.elem[d?"addClass":"removeClass"](e+"denied")),a.dataTransfer.dropEffect=d?"none":"copy",!1},_dragOverHandler:function(a){var b=this.elem.parent().get(0);return b&&!d.contains(b,a.currentTarget)?!1:(clearTimeout(this._leaveTimer),this._dragEnterHandler.call(this,a),!1)},_dragLeaveHandler:function(){var a,b=this;return a=function(){b.dndOver=!1,b.elem.removeClass(e+"over "+e+"denied")},clearTimeout(b._leaveTimer),b._leaveTimer=setTimeout(a,100),!1},_dropHandler:function(a){var b=this,f=b.getRuid(),g=b.elem.parent().get(0);return g&&!d.contains(g,a.currentTarget)?!1:(b._getTansferFiles(a,function(a){b.trigger("drop",d.map(a,function(a){return new c(f,a)}))}),b.dndOver=!1,b.elem.removeClass(e+"over"),!1)},_getTansferFiles:function(b,c){var d,e,f,g,h,i,j,k,l=[],m=[];for(b=b.originalEvent||b,f=b.dataTransfer,d=f.items,e=f.files,k=!(!d||!d[0].webkitGetAsEntry),i=0,j=e.length;j>i;i++)g=e[i],h=d&&d[i],k&&h.webkitGetAsEntry().isDirectory?m.push(this._traverseDirectoryTree(h.webkitGetAsEntry(),l)):l.push(g);a.when.apply(a,m).done(function(){l.length&&c(l)})},_traverseDirectoryTree:function(b,c){var d=a.Deferred(),e=this;return b.isFile?b.file(function(a){c.push(a),d.resolve()}):b.isDirectory&&b.createReader().readEntries(function(b){var f,g=b.length,h=[],i=[];for(f=0;g>f;f++)h.push(e._traverseDirectoryTree(b[f],i));a.when.apply(a,h).then(function(){c.push.apply(c,i),d.resolve()},d.reject)}),d.promise()},destroy:function(){var a=this.elem;a.off("dragenter",this.dragEnterHandler),a.off("dragover",this.dragEnterHandler),a.off("dragleave",this.dragLeaveHandler),a.off("drop",this.dropHandler),this.options.disableGlobalDnd&&(d(document).off("dragover",this.dragOverHandler),d(document).off("drop",this.dropHandler))}})}),b("runtime/html5/filepaste",["base","runtime/html5/runtime","lib/file"],function(a,b,c){return b.register("FilePaste",{init:function(){var b,c,d,e,f=this.options,g=this.elem=f.container,h=".*";if(f.accept){for(b=[],c=0,d=f.accept.length;d>c;c++)e=f.accept[c].mimeTypes,e&&b.push(e);b.length&&(h=b.join(","),h=h.replace(/,/g,"|").replace(/\*/g,".*"))}this.accept=h=new RegExp(h,"i"),this.hander=a.bindFn(this._pasteHander,this),g.on("paste",this.hander)},_pasteHander:function(a){var b,d,e,f,g,h=[],i=this.getRuid();for(a=a.originalEvent||a,b=a.clipboardData.items,f=0,g=b.length;g>f;f++)d=b[f],"file"===d.kind&&(e=d.getAsFile())&&h.push(new c(i,e));h.length&&(a.preventDefault(),a.stopPropagation(),this.trigger("paste",h))},destroy:function(){this.elem.off("paste",this.hander)}})}),b("runtime/html5/filepicker",["base","runtime/html5/runtime"],function(a,b){var c=a.$;return b.register("FilePicker",{init:function(){var a,b,d,e,f=this.getRuntime().getContainer(),g=this,h=g.owner,i=g.options,j=c(document.createElement("label")),k=c(document.createElement("input"));if(k.attr("type","file"),k.attr("name",i.name),k.addClass("webuploader-element-invisible"),j.on("click",function(){k.trigger("click")}),j.css({opacity:0,width:"100%",height:"100%",display:"block",cursor:"pointer",background:"#ffffff"}),i.multiple&&k.attr("multiple","multiple"),i.accept&&i.accept.length>0){for(a=[],b=0,d=i.accept.length;d>b;b++)a.push(i.accept[b].mimeTypes);k.attr("accept",a.join(","))}f.append(k),f.append(j),e=function(a){h.trigger(a.type)},k.on("change",function(a){var b,d=arguments.callee;g.files=a.target.files,b=this.cloneNode(!0),this.parentNode.replaceChild(b,this),k.off(),k=c(b).on("change",d).on("mouseenter mouseleave",e),h.trigger("change")}),j.on("mouseenter mouseleave",e)},getFiles:function(){return this.files},destroy:function(){}})}),b("runtime/html5/util",["base"],function(b){var c=a.createObjectURL&&a||a.URL&&URL.revokeObjectURL&&URL||a.webkitURL,d=b.noop,e=d;return c&&(d=function(){return c.createObjectURL.apply(c,arguments)},e=function(){return c.revokeObjectURL.apply(c,arguments)}),{createObjectURL:d,revokeObjectURL:e,dataURL2Blob:function(a){var b,c,d,e,f,g;for(g=a.split(","),b=~g[0].indexOf("base64")?atob(g[1]):decodeURIComponent(g[1]),d=new ArrayBuffer(b.length),c=new Uint8Array(d),e=0;e<b.length;e++)c[e]=b.charCodeAt(e);return f=g[0].split(":")[1].split(";")[0],this.arrayBufferToBlob(d,f)},dataURL2ArrayBuffer:function(a){var b,c,d,e;for(e=a.split(","),b=~e[0].indexOf("base64")?atob(e[1]):decodeURIComponent(e[1]),c=new Uint8Array(b.length),d=0;d<b.length;d++)c[d]=b.charCodeAt(d);return c.buffer},arrayBufferToBlob:function(b,c){var d,e=a.BlobBuilder||a.WebKitBlobBuilder;return e?(d=new e,d.append(b),d.getBlob(c)):new Blob([b],c?{type:c}:{})},canvasToDataUrl:function(a,b,c){return a.toDataURL(b,c/100)},parseMeta:function(a,b){b(!1,{})},updateImageHead:function(a){return a}}}),b("runtime/html5/imagemeta",["runtime/html5/util"],function(a){var b;return b={parsers:{65505:[]},maxMetaDataSize:262144,parse:function(a,b){var c=this,d=new FileReader;d.onload=function(){b(!1,c._parse(this.result)),d=d.onload=d.onerror=null},d.onerror=function(a){b(a.message),d=d.onload=d.onerror=null},a=a.slice(0,c.maxMetaDataSize),d.readAsArrayBuffer(a.getSource())},_parse:function(a,c){if(!(a.byteLength<6)){var d,e,f,g,h=new DataView(a),i=2,j=h.byteLength-4,k=i,l={};if(65496===h.getUint16(0)){for(;j>i&&(d=h.getUint16(i),d>=65504&&65519>=d||65534===d)&&(e=h.getUint16(i+2)+2,!(i+e>h.byteLength));){if(f=b.parsers[d],!c&&f)for(g=0;g<f.length;g+=1)f[g].call(b,h,i,e,l);i+=e,k=i}k>6&&(l.imageHead=a.slice?a.slice(2,k):new Uint8Array(a).subarray(2,k))}return l}},updateImageHead:function(a,b){var c,d,e,f=this._parse(a,!0);return e=2,f.imageHead&&(e=2+f.imageHead.byteLength),d=a.slice?a.slice(e):new Uint8Array(a).subarray(e),c=new Uint8Array(b.byteLength+2+d.byteLength),c[0]=255,c[1]=216,c.set(new Uint8Array(b),2),c.set(new Uint8Array(d),b.byteLength+2),c.buffer}},a.parseMeta=function(){return b.parse.apply(b,arguments)},a.updateImageHead=function(){return b.updateImageHead.apply(b,arguments)},b}),b("runtime/html5/imagemeta/exif",["base","runtime/html5/imagemeta"],function(a,b){var c={};return c.ExifMap=function(){return this},c.ExifMap.prototype.map={Orientation:274},c.ExifMap.prototype.get=function(a){return this[a]||this[this.map[a]]},c.exifTagTypes={1:{getValue:function(a,b){return a.getUint8(b)},size:1},2:{getValue:function(a,b){return String.fromCharCode(a.getUint8(b))},size:1,ascii:!0},3:{getValue:function(a,b,c){return a.getUint16(b,c)},size:2},4:{getValue:function(a,b,c){return a.getUint32(b,c)},size:4},5:{getValue:function(a,b,c){return a.getUint32(b,c)/a.getUint32(b+4,c)},size:8},9:{getValue:function(a,b,c){return a.getInt32(b,c)},size:4},10:{getValue:function(a,b,c){return a.getInt32(b,c)/a.getInt32(b+4,c)},size:8}},c.exifTagTypes[7]=c.exifTagTypes[1],c.getExifValue=function(b,d,e,f,g,h){var i,j,k,l,m,n,o=c.exifTagTypes[f];if(!o)return void a.log("Invalid Exif data: Invalid tag type.");if(i=o.size*g,j=i>4?d+b.getUint32(e+8,h):e+8,j+i>b.byteLength)return void a.log("Invalid Exif data: Invalid data offset.");if(1===g)return o.getValue(b,j,h);for(k=[],l=0;g>l;l+=1)k[l]=o.getValue(b,j+l*o.size,h);if(o.ascii){for(m="",l=0;l<k.length&&(n=k[l],"\x00"!==n);l+=1)m+=n;return m}return k},c.parseExifTag=function(a,b,d,e,f){var g=a.getUint16(d,e);f.exif[g]=c.getExifValue(a,b,d,a.getUint16(d+2,e),a.getUint32(d+4,e),e)},c.parseExifTags=function(b,c,d,e,f){var g,h,i;if(d+6>b.byteLength)return void a.log("Invalid Exif data: Invalid directory offset.");if(g=b.getUint16(d,e),h=d+2+12*g,h+4>b.byteLength)return void a.log("Invalid Exif data: Invalid directory size.");for(i=0;g>i;i+=1)this.parseExifTag(b,c,d+2+12*i,e,f);return b.getUint32(h,e)},c.parseExifData=function(b,d,e,f){var g,h,i=d+10;if(1165519206===b.getUint32(d+4)){if(i+8>b.byteLength)return void a.log("Invalid Exif data: Invalid segment size.");if(0!==b.getUint16(d+8))return void a.log("Invalid Exif data: Missing byte alignment offset.");switch(b.getUint16(i)){case 18761:g=!0;break;case 19789:g=!1;break;default:return void a.log("Invalid Exif data: Invalid byte alignment marker.")}if(42!==b.getUint16(i+2,g))return void a.log("Invalid Exif data: Missing TIFF marker.");h=b.getUint32(i+4,g),f.exif=new c.ExifMap,h=c.parseExifTags(b,i,i+h,g,f)}},b.parsers[65505].push(c.parseExifData),c}),b("runtime/html5/jpegencoder",[],function(){function a(a){function b(a){for(var b=[16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99],c=0;64>c;c++){var d=y((b[c]*a+50)/100);1>d?d=1:d>255&&(d=255),z[P[c]]=d}for(var e=[17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99],f=0;64>f;f++){var g=y((e[f]*a+50)/100);1>g?g=1:g>255&&(g=255),A[P[f]]=g}for(var h=[1,1.387039845,1.306562965,1.175875602,1,.785694958,.5411961,.275899379],i=0,j=0;8>j;j++)for(var k=0;8>k;k++)B[i]=1/(z[P[i]]*h[j]*h[k]*8),C[i]=1/(A[P[i]]*h[j]*h[k]*8),i++}function c(a,b){for(var c=0,d=0,e=new Array,f=1;16>=f;f++){for(var g=1;g<=a[f];g++)e[b[d]]=[],e[b[d]][0]=c,e[b[d]][1]=f,d++,c++;c*=2}return e}function d(){t=c(Q,R),u=c(U,V),v=c(S,T),w=c(W,X)}function e(){for(var a=1,b=2,c=1;15>=c;c++){for(var d=a;b>d;d++)E[32767+d]=c,D[32767+d]=[],D[32767+d][1]=c,D[32767+d][0]=d;for(var e=-(b-1);-a>=e;e++)E[32767+e]=c,D[32767+e]=[],D[32767+e][1]=c,D[32767+e][0]=b-1+e;a<<=1,b<<=1}}function f(){for(var a=0;256>a;a++)O[a]=19595*a,O[a+256>>0]=38470*a,O[a+512>>0]=7471*a+32768,O[a+768>>0]=-11059*a,O[a+1024>>0]=-21709*a,O[a+1280>>0]=32768*a+8421375,O[a+1536>>0]=-27439*a,O[a+1792>>0]=-5329*a}function g(a){for(var b=a[0],c=a[1]-1;c>=0;)b&1<<c&&(I|=1<<J),c--,J--,0>J&&(255==I?(h(255),h(0)):h(I),J=7,I=0)}function h(a){H.push(N[a])}function i(a){h(a>>8&255),h(255&a)}function j(a,b){var c,d,e,f,g,h,i,j,k,l=0,m=8,n=64;for(k=0;m>k;++k){c=a[l],d=a[l+1],e=a[l+2],f=a[l+3],g=a[l+4],h=a[l+5],i=a[l+6],j=a[l+7];var o=c+j,p=c-j,q=d+i,r=d-i,s=e+h,t=e-h,u=f+g,v=f-g,w=o+u,x=o-u,y=q+s,z=q-s;a[l]=w+y,a[l+4]=w-y;var A=.707106781*(z+x);a[l+2]=x+A,a[l+6]=x-A,w=v+t,y=t+r,z=r+p;var B=.382683433*(w-z),C=.5411961*w+B,D=1.306562965*z+B,E=.707106781*y,G=p+E,H=p-E;a[l+5]=H+C,a[l+3]=H-C,a[l+1]=G+D,a[l+7]=G-D,l+=8}for(l=0,k=0;m>k;++k){c=a[l],d=a[l+8],e=a[l+16],f=a[l+24],g=a[l+32],h=a[l+40],i=a[l+48],j=a[l+56];var I=c+j,J=c-j,K=d+i,L=d-i,M=e+h,N=e-h,O=f+g,P=f-g,Q=I+O,R=I-O,S=K+M,T=K-M;a[l]=Q+S,a[l+32]=Q-S;var U=.707106781*(T+R);a[l+16]=R+U,a[l+48]=R-U,Q=P+N,S=N+L,T=L+J;var V=.382683433*(Q-T),W=.5411961*Q+V,X=1.306562965*T+V,Y=.707106781*S,Z=J+Y,$=J-Y;a[l+40]=$+W,a[l+24]=$-W,a[l+8]=Z+X,a[l+56]=Z-X,l++}var _;for(k=0;n>k;++k)_=a[k]*b[k],F[k]=_>0?_+.5|0:_-.5|0;return F}function k(){i(65504),i(16),h(74),h(70),h(73),h(70),h(0),h(1),h(1),h(0),i(1),i(1),h(0),h(0)}function l(a,b){i(65472),i(17),h(8),i(b),i(a),h(3),h(1),h(17),h(0),h(2),h(17),h(1),h(3),h(17),h(1)}function m(){i(65499),i(132),h(0);for(var a=0;64>a;a++)h(z[a]);h(1);for(var b=0;64>b;b++)h(A[b])}function n(){i(65476),i(418),h(0);for(var a=0;16>a;a++)h(Q[a+1]);for(var b=0;11>=b;b++)h(R[b]);h(16);for(var c=0;16>c;c++)h(S[c+1]);for(var d=0;161>=d;d++)h(T[d]);h(1);for(var e=0;16>e;e++)h(U[e+1]);for(var f=0;11>=f;f++)h(V[f]);h(17);for(var g=0;16>g;g++)h(W[g+1]);for(var j=0;161>=j;j++)h(X[j])}function o(){i(65498),i(12),h(3),h(1),h(0),h(2),h(17),h(3),h(17),h(0),h(63),h(0)}function p(a,b,c,d,e){for(var f,h=e[0],i=e[240],k=16,l=63,m=64,n=j(a,b),o=0;m>o;++o)G[P[o]]=n[o];var p=G[0]-c;c=G[0],0==p?g(d[0]):(f=32767+p,g(d[E[f]]),g(D[f]));for(var q=63;q>0&&0==G[q];q--);if(0==q)return g(h),c;for(var r,s=1;q>=s;){for(var t=s;0==G[s]&&q>=s;++s);var u=s-t;if(u>=k){r=u>>4;for(var v=1;r>=v;++v)g(i);u=15&u}f=32767+G[s],g(e[(u<<4)+E[f]]),g(D[f]),s++}return q!=l&&g(h),c}function q(){for(var a=String.fromCharCode,b=0;256>b;b++)N[b]=a(b)}function r(a){if(0>=a&&(a=1),a>100&&(a=100),x!=a){var c=0;c=Math.floor(50>a?5e3/a:200-2*a),b(c),x=a}}function s(){a||(a=50),q(),d(),e(),f(),r(a)}var t,u,v,w,x,y=(Math.round,Math.floor),z=new Array(64),A=new Array(64),B=new Array(64),C=new Array(64),D=new Array(65535),E=new Array(65535),F=new Array(64),G=new Array(64),H=[],I=0,J=7,K=new Array(64),L=new Array(64),M=new Array(64),N=new Array(256),O=new Array(2048),P=[0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63],Q=[0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0],R=[0,1,2,3,4,5,6,7,8,9,10,11],S=[0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125],T=[1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250],U=[0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0],V=[0,1,2,3,4,5,6,7,8,9,10,11],W=[0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119],X=[0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,250];this.encode=function(a,b){b&&r(b),H=new Array,I=0,J=7,i(65496),k(),m(),l(a.width,a.height),n(),o();var c=0,d=0,e=0;I=0,J=7,this.encode.displayName="_encode_";for(var f,h,j,q,s,x,y,z,A,D=a.data,E=a.width,F=a.height,G=4*E,N=0;F>N;){for(f=0;G>f;){for(s=G*N+f,x=s,y=-1,z=0,A=0;64>A;A++)z=A>>3,y=4*(7&A),x=s+z*G+y,N+z>=F&&(x-=G*(N+1+z-F)),f+y>=G&&(x-=f+y-G+4),h=D[x++],j=D[x++],q=D[x++],K[A]=(O[h]+O[j+256>>0]+O[q+512>>0]>>16)-128,L[A]=(O[h+768>>0]+O[j+1024>>0]+O[q+1280>>0]>>16)-128,M[A]=(O[h+1280>>0]+O[j+1536>>0]+O[q+1792>>0]>>16)-128;c=p(K,B,c,t,v),d=p(L,C,d,u,w),e=p(M,C,e,u,w),f+=32}N+=8}if(J>=0){var P=[];P[1]=J+1,P[0]=(1<<J+1)-1,g(P)}i(65497);var Q="data:image/jpeg;base64,"+btoa(H.join(""));return H=[],Q},s()}return a.encode=function(b,c){var d=new a(c);return d.encode(b)},a}),b("runtime/html5/androidpatch",["runtime/html5/util","runtime/html5/jpegencoder","base"],function(a,b,c){var d,e=a.canvasToDataUrl;a.canvasToDataUrl=function(a,f,g){var h,i,j,k,l;return c.os.android?("image/jpeg"===f&&"undefined"==typeof d&&(k=e.apply(null,arguments),l=k.split(","),k=~l[0].indexOf("base64")?atob(l[1]):decodeURIComponent(l[1]),k=k.substring(0,2),d=255===k.charCodeAt(0)&&216===k.charCodeAt(1)),"image/jpeg"!==f||d?e.apply(null,arguments):(i=a.width,j=a.height,h=a.getContext("2d"),b.encode(h.getImageData(0,0,i,j),g))):e.apply(null,arguments)}}),b("runtime/html5/image",["base","runtime/html5/runtime","runtime/html5/util"],function(a,b,c){var d="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D";return b.register("Image",{modified:!1,init:function(){var a=this,b=new Image;b.onload=function(){a._info={type:a.type,width:this.width,height:this.height},a._metas||"image/jpeg"!==a.type?a.owner.trigger("load"):c.parseMeta(a._blob,function(b,c){a._metas=c,a.owner.trigger("load")})},b.onerror=function(){a.owner.trigger("error")},a._img=b},loadFromBlob:function(a){var b=this,d=b._img;b._blob=a,b.type=a.type,d.src=c.createObjectURL(a.getSource()),b.owner.once("load",function(){c.revokeObjectURL(d.src)})},resize:function(a,b){var c=this._canvas||(this._canvas=document.createElement("canvas"));this._resize(this._img,c,a,b),this._blob=null,this.modified=!0,this.owner.trigger("complete")},getAsBlob:function(a){var b,d=this._blob,e=this.options;if(a=a||this.type,this.modified||this.type!==a){if(b=this._canvas,"image/jpeg"===a){if(d=c.canvasToDataUrl(b,"image/jpeg",e.quality),e.preserveHeaders&&this._metas&&this._metas.imageHead)return d=c.dataURL2ArrayBuffer(d),d=c.updateImageHead(d,this._metas.imageHead),d=c.arrayBufferToBlob(d,a)}else d=c.canvasToDataUrl(b,a);d=c.dataURL2Blob(d)}return d},getAsDataUrl:function(a){var b=this.options;return a=a||this.type,"image/jpeg"===a?c.canvasToDataUrl(this._canvas,a,b.quality):this._canvas.toDataURL(a)},getOrientation:function(){return this._metas&&this._metas.exif&&this._metas.exif.get("Orientation")||1},info:function(a){return a?(this._info=a,this):this._info},meta:function(a){return a?(this._meta=a,this):this._meta},destroy:function(){var a=this._canvas;this._img.onload=null,a&&(a.getContext("2d").clearRect(0,0,a.width,a.height),a.width=a.height=0,this._canvas=null),this._img.src=d,this._img=this._blob=null},_resize:function(a,b,c,d){var e,f,g,h,i,j=this.options,k=a.width,l=a.height,m=this.getOrientation();~[5,6,7,8].indexOf(m)&&(c^=d,d^=c,c^=d),e=Math[j.crop?"max":"min"](c/k,d/l),j.allowMagnify||(e=Math.min(1,e)),f=k*e,g=l*e,j.crop?(b.width=c,b.height=d):(b.width=f,b.height=g),h=(b.width-f)/2,i=(b.height-g)/2,j.preserveHeaders||this._rotate2Orientaion(b,m),this._renderImageToCanvas(b,a,h,i,f,g)},_rotate2Orientaion:function(a,b){var c=a.width,d=a.height,e=a.getContext("2d");switch(b){case 5:case 6:case 7:case 8:a.width=d,a.height=c}switch(b){case 2:e.translate(c,0),e.scale(-1,1);break;case 3:e.translate(c,d),e.rotate(Math.PI);break;case 4:e.translate(0,d),e.scale(1,-1);break;case 5:e.rotate(.5*Math.PI),e.scale(1,-1);break;case 6:e.rotate(.5*Math.PI),e.translate(0,-d);break;case 7:e.rotate(.5*Math.PI),e.translate(c,-d),e.scale(-1,1);break;case 8:e.rotate(-.5*Math.PI),e.translate(-c,0)}},_renderImageToCanvas:function(){function b(a,b,c){var d,e,f,g=document.createElement("canvas"),h=g.getContext("2d"),i=0,j=c,k=c;for(g.width=1,g.height=c,h.drawImage(a,0,0),d=h.getImageData(0,0,1,c).data;k>i;)e=d[4*(k-1)+3],0===e?j=k:i=k,k=j+i>>1;return f=k/c,0===f?1:f}function c(a){var b,c,d=a.naturalWidth,e=a.naturalHeight;return d*e>1048576?(b=document.createElement("canvas"),b.width=b.height=1,c=b.getContext("2d"),c.drawImage(a,-d+1,0),0===c.getImageData(0,0,1,1).data[3]):!1}return a.os.ios?a.os.ios>=7?function(a,c,d,e,f,g){var h=c.naturalWidth,i=c.naturalHeight,j=b(c,h,i);return a.getContext("2d").drawImage(c,0,0,h*j,i*j,d,e,f,g)}:function(a,d,e,f,g,h){var i,j,k,l,m,n,o,p=d.naturalWidth,q=d.naturalHeight,r=a.getContext("2d"),s=c(d),t="image/jpeg"===this.type,u=1024,v=0,w=0;for(s&&(p/=2,q/=2),r.save(),i=document.createElement("canvas"),i.width=i.height=u,j=i.getContext("2d"),k=t?b(d,p,q):1,l=Math.ceil(u*g/p),m=Math.ceil(u*h/q/k);q>v;){for(n=0,o=0;p>n;)j.clearRect(0,0,u,u),j.drawImage(d,-n,-v),r.drawImage(i,0,0,u,u,e+o,f+w,l,m),n+=u,o+=l;v+=u,w+=m}r.restore(),i=j=null}:function(a,b,c,d,e,f){a.getContext("2d").drawImage(b,c,d,e,f)}}()})}),b("runtime/html5/transport",["base","runtime/html5/runtime"],function(a,b){var c=a.noop,d=a.$;return b.register("Transport",{init:function(){this._status=0,this._response=null},send:function(){var b,c,e,f=this.owner,g=this.options,h=this._initAjax(),i=f._blob,j=g.server;g.sendAsBinary?(j+=(/\?/.test(j)?"&":"?")+d.param(f._formData),c=i.getSource()):(b=new FormData,d.each(f._formData,function(a,c){b.append(a,c)}),b.append(g.fileVal,i.getSource(),g.filename||f._formData.name||"")),g.withCredentials&&"withCredentials"in h?(h.open(g.method,j,!0),h.withCredentials=!0):h.open(g.method,j),this._setRequestHeader(h,g.headers),c?(h.overrideMimeType("application/octet-stream"),a.os.android?(e=new FileReader,e.onload=function(){h.send(this.result),e=e.onload=null},e.readAsArrayBuffer(c)):h.send(c)):h.send(b)},getResponse:function(){return this._response},getResponseAsJson:function(){return this._parseJson(this._response)},getStatus:function(){return this._status},abort:function(){var a=this._xhr;a&&(a.upload.onprogress=c,a.onreadystatechange=c,a.abort(),this._xhr=a=null)},destroy:function(){this.abort()},_initAjax:function(){var a=this,b=new XMLHttpRequest,d=this.options;return!d.withCredentials||"withCredentials"in b||"undefined"==typeof XDomainRequest||(b=new XDomainRequest),b.upload.onprogress=function(b){var c=0;return b.lengthComputable&&(c=b.loaded/b.total),a.trigger("progress",c)},b.onreadystatechange=function(){return 4===b.readyState?(b.upload.onprogress=c,b.onreadystatechange=c,a._xhr=null,a._status=b.status,b.status>=200&&b.status<300?(a._response=b.responseText,a.trigger("load")):b.status>=500&&b.status<600?(a._response=b.responseText,a.trigger("error","server")):a.trigger("error",a._status?"http":"abort")):void 0},a._xhr=b,b},_setRequestHeader:function(a,b){d.each(b,function(b,c){a.setRequestHeader(b,c)})},_parseJson:function(a){var b;try{b=JSON.parse(a)}catch(c){b={}}return b}})}),b("runtime/flash/runtime",["base","runtime/runtime","runtime/compbase"],function(b,c,d){function e(){var a;try{a=navigator.plugins["Shockwave Flash"],a=a.description}catch(b){try{a=new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")}catch(c){a="0.0"}}return a=a.match(/\d+/g),parseFloat(a[0]+"."+a[1],10)}function f(){function d(a,b){var c,d,e=a.type||a;c=e.split("::"),d=c[0],e=c[1],"Ready"===e&&d===j.uid?j.trigger("ready"):f[d]&&f[d].trigger(e.toLowerCase(),a,b)}var e={},f={},g=this.destory,j=this,k=b.guid("webuploader_");c.apply(j,arguments),j.type=h,j.exec=function(a,c){var d,g=this,h=g.uid,k=b.slice(arguments,2);return f[h]=g,i[a]&&(e[h]||(e[h]=new i[a](g,j)),d=e[h],d[c])?d[c].apply(d,k):j.flashExec.apply(g,arguments)},a[k]=function(){var a=arguments;setTimeout(function(){d.apply(null,a)},1)},this.jsreciver=k,this.destory=function(){return g&&g.apply(this,arguments)},this.flashExec=function(a,c){var d=j.getFlash(),e=b.slice(arguments,2);return d.exec(this.uid,a,c,e)}}var g=b.$,h="flash",i={};return b.inherits(c,{constructor:f,init:function(){var a,c=this.getContainer(),d=this.options;c.css({position:"absolute",top:"-8px",left:"-8px",width:"9px",height:"9px",overflow:"hidden"}),a='<object id="'+this.uid+'" type="application/x-shockwave-flash" data="'+d.swf+'" ',b.browser.ie&&(a+='classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '),a+='width="100%" height="100%" style="outline:0"><param name="movie" value="'+d.swf+'" /><param name="flashvars" value="uid='+this.uid+"&jsreciver="+this.jsreciver+'" /><param name="wmode" value="transparent" /><param name="allowscriptaccess" value="always" /></object>',c.html(a)},getFlash:function(){return this._flash?this._flash:(this._flash=g("#"+this.uid).get(0),this._flash)}}),f.register=function(a,c){return c=i[a]=b.inherits(d,g.extend({flashExec:function(){var a=this.owner,b=this.getRuntime();return b.flashExec.apply(a,arguments)}},c))},e()>=11.4&&c.addRuntime(h,f),f}),b("runtime/flash/filepicker",["base","runtime/flash/runtime"],function(a,b){var c=a.$;return b.register("FilePicker",{init:function(a){var b,d,e=c.extend({},a);for(b=e.accept&&e.accept.length,d=0;b>d;d++)e.accept[d].title||(e.accept[d].title="Files");delete e.button,delete e.container,this.flashExec("FilePicker","init",e)},destroy:function(){}})}),b("runtime/flash/image",["runtime/flash/runtime"],function(a){return a.register("Image",{loadFromBlob:function(a){var b=this.owner;b.info()&&this.flashExec("Image","info",b.info()),b.meta()&&this.flashExec("Image","meta",b.meta()),this.flashExec("Image","loadFromBlob",a.uid)}})}),b("runtime/flash/transport",["base","runtime/flash/runtime","runtime/client"],function(a,b,c){var d=a.$;return b.register("Transport",{init:function(){this._status=0,this._response=null,this._responseJson=null},send:function(){var a,b=this.owner,c=this.options,e=this._initAjax(),f=b._blob,g=c.server;e.connectRuntime(f.ruid),c.sendAsBinary?(g+=(/\?/.test(g)?"&":"?")+d.param(b._formData),a=f.uid):(d.each(b._formData,function(a,b){e.exec("append",a,b)}),e.exec("appendBlob",c.fileVal,f.uid,c.filename||b._formData.name||"")),this._setRequestHeader(e,c.headers),e.exec("send",{method:c.method,url:g},a)},getStatus:function(){return this._status},getResponse:function(){return this._response},getResponseAsJson:function(){return this._responseJson},abort:function(){var a=this._xhr;a&&(a.exec("abort"),a.destroy(),this._xhr=a=null)},destroy:function(){this.abort()},_initAjax:function(){var a=this,b=new c("XMLHttpRequest");return b.on("uploadprogress progress",function(b){return a.trigger("progress",b.loaded/b.total)}),b.on("load",function(){var c=b.exec("getStatus"),d="";return b.off(),a._xhr=null,c>=200&&300>c?(a._response=b.exec("getResponse"),a._responseJson=b.exec("getResponseAsJson")):c>=500&&600>c?(a._response=b.exec("getResponse"),a._responseJson=b.exec("getResponseAsJson"),d="server"):d="http",b.destroy(),b=null,d?a.trigger("error",d):a.trigger("load")}),b.on("error",function(){b.off(),a._xhr=null,a.trigger("error","http")}),a._xhr=b,b},_setRequestHeader:function(a,b){d.each(b,function(b,c){a.exec("setRequestHeader",b,c)})}})}),b("preset/all",["base","widgets/filednd","widgets/filepaste","widgets/filepicker","widgets/image","widgets/queue","widgets/runtime","widgets/upload","widgets/validator","runtime/html5/blob","runtime/html5/dnd","runtime/html5/filepaste","runtime/html5/filepicker","runtime/html5/imagemeta/exif","runtime/html5/androidpatch","runtime/html5/image","runtime/html5/transport","runtime/flash/filepicker","runtime/flash/image","runtime/flash/transport"],function(a){return a}),b("webuploader",["preset/all"],function(a){return a}),c("webuploader")});
@@ -0,0 +1,4593 @@
1
+ /*! WebUploader 0.1.2 */
2
+
3
+
4
+ /**
5
+ * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。
6
+ *
7
+ * AMD API 内部的简单不完全实现,请忽略。只有当WebUploader被合并成一个文件的时候才会引入。
8
+ */
9
+ (function( root, factory ) {
10
+ var modules = {},
11
+
12
+ // 内部require, 简单不完全实现。
13
+ // https://github.com/amdjs/amdjs-api/wiki/require
14
+ _require = function( deps, callback ) {
15
+ var args, len, i;
16
+
17
+ // 如果deps不是数组,则直接返回指定module
18
+ if ( typeof deps === 'string' ) {
19
+ return getModule( deps );
20
+ } else {
21
+ args = [];
22
+ for( len = deps.length, i = 0; i < len; i++ ) {
23
+ args.push( getModule( deps[ i ] ) );
24
+ }
25
+
26
+ return callback.apply( null, args );
27
+ }
28
+ },
29
+
30
+ // 内部define,暂时不支持不指定id.
31
+ _define = function( id, deps, factory ) {
32
+ if ( arguments.length === 2 ) {
33
+ factory = deps;
34
+ deps = null;
35
+ }
36
+
37
+ _require( deps || [], function() {
38
+ setModule( id, factory, arguments );
39
+ });
40
+ },
41
+
42
+ // 设置module, 兼容CommonJs写法。
43
+ setModule = function( id, factory, args ) {
44
+ var module = {
45
+ exports: factory
46
+ },
47
+ returned;
48
+
49
+ if ( typeof factory === 'function' ) {
50
+ args.length || (args = [ _require, module.exports, module ]);
51
+ returned = factory.apply( null, args );
52
+ returned !== undefined && (module.exports = returned);
53
+ }
54
+
55
+ modules[ id ] = module.exports;
56
+ },
57
+
58
+ // 根据id获取module
59
+ getModule = function( id ) {
60
+ var module = modules[ id ] || root[ id ];
61
+
62
+ if ( !module ) {
63
+ throw new Error( '`' + id + '` is undefined' );
64
+ }
65
+
66
+ return module;
67
+ },
68
+
69
+ // 将所有modules,将路径ids装换成对象。
70
+ exportsTo = function( obj ) {
71
+ var key, host, parts, part, last, ucFirst;
72
+
73
+ // make the first character upper case.
74
+ ucFirst = function( str ) {
75
+ return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));
76
+ };
77
+
78
+ for ( key in modules ) {
79
+ host = obj;
80
+
81
+ if ( !modules.hasOwnProperty( key ) ) {
82
+ continue;
83
+ }
84
+
85
+ parts = key.split('/');
86
+ last = ucFirst( parts.pop() );
87
+
88
+ while( (part = ucFirst( parts.shift() )) ) {
89
+ host[ part ] = host[ part ] || {};
90
+ host = host[ part ];
91
+ }
92
+
93
+ host[ last ] = modules[ key ];
94
+ }
95
+ },
96
+
97
+ exports = factory( root, _define, _require ),
98
+ origin;
99
+
100
+ // exports every module.
101
+ exportsTo( exports );
102
+
103
+ if ( typeof module === 'object' && typeof module.exports === 'object' ) {
104
+
105
+ // For CommonJS and CommonJS-like environments where a proper window is present,
106
+ module.exports = exports;
107
+ } else if ( typeof define === 'function' && define.amd ) {
108
+
109
+ // Allow using this built library as an AMD module
110
+ // in another project. That other project will only
111
+ // see this AMD call, not the internal modules in
112
+ // the closure below.
113
+ define([], exports );
114
+ } else {
115
+
116
+ // Browser globals case. Just assign the
117
+ // result to a property on the global.
118
+ origin = root.WebUploader;
119
+ root.WebUploader = exports;
120
+ root.WebUploader.noConflict = function() {
121
+ root.WebUploader = origin;
122
+ };
123
+ }
124
+ })( this, function( window, define, require ) {
125
+
126
+
127
+ /**
128
+ * @fileOverview jQuery or Zepto
129
+ */
130
+ define('dollar-third',[],function() {
131
+ return window.jQuery || window.Zepto;
132
+ });
133
+ /**
134
+ * @fileOverview Dom 操作相关
135
+ */
136
+ define('dollar',[
137
+ 'dollar-third'
138
+ ], function( _ ) {
139
+ return _;
140
+ });
141
+ /**
142
+ * @fileOverview 使用jQuery的Promise
143
+ */
144
+ define('promise-third',[
145
+ 'dollar'
146
+ ], function( $ ) {
147
+ return {
148
+ Deferred: $.Deferred,
149
+ when: $.when,
150
+
151
+ isPromise: function( anything ) {
152
+ return anything && typeof anything.then === 'function';
153
+ }
154
+ };
155
+ });
156
+ /**
157
+ * @fileOverview Promise/A+
158
+ */
159
+ define('promise',[
160
+ 'promise-third'
161
+ ], function( _ ) {
162
+ return _;
163
+ });
164
+ /**
165
+ * @fileOverview 基础类方法。
166
+ */
167
+
168
+ /**
169
+ * Web Uploader内部类的详细说明,以下提及的功能类,都可以在`WebUploader`这个变量中访问到。
170
+ *
171
+ * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.
172
+ * 默认module id该文件的路径,而此路径将会转化成名字空间存放在WebUploader中。如:
173
+ *
174
+ * * module `base`:WebUploader.Base
175
+ * * module `file`: WebUploader.File
176
+ * * module `lib/dnd`: WebUploader.Lib.Dnd
177
+ * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd
178
+ *
179
+ *
180
+ * 以下文档将可能省略`WebUploader`前缀。
181
+ * @module WebUploader
182
+ * @title WebUploader API文档
183
+ */
184
+ define('base',[
185
+ 'dollar',
186
+ 'promise'
187
+ ], function( $, promise ) {
188
+
189
+ var noop = function() {},
190
+ call = Function.call;
191
+
192
+ // http://jsperf.com/uncurrythis
193
+ // 反科里化
194
+ function uncurryThis( fn ) {
195
+ return function() {
196
+ return call.apply( fn, arguments );
197
+ };
198
+ }
199
+
200
+ function bindFn( fn, context ) {
201
+ return function() {
202
+ return fn.apply( context, arguments );
203
+ };
204
+ }
205
+
206
+ function createObject( proto ) {
207
+ var f;
208
+
209
+ if ( Object.create ) {
210
+ return Object.create( proto );
211
+ } else {
212
+ f = function() {};
213
+ f.prototype = proto;
214
+ return new f();
215
+ }
216
+ }
217
+
218
+
219
+ /**
220
+ * 基础类,提供一些简单常用的方法。
221
+ * @class Base
222
+ */
223
+ return {
224
+
225
+ /**
226
+ * @property {String} version 当前版本号。
227
+ */
228
+ version: '0.1.2',
229
+
230
+ /**
231
+ * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。
232
+ */
233
+ $: $,
234
+
235
+ Deferred: promise.Deferred,
236
+
237
+ isPromise: promise.isPromise,
238
+
239
+ when: promise.when,
240
+
241
+ /**
242
+ * @description 简单的浏览器检查结果。
243
+ *
244
+ * * `webkit` webkit版本号,如果浏览器为非webkit内核,此属性为`undefined`。
245
+ * * `chrome` chrome浏览器版本号,如果浏览器为chrome,此属性为`undefined`。
246
+ * * `ie` ie浏览器版本号,如果浏览器为非ie,此属性为`undefined`。**暂不支持ie10+**
247
+ * * `firefox` firefox浏览器版本号,如果浏览器为非firefox,此属性为`undefined`。
248
+ * * `safari` safari浏览器版本号,如果浏览器为非safari,此属性为`undefined`。
249
+ * * `opera` opera浏览器版本号,如果浏览器为非opera,此属性为`undefined`。
250
+ *
251
+ * @property {Object} [browser]
252
+ */
253
+ browser: (function( ua ) {
254
+ var ret = {},
255
+ webkit = ua.match( /WebKit\/([\d.]+)/ ),
256
+ chrome = ua.match( /Chrome\/([\d.]+)/ ) ||
257
+ ua.match( /CriOS\/([\d.]+)/ ),
258
+
259
+ ie = ua.match( /MSIE\s([\d\.]+)/ ) ||
260
+ ua.match(/(?:trident)(?:.*rv:([\w.]+))?/i),
261
+ firefox = ua.match( /Firefox\/([\d.]+)/ ),
262
+ safari = ua.match( /Safari\/([\d.]+)/ ),
263
+ opera = ua.match( /OPR\/([\d.]+)/ );
264
+
265
+ webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));
266
+ chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));
267
+ ie && (ret.ie = parseFloat( ie[ 1 ] ));
268
+ firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));
269
+ safari && (ret.safari = parseFloat( safari[ 1 ] ));
270
+ opera && (ret.opera = parseFloat( opera[ 1 ] ));
271
+
272
+ return ret;
273
+ })( navigator.userAgent ),
274
+
275
+ /**
276
+ * @description 操作系统检查结果。
277
+ *
278
+ * * `android` 如果在android浏览器环境下,此值为对应的android版本号,否则为`undefined`。
279
+ * * `ios` 如果在ios浏览器环境下,此值为对应的ios版本号,否则为`undefined`。
280
+ * @property {Object} [os]
281
+ */
282
+ os: (function( ua ) {
283
+ var ret = {},
284
+
285
+ // osx = !!ua.match( /\(Macintosh\; Intel / ),
286
+ android = ua.match( /(?:Android);?[\s\/]+([\d.]+)?/ ),
287
+ ios = ua.match( /(?:iPad|iPod|iPhone).*OS\s([\d_]+)/ );
288
+
289
+ // osx && (ret.osx = true);
290
+ android && (ret.android = parseFloat( android[ 1 ] ));
291
+ ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));
292
+
293
+ return ret;
294
+ })( navigator.userAgent ),
295
+
296
+ /**
297
+ * 实现类与类之间的继承。
298
+ * @method inherits
299
+ * @grammar Base.inherits( super ) => child
300
+ * @grammar Base.inherits( super, protos ) => child
301
+ * @grammar Base.inherits( super, protos, statics ) => child
302
+ * @param {Class} super 父类
303
+ * @param {Object | Function} [protos] 子类或者对象。如果对象中包含constructor,子类将是用此属性值。
304
+ * @param {Function} [protos.constructor] 子类构造器,不指定的话将创建个临时的直接执行父类构造器的方法。
305
+ * @param {Object} [statics] 静态属性或方法。
306
+ * @return {Class} 返回子类。
307
+ * @example
308
+ * function Person() {
309
+ * console.log( 'Super' );
310
+ * }
311
+ * Person.prototype.hello = function() {
312
+ * console.log( 'hello' );
313
+ * };
314
+ *
315
+ * var Manager = Base.inherits( Person, {
316
+ * world: function() {
317
+ * console.log( 'World' );
318
+ * }
319
+ * });
320
+ *
321
+ * // 因为没有指定构造器,父类的构造器将会执行。
322
+ * var instance = new Manager(); // => Super
323
+ *
324
+ * // 继承子父类的方法
325
+ * instance.hello(); // => hello
326
+ * instance.world(); // => World
327
+ *
328
+ * // 子类的__super__属性指向父类
329
+ * console.log( Manager.__super__ === Person ); // => true
330
+ */
331
+ inherits: function( Super, protos, staticProtos ) {
332
+ var child;
333
+
334
+ if ( typeof protos === 'function' ) {
335
+ child = protos;
336
+ protos = null;
337
+ } else if ( protos && protos.hasOwnProperty('constructor') ) {
338
+ child = protos.constructor;
339
+ } else {
340
+ child = function() {
341
+ return Super.apply( this, arguments );
342
+ };
343
+ }
344
+
345
+ // 复制静态方法
346
+ $.extend( true, child, Super, staticProtos || {} );
347
+
348
+ /* jshint camelcase: false */
349
+
350
+ // 让子类的__super__属性指向父类。
351
+ child.__super__ = Super.prototype;
352
+
353
+ // 构建原型,添加原型方法或属性。
354
+ // 暂时用Object.create实现。
355
+ child.prototype = createObject( Super.prototype );
356
+ protos && $.extend( true, child.prototype, protos );
357
+
358
+ return child;
359
+ },
360
+
361
+ /**
362
+ * 一个不做任何事情的方法。可以用来赋值给默认的callback.
363
+ * @method noop
364
+ */
365
+ noop: noop,
366
+
367
+ /**
368
+ * 返回一个新的方法,此方法将已指定的`context`来执行。
369
+ * @grammar Base.bindFn( fn, context ) => Function
370
+ * @method bindFn
371
+ * @example
372
+ * var doSomething = function() {
373
+ * console.log( this.name );
374
+ * },
375
+ * obj = {
376
+ * name: 'Object Name'
377
+ * },
378
+ * aliasFn = Base.bind( doSomething, obj );
379
+ *
380
+ * aliasFn(); // => Object Name
381
+ *
382
+ */
383
+ bindFn: bindFn,
384
+
385
+ /**
386
+ * 引用Console.log如果存在的话,否则引用一个[空函数loop](#WebUploader:Base.log)。
387
+ * @grammar Base.log( args... ) => undefined
388
+ * @method log
389
+ */
390
+ log: (function() {
391
+ if ( window.console ) {
392
+ return bindFn( console.log, console );
393
+ }
394
+ return noop;
395
+ })(),
396
+
397
+ nextTick: (function() {
398
+
399
+ return function( cb ) {
400
+ setTimeout( cb, 1 );
401
+ };
402
+
403
+ // @bug 当浏览器不在当前窗口时就停了。
404
+ // var next = window.requestAnimationFrame ||
405
+ // window.webkitRequestAnimationFrame ||
406
+ // window.mozRequestAnimationFrame ||
407
+ // function( cb ) {
408
+ // window.setTimeout( cb, 1000 / 60 );
409
+ // };
410
+
411
+ // // fix: Uncaught TypeError: Illegal invocation
412
+ // return bindFn( next, window );
413
+ })(),
414
+
415
+ /**
416
+ * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。
417
+ * 将用来将非数组对象转化成数组对象。
418
+ * @grammar Base.slice( target, start[, end] ) => Array
419
+ * @method slice
420
+ * @example
421
+ * function doSomthing() {
422
+ * var args = Base.slice( arguments, 1 );
423
+ * console.log( args );
424
+ * }
425
+ *
426
+ * doSomthing( 'ignored', 'arg2', 'arg3' ); // => Array ["arg2", "arg3"]
427
+ */
428
+ slice: uncurryThis( [].slice ),
429
+
430
+ /**
431
+ * 生成唯一的ID
432
+ * @method guid
433
+ * @grammar Base.guid() => String
434
+ * @grammar Base.guid( prefx ) => String
435
+ */
436
+ guid: (function() {
437
+ var counter = 0;
438
+
439
+ return function( prefix ) {
440
+ var guid = (+new Date()).toString( 32 ),
441
+ i = 0;
442
+
443
+ for ( ; i < 5; i++ ) {
444
+ guid += Math.floor( Math.random() * 65535 ).toString( 32 );
445
+ }
446
+
447
+ return (prefix || 'wu_') + guid + (counter++).toString( 32 );
448
+ };
449
+ })(),
450
+
451
+ /**
452
+ * 格式化文件大小, 输出成带单位的字符串
453
+ * @method formatSize
454
+ * @grammar Base.formatSize( size ) => String
455
+ * @grammar Base.formatSize( size, pointLength ) => String
456
+ * @grammar Base.formatSize( size, pointLength, units ) => String
457
+ * @param {Number} size 文件大小
458
+ * @param {Number} [pointLength=2] 精确到的小数点数。
459
+ * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节,到千字节,一直往上指定。如果单位数组里面只指定了到了K(千字节),同时文件大小大于M, 此方法的输出将还是显示成多少K.
460
+ * @example
461
+ * console.log( Base.formatSize( 100 ) ); // => 100B
462
+ * console.log( Base.formatSize( 1024 ) ); // => 1.00K
463
+ * console.log( Base.formatSize( 1024, 0 ) ); // => 1K
464
+ * console.log( Base.formatSize( 1024 * 1024 ) ); // => 1.00M
465
+ * console.log( Base.formatSize( 1024 * 1024 * 1024 ) ); // => 1.00G
466
+ * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) ); // => 1024MB
467
+ */
468
+ formatSize: function( size, pointLength, units ) {
469
+ var unit;
470
+
471
+ units = units || [ 'B', 'K', 'M', 'G', 'TB' ];
472
+
473
+ while ( (unit = units.shift()) && size > 1024 ) {
474
+ size = size / 1024;
475
+ }
476
+
477
+ return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +
478
+ unit;
479
+ }
480
+ };
481
+ });
482
+ /**
483
+ * 事件处理类,可以独立使用,也可以扩展给对象使用。
484
+ * @fileOverview Mediator
485
+ */
486
+ define('mediator',[
487
+ 'base'
488
+ ], function( Base ) {
489
+ var $ = Base.$,
490
+ slice = [].slice,
491
+ separator = /\s+/,
492
+ protos;
493
+
494
+ // 根据条件过滤出事件handlers.
495
+ function findHandlers( arr, name, callback, context ) {
496
+ return $.grep( arr, function( handler ) {
497
+ return handler &&
498
+ (!name || handler.e === name) &&
499
+ (!callback || handler.cb === callback ||
500
+ handler.cb._cb === callback) &&
501
+ (!context || handler.ctx === context);
502
+ });
503
+ }
504
+
505
+ function eachEvent( events, callback, iterator ) {
506
+ // 不支持对象,只支持多个event用空格隔开
507
+ $.each( (events || '').split( separator ), function( _, key ) {
508
+ iterator( key, callback );
509
+ });
510
+ }
511
+
512
+ function triggerHanders( events, args ) {
513
+ var stoped = false,
514
+ i = -1,
515
+ len = events.length,
516
+ handler;
517
+
518
+ while ( ++i < len ) {
519
+ handler = events[ i ];
520
+
521
+ if ( handler.cb.apply( handler.ctx2, args ) === false ) {
522
+ stoped = true;
523
+ break;
524
+ }
525
+ }
526
+
527
+ return !stoped;
528
+ }
529
+
530
+ protos = {
531
+
532
+ /**
533
+ * 绑定事件。
534
+ *
535
+ * `callback`方法在执行时,arguments将会来源于trigger的时候携带的参数。如
536
+ * ```javascript
537
+ * var obj = {};
538
+ *
539
+ * // 使得obj有事件行为
540
+ * Mediator.installTo( obj );
541
+ *
542
+ * obj.on( 'testa', function( arg1, arg2 ) {
543
+ * console.log( arg1, arg2 ); // => 'arg1', 'arg2'
544
+ * });
545
+ *
546
+ * obj.trigger( 'testa', 'arg1', 'arg2' );
547
+ * ```
548
+ *
549
+ * 如果`callback`中,某一个方法`return false`了,则后续的其他`callback`都不会被执行到。
550
+ * 切会影响到`trigger`方法的返回值,为`false`。
551
+ *
552
+ * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处,
553
+ * 就是第一个参数为`type`,记录当前是什么事件在触发。此类`callback`的优先级比脚低,会再正常`callback`执行完后触发。
554
+ * ```javascript
555
+ * obj.on( 'all', function( type, arg1, arg2 ) {
556
+ * console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'
557
+ * });
558
+ * ```
559
+ *
560
+ * @method on
561
+ * @grammar on( name, callback[, context] ) => self
562
+ * @param {String} name 事件名,支持多个事件用空格隔开
563
+ * @param {Function} callback 事件处理器
564
+ * @param {Object} [context] 事件处理器的上下文。
565
+ * @return {self} 返回自身,方便链式
566
+ * @chainable
567
+ * @class Mediator
568
+ */
569
+ on: function( name, callback, context ) {
570
+ var me = this,
571
+ set;
572
+
573
+ if ( !callback ) {
574
+ return this;
575
+ }
576
+
577
+ set = this._events || (this._events = []);
578
+
579
+ eachEvent( name, callback, function( name, callback ) {
580
+ var handler = { e: name };
581
+
582
+ handler.cb = callback;
583
+ handler.ctx = context;
584
+ handler.ctx2 = context || me;
585
+ handler.id = set.length;
586
+
587
+ set.push( handler );
588
+ });
589
+
590
+ return this;
591
+ },
592
+
593
+ /**
594
+ * 绑定事件,且当handler执行完后,自动解除绑定。
595
+ * @method once
596
+ * @grammar once( name, callback[, context] ) => self
597
+ * @param {String} name 事件名
598
+ * @param {Function} callback 事件处理器
599
+ * @param {Object} [context] 事件处理器的上下文。
600
+ * @return {self} 返回自身,方便链式
601
+ * @chainable
602
+ */
603
+ once: function( name, callback, context ) {
604
+ var me = this;
605
+
606
+ if ( !callback ) {
607
+ return me;
608
+ }
609
+
610
+ eachEvent( name, callback, function( name, callback ) {
611
+ var once = function() {
612
+ me.off( name, once );
613
+ return callback.apply( context || me, arguments );
614
+ };
615
+
616
+ once._cb = callback;
617
+ me.on( name, once, context );
618
+ });
619
+
620
+ return me;
621
+ },
622
+
623
+ /**
624
+ * 解除事件绑定
625
+ * @method off
626
+ * @grammar off( [name[, callback[, context] ] ] ) => self
627
+ * @param {String} [name] 事件名
628
+ * @param {Function} [callback] 事件处理器
629
+ * @param {Object} [context] 事件处理器的上下文。
630
+ * @return {self} 返回自身,方便链式
631
+ * @chainable
632
+ */
633
+ off: function( name, cb, ctx ) {
634
+ var events = this._events;
635
+
636
+ if ( !events ) {
637
+ return this;
638
+ }
639
+
640
+ if ( !name && !cb && !ctx ) {
641
+ this._events = [];
642
+ return this;
643
+ }
644
+
645
+ eachEvent( name, cb, function( name, cb ) {
646
+ $.each( findHandlers( events, name, cb, ctx ), function() {
647
+ delete events[ this.id ];
648
+ });
649
+ });
650
+
651
+ return this;
652
+ },
653
+
654
+ /**
655
+ * 触发事件
656
+ * @method trigger
657
+ * @grammar trigger( name[, args...] ) => self
658
+ * @param {String} type 事件名
659
+ * @param {*} [...] 任意参数
660
+ * @return {Boolean} 如果handler中return false了,则返回false, 否则返回true
661
+ */
662
+ trigger: function( type ) {
663
+ var args, events, allEvents;
664
+
665
+ if ( !this._events || !type ) {
666
+ return this;
667
+ }
668
+
669
+ args = slice.call( arguments, 1 );
670
+ events = findHandlers( this._events, type );
671
+ allEvents = findHandlers( this._events, 'all' );
672
+
673
+ return triggerHanders( events, args ) &&
674
+ triggerHanders( allEvents, arguments );
675
+ }
676
+ };
677
+
678
+ /**
679
+ * 中介者,它本身是个单例,但可以通过[installTo](#WebUploader:Mediator:installTo)方法,使任何对象具备事件行为。
680
+ * 主要目的是负责模块与模块之间的合作,降低耦合度。
681
+ *
682
+ * @class Mediator
683
+ */
684
+ return $.extend({
685
+
686
+ /**
687
+ * 可以通过这个接口,使任何对象具备事件功能。
688
+ * @method installTo
689
+ * @param {Object} obj 需要具备事件行为的对象。
690
+ * @return {Object} 返回obj.
691
+ */
692
+ installTo: function( obj ) {
693
+ return $.extend( obj, protos );
694
+ }
695
+
696
+ }, protos );
697
+ });
698
+ /**
699
+ * @fileOverview Uploader上传类
700
+ */
701
+ define('uploader',[
702
+ 'base',
703
+ 'mediator'
704
+ ], function( Base, Mediator ) {
705
+
706
+ var $ = Base.$;
707
+
708
+ /**
709
+ * 上传入口类。
710
+ * @class Uploader
711
+ * @constructor
712
+ * @grammar new Uploader( opts ) => Uploader
713
+ * @example
714
+ * var uploader = WebUploader.Uploader({
715
+ * swf: 'path_of_swf/Uploader.swf',
716
+ *
717
+ * // 开起分片上传。
718
+ * chunked: true
719
+ * });
720
+ */
721
+ function Uploader( opts ) {
722
+ this.options = $.extend( true, {}, Uploader.options, opts );
723
+ this._init( this.options );
724
+ }
725
+
726
+ // default Options
727
+ // widgets中有相应扩展
728
+ Uploader.options = {};
729
+ Mediator.installTo( Uploader.prototype );
730
+
731
+ // 批量添加纯命令式方法。
732
+ $.each({
733
+ upload: 'start-upload',
734
+ stop: 'stop-upload',
735
+ getFile: 'get-file',
736
+ getFiles: 'get-files',
737
+ addFile: 'add-file',
738
+ addFiles: 'add-file',
739
+ sort: 'sort-files',
740
+ removeFile: 'remove-file',
741
+ skipFile: 'skip-file',
742
+ retry: 'retry',
743
+ isInProgress: 'is-in-progress',
744
+ makeThumb: 'make-thumb',
745
+ getDimension: 'get-dimension',
746
+ addButton: 'add-btn',
747
+ getRuntimeType: 'get-runtime-type',
748
+ refresh: 'refresh',
749
+ disable: 'disable',
750
+ enable: 'enable',
751
+ reset: 'reset'
752
+ }, function( fn, command ) {
753
+ Uploader.prototype[ fn ] = function() {
754
+ return this.request( command, arguments );
755
+ };
756
+ });
757
+
758
+ $.extend( Uploader.prototype, {
759
+ state: 'pending',
760
+
761
+ _init: function( opts ) {
762
+ var me = this;
763
+
764
+ me.request( 'init', opts, function() {
765
+ me.state = 'ready';
766
+ me.trigger('ready');
767
+ });
768
+ },
769
+
770
+ /**
771
+ * 获取或者设置Uploader配置项。
772
+ * @method option
773
+ * @grammar option( key ) => *
774
+ * @grammar option( key, val ) => self
775
+ * @example
776
+ *
777
+ * // 初始状态图片上传前不会压缩
778
+ * var uploader = new WebUploader.Uploader({
779
+ * resize: null;
780
+ * });
781
+ *
782
+ * // 修改后图片上传前,尝试将图片压缩到1600 * 1600
783
+ * uploader.options( 'resize', {
784
+ * width: 1600,
785
+ * height: 1600
786
+ * });
787
+ */
788
+ option: function( key, val ) {
789
+ var opts = this.options;
790
+
791
+ // setter
792
+ if ( arguments.length > 1 ) {
793
+
794
+ if ( $.isPlainObject( val ) &&
795
+ $.isPlainObject( opts[ key ] ) ) {
796
+ $.extend( opts[ key ], val );
797
+ } else {
798
+ opts[ key ] = val;
799
+ }
800
+
801
+ } else { // getter
802
+ return key ? opts[ key ] : opts;
803
+ }
804
+ },
805
+
806
+ /**
807
+ * 获取文件统计信息。返回一个包含一下信息的对象。
808
+ * * `successNum` 上传成功的文件数
809
+ * * `uploadFailNum` 上传失败的文件数
810
+ * * `cancelNum` 被删除的文件数
811
+ * * `invalidNum` 无效的文件数
812
+ * * `queueNum` 还在队列中的文件数
813
+ * @method getStats
814
+ * @grammar getStats() => Object
815
+ */
816
+ getStats: function() {
817
+ // return this._mgr.getStats.apply( this._mgr, arguments );
818
+ var stats = this.request('get-stats');
819
+
820
+ return {
821
+ successNum: stats.numOfSuccess,
822
+
823
+ // who care?
824
+ // queueFailNum: 0,
825
+ cancelNum: stats.numOfCancel,
826
+ invalidNum: stats.numOfInvalid,
827
+ uploadFailNum: stats.numOfUploadFailed,
828
+ queueNum: stats.numOfQueue
829
+ };
830
+ },
831
+
832
+ // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器
833
+ trigger: function( type/*, args...*/ ) {
834
+ var args = [].slice.call( arguments, 1 ),
835
+ opts = this.options,
836
+ name = 'on' + type.substring( 0, 1 ).toUpperCase() +
837
+ type.substring( 1 );
838
+
839
+ if (
840
+ // 调用通过on方法注册的handler.
841
+ Mediator.trigger.apply( this, arguments ) === false ||
842
+
843
+ // 调用opts.onEvent
844
+ $.isFunction( opts[ name ] ) &&
845
+ opts[ name ].apply( this, args ) === false ||
846
+
847
+ // 调用this.onEvent
848
+ $.isFunction( this[ name ] ) &&
849
+ this[ name ].apply( this, args ) === false ||
850
+
851
+ // 广播所有uploader的事件。
852
+ Mediator.trigger.apply( Mediator,
853
+ [ this, type ].concat( args ) ) === false ) {
854
+
855
+ return false;
856
+ }
857
+
858
+ return true;
859
+ },
860
+
861
+ // widgets/widget.js将补充此方法的详细文档。
862
+ request: Base.noop
863
+ });
864
+
865
+ /**
866
+ * 创建Uploader实例,等同于new Uploader( opts );
867
+ * @method create
868
+ * @class Base
869
+ * @static
870
+ * @grammar Base.create( opts ) => Uploader
871
+ */
872
+ Base.create = Uploader.create = function( opts ) {
873
+ return new Uploader( opts );
874
+ };
875
+
876
+ // 暴露Uploader,可以通过它来扩展业务逻辑。
877
+ Base.Uploader = Uploader;
878
+
879
+ return Uploader;
880
+ });
881
+ /**
882
+ * @fileOverview Runtime管理器,负责Runtime的选择, 连接
883
+ */
884
+ define('runtime/runtime',[
885
+ 'base',
886
+ 'mediator'
887
+ ], function( Base, Mediator ) {
888
+
889
+ var $ = Base.$,
890
+ factories = {},
891
+
892
+ // 获取对象的第一个key
893
+ getFirstKey = function( obj ) {
894
+ for ( var key in obj ) {
895
+ if ( obj.hasOwnProperty( key ) ) {
896
+ return key;
897
+ }
898
+ }
899
+ return null;
900
+ };
901
+
902
+ // 接口类。
903
+ function Runtime( options ) {
904
+ this.options = $.extend({
905
+ container: document.body
906
+ }, options );
907
+ this.uid = Base.guid('rt_');
908
+ }
909
+
910
+ $.extend( Runtime.prototype, {
911
+
912
+ getContainer: function() {
913
+ var opts = this.options,
914
+ parent, container;
915
+
916
+ if ( this._container ) {
917
+ return this._container;
918
+ }
919
+
920
+ parent = $( opts.container || document.body );
921
+ container = $( document.createElement('div') );
922
+
923
+ container.attr( 'id', 'rt_' + this.uid );
924
+ container.css({
925
+ position: 'absolute',
926
+ top: '0px',
927
+ left: '0px',
928
+ width: '1px',
929
+ height: '1px',
930
+ overflow: 'hidden'
931
+ });
932
+
933
+ parent.append( container );
934
+ parent.addClass('webuploader-container');
935
+ this._container = container;
936
+ return container;
937
+ },
938
+
939
+ init: Base.noop,
940
+ exec: Base.noop,
941
+
942
+ destroy: function() {
943
+ if ( this._container ) {
944
+ this._container.parentNode.removeChild( this.__container );
945
+ }
946
+
947
+ this.off();
948
+ }
949
+ });
950
+
951
+ Runtime.orders = 'html5,flash';
952
+
953
+
954
+ /**
955
+ * 添加Runtime实现。
956
+ * @param {String} type 类型
957
+ * @param {Runtime} factory 具体Runtime实现。
958
+ */
959
+ Runtime.addRuntime = function( type, factory ) {
960
+ factories[ type ] = factory;
961
+ };
962
+
963
+ Runtime.hasRuntime = function( type ) {
964
+ return !!(type ? factories[ type ] : getFirstKey( factories ));
965
+ };
966
+
967
+ Runtime.create = function( opts, orders ) {
968
+ var type, runtime;
969
+
970
+ orders = orders || Runtime.orders;
971
+ $.each( orders.split( /\s*,\s*/g ), function() {
972
+ if ( factories[ this ] ) {
973
+ type = this;
974
+ return false;
975
+ }
976
+ });
977
+
978
+ type = type || getFirstKey( factories );
979
+
980
+ if ( !type ) {
981
+ throw new Error('Runtime Error');
982
+ }
983
+
984
+ runtime = new factories[ type ]( opts );
985
+ return runtime;
986
+ };
987
+
988
+ Mediator.installTo( Runtime.prototype );
989
+ return Runtime;
990
+ });
991
+
992
+ /**
993
+ * @fileOverview Runtime管理器,负责Runtime的选择, 连接
994
+ */
995
+ define('runtime/client',[
996
+ 'base',
997
+ 'mediator',
998
+ 'runtime/runtime'
999
+ ], function( Base, Mediator, Runtime ) {
1000
+
1001
+ var cache;
1002
+
1003
+ cache = (function() {
1004
+ var obj = {};
1005
+
1006
+ return {
1007
+ add: function( runtime ) {
1008
+ obj[ runtime.uid ] = runtime;
1009
+ },
1010
+
1011
+ get: function( ruid, standalone ) {
1012
+ var i;
1013
+
1014
+ if ( ruid ) {
1015
+ return obj[ ruid ];
1016
+ }
1017
+
1018
+ for ( i in obj ) {
1019
+ // 有些类型不能重用,比如filepicker.
1020
+ if ( standalone && obj[ i ].__standalone ) {
1021
+ continue;
1022
+ }
1023
+
1024
+ return obj[ i ];
1025
+ }
1026
+
1027
+ return null;
1028
+ },
1029
+
1030
+ remove: function( runtime ) {
1031
+ delete obj[ runtime.uid ];
1032
+ }
1033
+ };
1034
+ })();
1035
+
1036
+ function RuntimeClient( component, standalone ) {
1037
+ var deferred = Base.Deferred(),
1038
+ runtime;
1039
+
1040
+ this.uid = Base.guid('client_');
1041
+
1042
+ // 允许runtime没有初始化之前,注册一些方法在初始化后执行。
1043
+ this.runtimeReady = function( cb ) {
1044
+ return deferred.done( cb );
1045
+ };
1046
+
1047
+ this.connectRuntime = function( opts, cb ) {
1048
+
1049
+ // already connected.
1050
+ if ( runtime ) {
1051
+ throw new Error('already connected!');
1052
+ }
1053
+
1054
+ deferred.done( cb );
1055
+
1056
+ if ( typeof opts === 'string' && cache.get( opts ) ) {
1057
+ runtime = cache.get( opts );
1058
+ }
1059
+
1060
+ // 像filePicker只能独立存在,不能公用。
1061
+ runtime = runtime || cache.get( null, standalone );
1062
+
1063
+ // 需要创建
1064
+ if ( !runtime ) {
1065
+ runtime = Runtime.create( opts, opts.runtimeOrder );
1066
+ runtime.__promise = deferred.promise();
1067
+ runtime.once( 'ready', deferred.resolve );
1068
+ runtime.init();
1069
+ cache.add( runtime );
1070
+ runtime.__client = 1;
1071
+ } else {
1072
+ // 来自cache
1073
+ Base.$.extend( runtime.options, opts );
1074
+ runtime.__promise.then( deferred.resolve );
1075
+ runtime.__client++;
1076
+ }
1077
+
1078
+ standalone && (runtime.__standalone = standalone);
1079
+ return runtime;
1080
+ };
1081
+
1082
+ this.getRuntime = function() {
1083
+ return runtime;
1084
+ };
1085
+
1086
+ this.disconnectRuntime = function() {
1087
+ if ( !runtime ) {
1088
+ return;
1089
+ }
1090
+
1091
+ runtime.__client--;
1092
+
1093
+ if ( runtime.__client <= 0 ) {
1094
+ cache.remove( runtime );
1095
+ delete runtime.__promise;
1096
+ runtime.destroy();
1097
+ }
1098
+
1099
+ runtime = null;
1100
+ };
1101
+
1102
+ this.exec = function() {
1103
+ if ( !runtime ) {
1104
+ return;
1105
+ }
1106
+
1107
+ var args = Base.slice( arguments );
1108
+ component && args.unshift( component );
1109
+
1110
+ return runtime.exec.apply( this, args );
1111
+ };
1112
+
1113
+ this.getRuid = function() {
1114
+ return runtime && runtime.uid;
1115
+ };
1116
+
1117
+ this.destroy = (function( destroy ) {
1118
+ return function() {
1119
+ destroy && destroy.apply( this, arguments );
1120
+ this.trigger('destroy');
1121
+ this.off();
1122
+ this.exec('destroy');
1123
+ this.disconnectRuntime();
1124
+ };
1125
+ })( this.destroy );
1126
+ }
1127
+
1128
+ Mediator.installTo( RuntimeClient.prototype );
1129
+ return RuntimeClient;
1130
+ });
1131
+ /**
1132
+ * @fileOverview 错误信息
1133
+ */
1134
+ define('lib/dnd',[
1135
+ 'base',
1136
+ 'mediator',
1137
+ 'runtime/client'
1138
+ ], function( Base, Mediator, RuntimeClent ) {
1139
+
1140
+ var $ = Base.$;
1141
+
1142
+ function DragAndDrop( opts ) {
1143
+ opts = this.options = $.extend({}, DragAndDrop.options, opts );
1144
+
1145
+ opts.container = $( opts.container );
1146
+
1147
+ if ( !opts.container.length ) {
1148
+ return;
1149
+ }
1150
+
1151
+ RuntimeClent.call( this, 'DragAndDrop' );
1152
+ }
1153
+
1154
+ DragAndDrop.options = {
1155
+ accept: null,
1156
+ disableGlobalDnd: false
1157
+ };
1158
+
1159
+ Base.inherits( RuntimeClent, {
1160
+ constructor: DragAndDrop,
1161
+
1162
+ init: function() {
1163
+ var me = this;
1164
+
1165
+ me.connectRuntime( me.options, function() {
1166
+ me.exec('init');
1167
+ me.trigger('ready');
1168
+ });
1169
+ },
1170
+
1171
+ destroy: function() {
1172
+ this.disconnectRuntime();
1173
+ }
1174
+ });
1175
+
1176
+ Mediator.installTo( DragAndDrop.prototype );
1177
+
1178
+ return DragAndDrop;
1179
+ });
1180
+ /**
1181
+ * @fileOverview 组件基类。
1182
+ */
1183
+ define('widgets/widget',[
1184
+ 'base',
1185
+ 'uploader'
1186
+ ], function( Base, Uploader ) {
1187
+
1188
+ var $ = Base.$,
1189
+ _init = Uploader.prototype._init,
1190
+ IGNORE = {},
1191
+ widgetClass = [];
1192
+
1193
+ function isArrayLike( obj ) {
1194
+ if ( !obj ) {
1195
+ return false;
1196
+ }
1197
+
1198
+ var length = obj.length,
1199
+ type = $.type( obj );
1200
+
1201
+ if ( obj.nodeType === 1 && length ) {
1202
+ return true;
1203
+ }
1204
+
1205
+ return type === 'array' || type !== 'function' && type !== 'string' &&
1206
+ (length === 0 || typeof length === 'number' && length > 0 &&
1207
+ (length - 1) in obj);
1208
+ }
1209
+
1210
+ function Widget( uploader ) {
1211
+ this.owner = uploader;
1212
+ this.options = uploader.options;
1213
+ }
1214
+
1215
+ $.extend( Widget.prototype, {
1216
+
1217
+ init: Base.noop,
1218
+
1219
+ // 类Backbone的事件监听声明,监听uploader实例上的事件
1220
+ // widget直接无法监听事件,事件只能通过uploader来传递
1221
+ invoke: function( apiName, args ) {
1222
+
1223
+ /*
1224
+ {
1225
+ 'make-thumb': 'makeThumb'
1226
+ }
1227
+ */
1228
+ var map = this.responseMap;
1229
+
1230
+ // 如果无API响应声明则忽略
1231
+ if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||
1232
+ !$.isFunction( this[ map[ apiName ] ] ) ) {
1233
+
1234
+ return IGNORE;
1235
+ }
1236
+
1237
+ return this[ map[ apiName ] ].apply( this, args );
1238
+
1239
+ },
1240
+
1241
+ /**
1242
+ * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。
1243
+ * @method request
1244
+ * @grammar request( command, args ) => * | Promise
1245
+ * @grammar request( command, args, callback ) => Promise
1246
+ * @for Uploader
1247
+ */
1248
+ request: function() {
1249
+ return this.owner.request.apply( this.owner, arguments );
1250
+ }
1251
+ });
1252
+
1253
+ // 扩展Uploader.
1254
+ $.extend( Uploader.prototype, {
1255
+
1256
+ // 覆写_init用来初始化widgets
1257
+ _init: function() {
1258
+ var me = this,
1259
+ widgets = me._widgets = [];
1260
+
1261
+ $.each( widgetClass, function( _, klass ) {
1262
+ widgets.push( new klass( me ) );
1263
+ });
1264
+
1265
+ return _init.apply( me, arguments );
1266
+ },
1267
+
1268
+ request: function( apiName, args, callback ) {
1269
+ var i = 0,
1270
+ widgets = this._widgets,
1271
+ len = widgets.length,
1272
+ rlts = [],
1273
+ dfds = [],
1274
+ widget, rlt, promise, key;
1275
+
1276
+ args = isArrayLike( args ) ? args : [ args ];
1277
+
1278
+ for ( ; i < len; i++ ) {
1279
+ widget = widgets[ i ];
1280
+ rlt = widget.invoke( apiName, args );
1281
+
1282
+ if ( rlt !== IGNORE ) {
1283
+
1284
+ // Deferred对象
1285
+ if ( Base.isPromise( rlt ) ) {
1286
+ dfds.push( rlt );
1287
+ } else {
1288
+ rlts.push( rlt );
1289
+ }
1290
+ }
1291
+ }
1292
+
1293
+ // 如果有callback,则用异步方式。
1294
+ if ( callback || dfds.length ) {
1295
+ promise = Base.when.apply( Base, dfds );
1296
+ key = promise.pipe ? 'pipe' : 'then';
1297
+
1298
+ // 很重要不能删除。删除了会死循环。
1299
+ // 保证执行顺序。让callback总是在下一个tick中执行。
1300
+ return promise[ key ](function() {
1301
+ var deferred = Base.Deferred(),
1302
+ args = arguments;
1303
+
1304
+ setTimeout(function() {
1305
+ deferred.resolve.apply( deferred, args );
1306
+ }, 1 );
1307
+
1308
+ return deferred.promise();
1309
+ })[ key ]( callback || Base.noop );
1310
+ } else {
1311
+ return rlts[ 0 ];
1312
+ }
1313
+ }
1314
+ });
1315
+
1316
+ /**
1317
+ * 添加组件
1318
+ * @param {object} widgetProto 组件原型,构造函数通过constructor属性定义
1319
+ * @param {object} responseMap API名称与函数实现的映射
1320
+ * @example
1321
+ * Uploader.register( {
1322
+ * init: function( options ) {},
1323
+ * makeThumb: function() {}
1324
+ * }, {
1325
+ * 'make-thumb': 'makeThumb'
1326
+ * } );
1327
+ */
1328
+ Uploader.register = Widget.register = function( responseMap, widgetProto ) {
1329
+ var map = { init: 'init' },
1330
+ klass;
1331
+
1332
+ if ( arguments.length === 1 ) {
1333
+ widgetProto = responseMap;
1334
+ widgetProto.responseMap = map;
1335
+ } else {
1336
+ widgetProto.responseMap = $.extend( map, responseMap );
1337
+ }
1338
+
1339
+ klass = Base.inherits( Widget, widgetProto );
1340
+ widgetClass.push( klass );
1341
+
1342
+ return klass;
1343
+ };
1344
+
1345
+ return Widget;
1346
+ });
1347
+ /**
1348
+ * @fileOverview DragAndDrop Widget。
1349
+ */
1350
+ define('widgets/filednd',[
1351
+ 'base',
1352
+ 'uploader',
1353
+ 'lib/dnd',
1354
+ 'widgets/widget'
1355
+ ], function( Base, Uploader, Dnd ) {
1356
+ var $ = Base.$;
1357
+
1358
+ Uploader.options.dnd = '';
1359
+
1360
+ /**
1361
+ * @property {Selector} [dnd=undefined] 指定Drag And Drop拖拽的容器,如果不指定,则不启动。
1362
+ * @namespace options
1363
+ * @for Uploader
1364
+ */
1365
+
1366
+ /**
1367
+ * @event dndAccept
1368
+ * @param {DataTransferItemList} items DataTransferItem
1369
+ * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API,且只能通过 mime-type 验证。
1370
+ * @for Uploader
1371
+ */
1372
+ return Uploader.register({
1373
+ init: function( opts ) {
1374
+
1375
+ if ( !opts.dnd ||
1376
+ this.request('predict-runtime-type') !== 'html5' ) {
1377
+ return;
1378
+ }
1379
+
1380
+ var me = this,
1381
+ deferred = Base.Deferred(),
1382
+ options = $.extend({}, {
1383
+ disableGlobalDnd: opts.disableGlobalDnd,
1384
+ container: opts.dnd,
1385
+ accept: opts.accept
1386
+ }),
1387
+ dnd;
1388
+
1389
+ dnd = new Dnd( options );
1390
+
1391
+ dnd.once( 'ready', deferred.resolve );
1392
+ dnd.on( 'drop', function( files ) {
1393
+ me.request( 'add-file', [ files ]);
1394
+ });
1395
+
1396
+ // 检测文件是否全部允许添加。
1397
+ dnd.on( 'accept', function( items ) {
1398
+ return me.owner.trigger( 'dndAccept', items );
1399
+ });
1400
+
1401
+ dnd.init();
1402
+
1403
+ return deferred.promise();
1404
+ }
1405
+ });
1406
+ });
1407
+
1408
+ /**
1409
+ * @fileOverview 错误信息
1410
+ */
1411
+ define('lib/filepaste',[
1412
+ 'base',
1413
+ 'mediator',
1414
+ 'runtime/client'
1415
+ ], function( Base, Mediator, RuntimeClent ) {
1416
+
1417
+ var $ = Base.$;
1418
+
1419
+ function FilePaste( opts ) {
1420
+ opts = this.options = $.extend({}, opts );
1421
+ opts.container = $( opts.container || document.body );
1422
+ RuntimeClent.call( this, 'FilePaste' );
1423
+ }
1424
+
1425
+ Base.inherits( RuntimeClent, {
1426
+ constructor: FilePaste,
1427
+
1428
+ init: function() {
1429
+ var me = this;
1430
+
1431
+ me.connectRuntime( me.options, function() {
1432
+ me.exec('init');
1433
+ me.trigger('ready');
1434
+ });
1435
+ },
1436
+
1437
+ destroy: function() {
1438
+ this.exec('destroy');
1439
+ this.disconnectRuntime();
1440
+ this.off();
1441
+ }
1442
+ });
1443
+
1444
+ Mediator.installTo( FilePaste.prototype );
1445
+
1446
+ return FilePaste;
1447
+ });
1448
+ /**
1449
+ * @fileOverview 组件基类。
1450
+ */
1451
+ define('widgets/filepaste',[
1452
+ 'base',
1453
+ 'uploader',
1454
+ 'lib/filepaste',
1455
+ 'widgets/widget'
1456
+ ], function( Base, Uploader, FilePaste ) {
1457
+ var $ = Base.$;
1458
+
1459
+ /**
1460
+ * @property {Selector} [paste=undefined] 指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.
1461
+ * @namespace options
1462
+ * @for Uploader
1463
+ */
1464
+ return Uploader.register({
1465
+ init: function( opts ) {
1466
+
1467
+ if ( !opts.paste ||
1468
+ this.request('predict-runtime-type') !== 'html5' ) {
1469
+ return;
1470
+ }
1471
+
1472
+ var me = this,
1473
+ deferred = Base.Deferred(),
1474
+ options = $.extend({}, {
1475
+ container: opts.paste,
1476
+ accept: opts.accept
1477
+ }),
1478
+ paste;
1479
+
1480
+ paste = new FilePaste( options );
1481
+
1482
+ paste.once( 'ready', deferred.resolve );
1483
+ paste.on( 'paste', function( files ) {
1484
+ me.owner.request( 'add-file', [ files ]);
1485
+ });
1486
+ paste.init();
1487
+
1488
+ return deferred.promise();
1489
+ }
1490
+ });
1491
+ });
1492
+ /**
1493
+ * @fileOverview Blob
1494
+ */
1495
+ define('lib/blob',[
1496
+ 'base',
1497
+ 'runtime/client'
1498
+ ], function( Base, RuntimeClient ) {
1499
+
1500
+ function Blob( ruid, source ) {
1501
+ var me = this;
1502
+
1503
+ me.source = source;
1504
+ me.ruid = ruid;
1505
+
1506
+ RuntimeClient.call( me, 'Blob' );
1507
+
1508
+ this.uid = source.uid || this.uid;
1509
+ this.type = source.type || '';
1510
+ this.size = source.size || 0;
1511
+
1512
+ if ( ruid ) {
1513
+ me.connectRuntime( ruid );
1514
+ }
1515
+ }
1516
+
1517
+ Base.inherits( RuntimeClient, {
1518
+ constructor: Blob,
1519
+
1520
+ slice: function( start, end ) {
1521
+ return this.exec( 'slice', start, end );
1522
+ },
1523
+
1524
+ getSource: function() {
1525
+ return this.source;
1526
+ }
1527
+ });
1528
+
1529
+ return Blob;
1530
+ });
1531
+ /**
1532
+ * 为了统一化Flash的File和HTML5的File而存在。
1533
+ * 以至于要调用Flash里面的File,也可以像调用HTML5版本的File一下。
1534
+ * @fileOverview File
1535
+ */
1536
+ define('lib/file',[
1537
+ 'base',
1538
+ 'lib/blob'
1539
+ ], function( Base, Blob ) {
1540
+
1541
+ var uid = 1,
1542
+ rExt = /\.([^.]+)$/;
1543
+
1544
+ function File( ruid, file ) {
1545
+ var ext;
1546
+
1547
+ Blob.apply( this, arguments );
1548
+ this.name = file.name || ('untitled' + uid++);
1549
+ ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';
1550
+
1551
+ // todo 支持其他类型文件的转换。
1552
+
1553
+ // 如果有mimetype, 但是文件名里面没有找出后缀规律
1554
+ if ( !ext && this.type ) {
1555
+ ext = /\/(jpg|jpeg|png|gif|bmp)$/i.exec( this.type ) ?
1556
+ RegExp.$1.toLowerCase() : '';
1557
+ this.name += '.' + ext;
1558
+ }
1559
+
1560
+ // 如果没有指定mimetype, 但是知道文件后缀。
1561
+ if ( !this.type && ~'jpg,jpeg,png,gif,bmp'.indexOf( ext ) ) {
1562
+ this.type = 'image/' + (ext === 'jpg' ? 'jpeg' : ext);
1563
+ }
1564
+
1565
+ this.ext = ext;
1566
+ this.lastModifiedDate = file.lastModifiedDate ||
1567
+ (new Date()).toLocaleString();
1568
+ }
1569
+
1570
+ return Base.inherits( Blob, File );
1571
+ });
1572
+
1573
+ /**
1574
+ * @fileOverview 错误信息
1575
+ */
1576
+ define('lib/filepicker',[
1577
+ 'base',
1578
+ 'runtime/client',
1579
+ 'lib/file'
1580
+ ], function( Base, RuntimeClent, File ) {
1581
+
1582
+ var $ = Base.$;
1583
+
1584
+ function FilePicker( opts ) {
1585
+ opts = this.options = $.extend({}, FilePicker.options, opts );
1586
+
1587
+ opts.container = $( opts.id );
1588
+
1589
+ if ( !opts.container.length ) {
1590
+ throw new Error('按钮指定错误');
1591
+ }
1592
+
1593
+ opts.innerHTML = opts.innerHTML || opts.label ||
1594
+ opts.container.html() || '';
1595
+
1596
+ opts.button = $( opts.button || document.createElement('div') );
1597
+ opts.button.html( opts.innerHTML );
1598
+ opts.container.html( opts.button );
1599
+
1600
+ RuntimeClent.call( this, 'FilePicker', true );
1601
+ }
1602
+
1603
+ FilePicker.options = {
1604
+ button: null,
1605
+ container: null,
1606
+ label: null,
1607
+ innerHTML: null,
1608
+ multiple: true,
1609
+ accept: null,
1610
+ name: 'file'
1611
+ };
1612
+
1613
+ Base.inherits( RuntimeClent, {
1614
+ constructor: FilePicker,
1615
+
1616
+ init: function() {
1617
+ var me = this,
1618
+ opts = me.options,
1619
+ button = opts.button;
1620
+
1621
+ button.addClass('webuploader-pick');
1622
+
1623
+ me.on( 'all', function( type ) {
1624
+ var files;
1625
+
1626
+ switch ( type ) {
1627
+ case 'mouseenter':
1628
+ button.addClass('webuploader-pick-hover');
1629
+ break;
1630
+
1631
+ case 'mouseleave':
1632
+ button.removeClass('webuploader-pick-hover');
1633
+ break;
1634
+
1635
+ case 'change':
1636
+ files = me.exec('getFiles');
1637
+ me.trigger( 'select', $.map( files, function( file ) {
1638
+ file = new File( me.getRuid(), file );
1639
+
1640
+ // 记录来源。
1641
+ file._refer = opts.container;
1642
+ return file;
1643
+ }), opts.container );
1644
+ break;
1645
+ }
1646
+ });
1647
+
1648
+ me.connectRuntime( opts, function() {
1649
+ me.refresh();
1650
+ me.exec( 'init', opts );
1651
+ me.trigger('ready');
1652
+ });
1653
+
1654
+ $( window ).on( 'resize', function() {
1655
+ me.refresh();
1656
+ });
1657
+ },
1658
+
1659
+ refresh: function() {
1660
+ var shimContainer = this.getRuntime().getContainer(),
1661
+ button = this.options.button,
1662
+ width = button.outerWidth ?
1663
+ button.outerWidth() : button.width(),
1664
+
1665
+ height = button.outerHeight ?
1666
+ button.outerHeight() : button.height(),
1667
+
1668
+ pos = button.offset();
1669
+
1670
+ width && height && shimContainer.css({
1671
+ bottom: 'auto',
1672
+ right: 'auto',
1673
+ width: width + 'px',
1674
+ height: height + 'px'
1675
+ }).offset( pos );
1676
+ },
1677
+
1678
+ enable: function() {
1679
+ var btn = this.options.button;
1680
+
1681
+ btn.removeClass('webuploader-pick-disable');
1682
+ this.refresh();
1683
+ },
1684
+
1685
+ disable: function() {
1686
+ var btn = this.options.button;
1687
+
1688
+ this.getRuntime().getContainer().css({
1689
+ top: '-99999px'
1690
+ });
1691
+
1692
+ btn.addClass('webuploader-pick-disable');
1693
+ },
1694
+
1695
+ destroy: function() {
1696
+ if ( this.runtime ) {
1697
+ this.exec('destroy');
1698
+ this.disconnectRuntime();
1699
+ }
1700
+ }
1701
+ });
1702
+
1703
+ return FilePicker;
1704
+ });
1705
+
1706
+ /**
1707
+ * @fileOverview 文件选择相关
1708
+ */
1709
+ define('widgets/filepicker',[
1710
+ 'base',
1711
+ 'uploader',
1712
+ 'lib/filepicker',
1713
+ 'widgets/widget'
1714
+ ], function( Base, Uploader, FilePicker ) {
1715
+ var $ = Base.$;
1716
+
1717
+ $.extend( Uploader.options, {
1718
+
1719
+ /**
1720
+ * @property {Selector | Object} [pick=undefined]
1721
+ * @namespace options
1722
+ * @for Uploader
1723
+ * @description 指定选择文件的按钮容器,不指定则不创建按钮。
1724
+ *
1725
+ * * `id` {Seletor} 指定选择文件的按钮容器,不指定则不创建按钮。
1726
+ * * `label` {String} 请采用 `innerHTML` 代替
1727
+ * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。
1728
+ * * `multiple` {Boolean} 是否开起同时选择多个文件能力。
1729
+ */
1730
+ pick: null,
1731
+
1732
+ /**
1733
+ * @property {Arroy} [accept=null]
1734
+ * @namespace options
1735
+ * @for Uploader
1736
+ * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表,所以这里需要分开指定。
1737
+ *
1738
+ * * `title` {String} 文字描述
1739
+ * * `extensions` {String} 允许的文件后缀,不带点,多个用逗号分割。
1740
+ * * `mimeTypes` {String} 多个用逗号分割。
1741
+ *
1742
+ * 如:
1743
+ *
1744
+ * ```
1745
+ * {
1746
+ * title: 'Images',
1747
+ * extensions: 'gif,jpg,jpeg,bmp,png',
1748
+ * mimeTypes: 'image/*'
1749
+ * }
1750
+ * ```
1751
+ */
1752
+ accept: null/*{
1753
+ title: 'Images',
1754
+ extensions: 'gif,jpg,jpeg,bmp,png',
1755
+ mimeTypes: 'image/*'
1756
+ }*/
1757
+ });
1758
+
1759
+ return Uploader.register({
1760
+ 'add-btn': 'addButton',
1761
+ refresh: 'refresh',
1762
+ disable: 'disable',
1763
+ enable: 'enable'
1764
+ }, {
1765
+
1766
+ init: function( opts ) {
1767
+ this.pickers = [];
1768
+ return opts.pick && this.addButton( opts.pick );
1769
+ },
1770
+
1771
+ refresh: function() {
1772
+ $.each( this.pickers, function() {
1773
+ this.refresh();
1774
+ });
1775
+ },
1776
+
1777
+ /**
1778
+ * @method addButton
1779
+ * @for Uploader
1780
+ * @grammar addButton( pick ) => Promise
1781
+ * @description
1782
+ * 添加文件选择按钮,如果一个按钮不够,需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。
1783
+ * @example
1784
+ * uploader.addButton({
1785
+ * id: '#btnContainer',
1786
+ * innerHTML: '选择文件'
1787
+ * });
1788
+ */
1789
+ addButton: function( pick ) {
1790
+ var me = this,
1791
+ opts = me.options,
1792
+ accept = opts.accept,
1793
+ options, picker, deferred;
1794
+
1795
+ if ( !pick ) {
1796
+ return;
1797
+ }
1798
+
1799
+ deferred = Base.Deferred();
1800
+ $.isPlainObject( pick ) || (pick = {
1801
+ id: pick
1802
+ });
1803
+
1804
+ options = $.extend({}, pick, {
1805
+ accept: $.isPlainObject( accept ) ? [ accept ] : accept,
1806
+ swf: opts.swf,
1807
+ runtimeOrder: opts.runtimeOrder
1808
+ });
1809
+
1810
+ picker = new FilePicker( options );
1811
+
1812
+ picker.once( 'ready', deferred.resolve );
1813
+ picker.on( 'select', function( files ) {
1814
+ me.owner.request( 'add-file', [ files ]);
1815
+ });
1816
+ picker.init();
1817
+
1818
+ this.pickers.push( picker );
1819
+
1820
+ return deferred.promise();
1821
+ },
1822
+
1823
+ disable: function() {
1824
+ $.each( this.pickers, function() {
1825
+ this.disable();
1826
+ });
1827
+ },
1828
+
1829
+ enable: function() {
1830
+ $.each( this.pickers, function() {
1831
+ this.enable();
1832
+ });
1833
+ }
1834
+ });
1835
+ });
1836
+ /**
1837
+ * @fileOverview 文件属性封装
1838
+ */
1839
+ define('file',[
1840
+ 'base',
1841
+ 'mediator'
1842
+ ], function( Base, Mediator ) {
1843
+
1844
+ var $ = Base.$,
1845
+ idPrefix = 'WU_FILE_',
1846
+ idSuffix = 0,
1847
+ rExt = /\.([^.]+)$/,
1848
+ statusMap = {};
1849
+
1850
+ function gid() {
1851
+ return idPrefix + idSuffix++;
1852
+ }
1853
+
1854
+ /**
1855
+ * 文件类
1856
+ * @class File
1857
+ * @constructor 构造函数
1858
+ * @grammar new File( source ) => File
1859
+ * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。
1860
+ */
1861
+ function WUFile( source ) {
1862
+
1863
+ /**
1864
+ * 文件名,包括扩展名(后缀)
1865
+ * @property name
1866
+ * @type {string}
1867
+ */
1868
+ this.name = source.name || 'Untitled';
1869
+
1870
+ /**
1871
+ * 文件体积(字节)
1872
+ * @property size
1873
+ * @type {uint}
1874
+ * @default 0
1875
+ */
1876
+ this.size = source.size || 0;
1877
+
1878
+ /**
1879
+ * 文件MIMETYPE类型,与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)
1880
+ * @property type
1881
+ * @type {string}
1882
+ * @default 'application'
1883
+ */
1884
+ this.type = source.type || 'application';
1885
+
1886
+ /**
1887
+ * 文件最后修改日期
1888
+ * @property lastModifiedDate
1889
+ * @type {int}
1890
+ * @default 当前时间戳
1891
+ */
1892
+ this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);
1893
+
1894
+ /**
1895
+ * 文件ID,每个对象具有唯一ID,与文件名无关
1896
+ * @property id
1897
+ * @type {string}
1898
+ */
1899
+ this.id = gid();
1900
+
1901
+ /**
1902
+ * 文件扩展名,通过文件名获取,例如test.png的扩展名为png
1903
+ * @property ext
1904
+ * @type {string}
1905
+ */
1906
+ this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';
1907
+
1908
+
1909
+ /**
1910
+ * 状态文字说明。在不同的status语境下有不同的用途。
1911
+ * @property statusText
1912
+ * @type {string}
1913
+ */
1914
+ this.statusText = '';
1915
+
1916
+ // 存储文件状态,防止通过属性直接修改
1917
+ statusMap[ this.id ] = WUFile.Status.INITED;
1918
+
1919
+ this.source = source;
1920
+ this.loaded = 0;
1921
+
1922
+ this.on( 'error', function( msg ) {
1923
+ this.setStatus( WUFile.Status.ERROR, msg );
1924
+ });
1925
+ }
1926
+
1927
+ $.extend( WUFile.prototype, {
1928
+
1929
+ /**
1930
+ * 设置状态,状态变化时会触发`change`事件。
1931
+ * @method setStatus
1932
+ * @grammar setStatus( status[, statusText] );
1933
+ * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)
1934
+ * @param {String} [statusText=''] 状态说明,常在error时使用,用http, abort,server等来标记是由于什么原因导致文件错误。
1935
+ */
1936
+ setStatus: function( status, text ) {
1937
+
1938
+ var prevStatus = statusMap[ this.id ];
1939
+
1940
+ typeof text !== 'undefined' && (this.statusText = text);
1941
+
1942
+ if ( status !== prevStatus ) {
1943
+ statusMap[ this.id ] = status;
1944
+ /**
1945
+ * 文件状态变化
1946
+ * @event statuschange
1947
+ */
1948
+ this.trigger( 'statuschange', status, prevStatus );
1949
+ }
1950
+
1951
+ },
1952
+
1953
+ /**
1954
+ * 获取文件状态
1955
+ * @return {File.Status}
1956
+ * @example
1957
+ 文件状态具体包括以下几种类型:
1958
+ {
1959
+ // 初始化
1960
+ INITED: 0,
1961
+ // 已入队列
1962
+ QUEUED: 1,
1963
+ // 正在上传
1964
+ PROGRESS: 2,
1965
+ // 上传出错
1966
+ ERROR: 3,
1967
+ // 上传成功
1968
+ COMPLETE: 4,
1969
+ // 上传取消
1970
+ CANCELLED: 5
1971
+ }
1972
+ */
1973
+ getStatus: function() {
1974
+ return statusMap[ this.id ];
1975
+ },
1976
+
1977
+ /**
1978
+ * 获取文件原始信息。
1979
+ * @return {*}
1980
+ */
1981
+ getSource: function() {
1982
+ return this.source;
1983
+ },
1984
+
1985
+ destory: function() {
1986
+ delete statusMap[ this.id ];
1987
+ }
1988
+ });
1989
+
1990
+ Mediator.installTo( WUFile.prototype );
1991
+
1992
+ /**
1993
+ * 文件状态值,具体包括以下几种类型:
1994
+ * * `inited` 初始状态
1995
+ * * `queued` 已经进入队列, 等待上传
1996
+ * * `progress` 上传中
1997
+ * * `complete` 上传完成。
1998
+ * * `error` 上传出错,可重试
1999
+ * * `interrupt` 上传中断,可续传。
2000
+ * * `invalid` 文件不合格,不能重试上传。会自动从队列中移除。
2001
+ * * `cancelled` 文件被移除。
2002
+ * @property {Object} Status
2003
+ * @namespace File
2004
+ * @class File
2005
+ * @static
2006
+ */
2007
+ WUFile.Status = {
2008
+ INITED: 'inited', // 初始状态
2009
+ QUEUED: 'queued', // 已经进入队列, 等待上传
2010
+ PROGRESS: 'progress', // 上传中
2011
+ ERROR: 'error', // 上传出错,可重试
2012
+ COMPLETE: 'complete', // 上传完成。
2013
+ CANCELLED: 'cancelled', // 上传取消。
2014
+ INTERRUPT: 'interrupt', // 上传中断,可续传。
2015
+ INVALID: 'invalid' // 文件不合格,不能重试上传。
2016
+ };
2017
+
2018
+ return WUFile;
2019
+ });
2020
+
2021
+ /**
2022
+ * @fileOverview 文件队列
2023
+ */
2024
+ define('queue',[
2025
+ 'base',
2026
+ 'mediator',
2027
+ 'file'
2028
+ ], function( Base, Mediator, WUFile ) {
2029
+
2030
+ var $ = Base.$,
2031
+ STATUS = WUFile.Status;
2032
+
2033
+ /**
2034
+ * 文件队列, 用来存储各个状态中的文件。
2035
+ * @class Queue
2036
+ * @extends Mediator
2037
+ */
2038
+ function Queue() {
2039
+
2040
+ /**
2041
+ * 统计文件数。
2042
+ * * `numOfQueue` 队列中的文件数。
2043
+ * * `numOfSuccess` 上传成功的文件数
2044
+ * * `numOfCancel` 被移除的文件数
2045
+ * * `numOfProgress` 正在上传中的文件数
2046
+ * * `numOfUploadFailed` 上传错误的文件数。
2047
+ * * `numOfInvalid` 无效的文件数。
2048
+ * @property {Object} stats
2049
+ */
2050
+ this.stats = {
2051
+ numOfQueue: 0,
2052
+ numOfSuccess: 0,
2053
+ numOfCancel: 0,
2054
+ numOfProgress: 0,
2055
+ numOfUploadFailed: 0,
2056
+ numOfInvalid: 0
2057
+ };
2058
+
2059
+ // 上传队列,仅包括等待上传的文件
2060
+ this._queue = [];
2061
+
2062
+ // 存储所有文件
2063
+ this._map = {};
2064
+ }
2065
+
2066
+ $.extend( Queue.prototype, {
2067
+
2068
+ /**
2069
+ * 将新文件加入对队列尾部
2070
+ *
2071
+ * @method append
2072
+ * @param {File} file 文件对象
2073
+ */
2074
+ append: function( file ) {
2075
+ this._queue.push( file );
2076
+ this._fileAdded( file );
2077
+ return this;
2078
+ },
2079
+
2080
+ /**
2081
+ * 将新文件加入对队列头部
2082
+ *
2083
+ * @method prepend
2084
+ * @param {File} file 文件对象
2085
+ */
2086
+ prepend: function( file ) {
2087
+ this._queue.unshift( file );
2088
+ this._fileAdded( file );
2089
+ return this;
2090
+ },
2091
+
2092
+ /**
2093
+ * 获取文件对象
2094
+ *
2095
+ * @method getFile
2096
+ * @param {String} fileId 文件ID
2097
+ * @return {File}
2098
+ */
2099
+ getFile: function( fileId ) {
2100
+ if ( typeof fileId !== 'string' ) {
2101
+ return fileId;
2102
+ }
2103
+ return this._map[ fileId ];
2104
+ },
2105
+
2106
+ /**
2107
+ * 从队列中取出一个指定状态的文件。
2108
+ * @grammar fetch( status ) => File
2109
+ * @method fetch
2110
+ * @param {String} status [文件状态值](#WebUploader:File:File.Status)
2111
+ * @return {File} [File](#WebUploader:File)
2112
+ */
2113
+ fetch: function( status ) {
2114
+ var len = this._queue.length,
2115
+ i, file;
2116
+
2117
+ status = status || STATUS.QUEUED;
2118
+
2119
+ for ( i = 0; i < len; i++ ) {
2120
+ file = this._queue[ i ];
2121
+
2122
+ if ( status === file.getStatus() ) {
2123
+ return file;
2124
+ }
2125
+ }
2126
+
2127
+ return null;
2128
+ },
2129
+
2130
+ /**
2131
+ * 对队列进行排序,能够控制文件上传顺序。
2132
+ * @grammar sort( fn ) => undefined
2133
+ * @method sort
2134
+ * @param {Function} fn 排序方法
2135
+ */
2136
+ sort: function( fn ) {
2137
+ if ( typeof fn === 'function' ) {
2138
+ this._queue.sort( fn );
2139
+ }
2140
+ },
2141
+
2142
+ /**
2143
+ * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。
2144
+ * @grammar getFiles( [status1[, status2 ...]] ) => Array
2145
+ * @method getFiles
2146
+ * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)
2147
+ */
2148
+ getFiles: function() {
2149
+ var sts = [].slice.call( arguments, 0 ),
2150
+ ret = [],
2151
+ i = 0,
2152
+ len = this._queue.length,
2153
+ file;
2154
+
2155
+ for ( ; i < len; i++ ) {
2156
+ file = this._queue[ i ];
2157
+
2158
+ if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {
2159
+ continue;
2160
+ }
2161
+
2162
+ ret.push( file );
2163
+ }
2164
+
2165
+ return ret;
2166
+ },
2167
+
2168
+ _fileAdded: function( file ) {
2169
+ var me = this,
2170
+ existing = this._map[ file.id ];
2171
+
2172
+ if ( !existing ) {
2173
+ this._map[ file.id ] = file;
2174
+
2175
+ file.on( 'statuschange', function( cur, pre ) {
2176
+ me._onFileStatusChange( cur, pre );
2177
+ });
2178
+ }
2179
+
2180
+ file.setStatus( STATUS.QUEUED );
2181
+ },
2182
+
2183
+ _onFileStatusChange: function( curStatus, preStatus ) {
2184
+ var stats = this.stats;
2185
+
2186
+ switch ( preStatus ) {
2187
+ case STATUS.PROGRESS:
2188
+ stats.numOfProgress--;
2189
+ break;
2190
+
2191
+ case STATUS.QUEUED:
2192
+ stats.numOfQueue --;
2193
+ break;
2194
+
2195
+ case STATUS.ERROR:
2196
+ stats.numOfUploadFailed--;
2197
+ break;
2198
+
2199
+ case STATUS.INVALID:
2200
+ stats.numOfInvalid--;
2201
+ break;
2202
+ }
2203
+
2204
+ switch ( curStatus ) {
2205
+ case STATUS.QUEUED:
2206
+ stats.numOfQueue++;
2207
+ break;
2208
+
2209
+ case STATUS.PROGRESS:
2210
+ stats.numOfProgress++;
2211
+ break;
2212
+
2213
+ case STATUS.ERROR:
2214
+ stats.numOfUploadFailed++;
2215
+ break;
2216
+
2217
+ case STATUS.COMPLETE:
2218
+ stats.numOfSuccess++;
2219
+ break;
2220
+
2221
+ case STATUS.CANCELLED:
2222
+ stats.numOfCancel++;
2223
+ break;
2224
+
2225
+ case STATUS.INVALID:
2226
+ stats.numOfInvalid++;
2227
+ break;
2228
+ }
2229
+ }
2230
+
2231
+ });
2232
+
2233
+ Mediator.installTo( Queue.prototype );
2234
+
2235
+ return Queue;
2236
+ });
2237
+ /**
2238
+ * @fileOverview 队列
2239
+ */
2240
+ define('widgets/queue',[
2241
+ 'base',
2242
+ 'uploader',
2243
+ 'queue',
2244
+ 'file',
2245
+ 'lib/file',
2246
+ 'runtime/client',
2247
+ 'widgets/widget'
2248
+ ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {
2249
+
2250
+ var $ = Base.$,
2251
+ rExt = /\.\w+$/,
2252
+ Status = WUFile.Status;
2253
+
2254
+ return Uploader.register({
2255
+ 'sort-files': 'sortFiles',
2256
+ 'add-file': 'addFiles',
2257
+ 'get-file': 'getFile',
2258
+ 'fetch-file': 'fetchFile',
2259
+ 'get-stats': 'getStats',
2260
+ 'get-files': 'getFiles',
2261
+ 'remove-file': 'removeFile',
2262
+ 'retry': 'retry',
2263
+ 'reset': 'reset',
2264
+ 'accept-file': 'acceptFile'
2265
+ }, {
2266
+
2267
+ init: function( opts ) {
2268
+ var me = this,
2269
+ deferred, len, i, item, arr, accept, runtime;
2270
+
2271
+ if ( $.isPlainObject( opts.accept ) ) {
2272
+ opts.accept = [ opts.accept ];
2273
+ }
2274
+
2275
+ // accept中的中生成匹配正则。
2276
+ if ( opts.accept ) {
2277
+ arr = [];
2278
+
2279
+ for ( i = 0, len = opts.accept.length; i < len; i++ ) {
2280
+ item = opts.accept[ i ].extensions;
2281
+ item && arr.push( item );
2282
+ }
2283
+
2284
+ if ( arr.length ) {
2285
+ accept = '\\.' + arr.join(',')
2286
+ .replace( /,/g, '$|\\.' )
2287
+ .replace( /\*/g, '.*' ) + '$';
2288
+ }
2289
+
2290
+ me.accept = new RegExp( accept, 'i' );
2291
+ }
2292
+
2293
+ me.queue = new Queue();
2294
+ me.stats = me.queue.stats;
2295
+
2296
+ // 如果当前不是html5运行时,那就算了。
2297
+ // 不执行后续操作
2298
+ if ( this.request('predict-runtime-type') !== 'html5' ) {
2299
+ return;
2300
+ }
2301
+
2302
+ // 创建一个 html5 运行时的 placeholder
2303
+ // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。
2304
+ deferred = Base.Deferred();
2305
+ runtime = new RuntimeClient('Placeholder');
2306
+ runtime.connectRuntime({
2307
+ runtimeOrder: 'html5'
2308
+ }, function() {
2309
+ me._ruid = runtime.getRuid();
2310
+ deferred.resolve();
2311
+ });
2312
+ return deferred.promise();
2313
+ },
2314
+
2315
+
2316
+ // 为了支持外部直接添加一个原生File对象。
2317
+ _wrapFile: function( file ) {
2318
+ if ( !(file instanceof WUFile) ) {
2319
+
2320
+ if ( !(file instanceof File) ) {
2321
+ if ( !this._ruid ) {
2322
+ throw new Error('Can\'t add external files.');
2323
+ }
2324
+ file = new File( this._ruid, file );
2325
+ }
2326
+
2327
+ file = new WUFile( file );
2328
+ }
2329
+
2330
+ return file;
2331
+ },
2332
+
2333
+ // 判断文件是否可以被加入队列
2334
+ acceptFile: function( file ) {
2335
+ var invalid = !file || file.size < 6 || this.accept &&
2336
+
2337
+ // 如果名字中有后缀,才做后缀白名单处理。
2338
+ rExt.exec( file.name ) && !this.accept.test( file.name );
2339
+
2340
+ return !invalid;
2341
+ },
2342
+
2343
+
2344
+ /**
2345
+ * @event beforeFileQueued
2346
+ * @param {File} file File对象
2347
+ * @description 当文件被加入队列之前触发,此事件的handler返回值为`false`,则此文件不会被添加进入队列。
2348
+ * @for Uploader
2349
+ */
2350
+
2351
+ /**
2352
+ * @event fileQueued
2353
+ * @param {File} file File对象
2354
+ * @description 当文件被加入队列以后触发。
2355
+ * @for Uploader
2356
+ */
2357
+
2358
+ _addFile: function( file ) {
2359
+ var me = this;
2360
+
2361
+ file = me._wrapFile( file );
2362
+
2363
+ // 不过类型判断允许不允许,先派送 `beforeFileQueued`
2364
+ if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {
2365
+ return;
2366
+ }
2367
+
2368
+ // 类型不匹配,则派送错误事件,并返回。
2369
+ if ( !me.acceptFile( file ) ) {
2370
+ me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );
2371
+ return;
2372
+ }
2373
+
2374
+ me.queue.append( file );
2375
+ me.owner.trigger( 'fileQueued', file );
2376
+ return file;
2377
+ },
2378
+
2379
+ getFile: function( fileId ) {
2380
+ return this.queue.getFile( fileId );
2381
+ },
2382
+
2383
+ /**
2384
+ * @event filesQueued
2385
+ * @param {File} files 数组,内容为原始File(lib/File)对象。
2386
+ * @description 当一批文件添加进队列以后触发。
2387
+ * @for Uploader
2388
+ */
2389
+
2390
+ /**
2391
+ * @method addFiles
2392
+ * @grammar addFiles( file ) => undefined
2393
+ * @grammar addFiles( [file1, file2 ...] ) => undefined
2394
+ * @param {Array of File or File} [files] Files 对象 数组
2395
+ * @description 添加文件到队列
2396
+ * @for Uploader
2397
+ */
2398
+ addFiles: function( files ) {
2399
+ var me = this;
2400
+
2401
+ if ( !files.length ) {
2402
+ files = [ files ];
2403
+ }
2404
+
2405
+ files = $.map( files, function( file ) {
2406
+ return me._addFile( file );
2407
+ });
2408
+
2409
+ me.owner.trigger( 'filesQueued', files );
2410
+
2411
+ if ( me.options.auto ) {
2412
+ me.request('start-upload');
2413
+ }
2414
+ },
2415
+
2416
+ getStats: function() {
2417
+ return this.stats;
2418
+ },
2419
+
2420
+ /**
2421
+ * @event fileDequeued
2422
+ * @param {File} file File对象
2423
+ * @description 当文件被移除队列后触发。
2424
+ * @for Uploader
2425
+ */
2426
+
2427
+ /**
2428
+ * @method removeFile
2429
+ * @grammar removeFile( file ) => undefined
2430
+ * @grammar removeFile( id ) => undefined
2431
+ * @param {File|id} file File对象或这File对象的id
2432
+ * @description 移除某一文件。
2433
+ * @for Uploader
2434
+ * @example
2435
+ *
2436
+ * $li.on('click', '.remove-this', function() {
2437
+ * uploader.removeFile( file );
2438
+ * })
2439
+ */
2440
+ removeFile: function( file ) {
2441
+ var me = this;
2442
+
2443
+ file = file.id ? file : me.queue.getFile( file );
2444
+
2445
+ file.setStatus( Status.CANCELLED );
2446
+ me.owner.trigger( 'fileDequeued', file );
2447
+ },
2448
+
2449
+ /**
2450
+ * @method getFiles
2451
+ * @grammar getFiles() => Array
2452
+ * @grammar getFiles( status1, status2, status... ) => Array
2453
+ * @description 返回指定状态的文件集合,不传参数将返回所有状态的文件。
2454
+ * @for Uploader
2455
+ * @example
2456
+ * console.log( uploader.getFiles() ); // => all files
2457
+ * console.log( uploader.getFiles('error') ) // => all error files.
2458
+ */
2459
+ getFiles: function() {
2460
+ return this.queue.getFiles.apply( this.queue, arguments );
2461
+ },
2462
+
2463
+ fetchFile: function() {
2464
+ return this.queue.fetch.apply( this.queue, arguments );
2465
+ },
2466
+
2467
+ /**
2468
+ * @method retry
2469
+ * @grammar retry() => undefined
2470
+ * @grammar retry( file ) => undefined
2471
+ * @description 重试上传,重试指定文件,或者从出错的文件开始重新上传。
2472
+ * @for Uploader
2473
+ * @example
2474
+ * function retry() {
2475
+ * uploader.retry();
2476
+ * }
2477
+ */
2478
+ retry: function( file, noForceStart ) {
2479
+ var me = this,
2480
+ files, i, len;
2481
+
2482
+ if ( file ) {
2483
+ file = file.id ? file : me.queue.getFile( file );
2484
+ file.setStatus( Status.QUEUED );
2485
+ noForceStart || me.request('start-upload');
2486
+ return;
2487
+ }
2488
+
2489
+ files = me.queue.getFiles( Status.ERROR );
2490
+ i = 0;
2491
+ len = files.length;
2492
+
2493
+ for ( ; i < len; i++ ) {
2494
+ file = files[ i ];
2495
+ file.setStatus( Status.QUEUED );
2496
+ }
2497
+
2498
+ me.request('start-upload');
2499
+ },
2500
+
2501
+ /**
2502
+ * @method sort
2503
+ * @grammar sort( fn ) => undefined
2504
+ * @description 排序队列中的文件,在上传之前调整可以控制上传顺序。
2505
+ * @for Uploader
2506
+ */
2507
+ sortFiles: function() {
2508
+ return this.queue.sort.apply( this.queue, arguments );
2509
+ },
2510
+
2511
+ /**
2512
+ * @method reset
2513
+ * @grammar reset() => undefined
2514
+ * @description 重置uploader。目前只重置了队列。
2515
+ * @for Uploader
2516
+ * @example
2517
+ * uploader.reset();
2518
+ */
2519
+ reset: function() {
2520
+ this.queue = new Queue();
2521
+ this.stats = this.queue.stats;
2522
+ }
2523
+ });
2524
+
2525
+ });
2526
+ /**
2527
+ * @fileOverview 添加获取Runtime相关信息的方法。
2528
+ */
2529
+ define('widgets/runtime',[
2530
+ 'uploader',
2531
+ 'runtime/runtime',
2532
+ 'widgets/widget'
2533
+ ], function( Uploader, Runtime ) {
2534
+
2535
+ Uploader.support = function() {
2536
+ return Runtime.hasRuntime.apply( Runtime, arguments );
2537
+ };
2538
+
2539
+ return Uploader.register({
2540
+ 'predict-runtime-type': 'predictRuntmeType'
2541
+ }, {
2542
+
2543
+ init: function() {
2544
+ if ( !this.predictRuntmeType() ) {
2545
+ throw Error('Runtime Error');
2546
+ }
2547
+ },
2548
+
2549
+ /**
2550
+ * 预测Uploader将采用哪个`Runtime`
2551
+ * @grammar predictRuntmeType() => String
2552
+ * @method predictRuntmeType
2553
+ * @for Uploader
2554
+ */
2555
+ predictRuntmeType: function() {
2556
+ var orders = this.options.runtimeOrder || Runtime.orders,
2557
+ type = this.type,
2558
+ i, len;
2559
+
2560
+ if ( !type ) {
2561
+ orders = orders.split( /\s*,\s*/g );
2562
+
2563
+ for ( i = 0, len = orders.length; i < len; i++ ) {
2564
+ if ( Runtime.hasRuntime( orders[ i ] ) ) {
2565
+ this.type = type = orders[ i ];
2566
+ break;
2567
+ }
2568
+ }
2569
+ }
2570
+
2571
+ return type;
2572
+ }
2573
+ });
2574
+ });
2575
+ /**
2576
+ * @fileOverview Transport
2577
+ */
2578
+ define('lib/transport',[
2579
+ 'base',
2580
+ 'runtime/client',
2581
+ 'mediator'
2582
+ ], function( Base, RuntimeClient, Mediator ) {
2583
+
2584
+ var $ = Base.$;
2585
+
2586
+ function Transport( opts ) {
2587
+ var me = this;
2588
+
2589
+ opts = me.options = $.extend( true, {}, Transport.options, opts || {} );
2590
+ RuntimeClient.call( this, 'Transport' );
2591
+
2592
+ this._blob = null;
2593
+ this._formData = opts.formData || {};
2594
+ this._headers = opts.headers || {};
2595
+
2596
+ this.on( 'progress', this._timeout );
2597
+ this.on( 'load error', function() {
2598
+ me.trigger( 'progress', 1 );
2599
+ clearTimeout( me._timer );
2600
+ });
2601
+ }
2602
+
2603
+ Transport.options = {
2604
+ server: '',
2605
+ method: 'POST',
2606
+
2607
+ // 跨域时,是否允许携带cookie, 只有html5 runtime才有效
2608
+ withCredentials: false,
2609
+ fileVal: 'file',
2610
+ timeout: 2 * 60 * 1000, // 2分钟
2611
+ formData: {},
2612
+ headers: {},
2613
+ sendAsBinary: false
2614
+ };
2615
+
2616
+ $.extend( Transport.prototype, {
2617
+
2618
+ // 添加Blob, 只能添加一次,最后一次有效。
2619
+ appendBlob: function( key, blob, filename ) {
2620
+ var me = this,
2621
+ opts = me.options;
2622
+
2623
+ if ( me.getRuid() ) {
2624
+ me.disconnectRuntime();
2625
+ }
2626
+
2627
+ // 连接到blob归属的同一个runtime.
2628
+ me.connectRuntime( blob.ruid, function() {
2629
+ me.exec('init');
2630
+ });
2631
+
2632
+ me._blob = blob;
2633
+ opts.fileVal = key || opts.fileVal;
2634
+ opts.filename = filename || opts.filename;
2635
+ },
2636
+
2637
+ // 添加其他字段
2638
+ append: function( key, value ) {
2639
+ if ( typeof key === 'object' ) {
2640
+ $.extend( this._formData, key );
2641
+ } else {
2642
+ this._formData[ key ] = value;
2643
+ }
2644
+ },
2645
+
2646
+ setRequestHeader: function( key, value ) {
2647
+ if ( typeof key === 'object' ) {
2648
+ $.extend( this._headers, key );
2649
+ } else {
2650
+ this._headers[ key ] = value;
2651
+ }
2652
+ },
2653
+
2654
+ send: function( method ) {
2655
+ this.exec( 'send', method );
2656
+ this._timeout();
2657
+ },
2658
+
2659
+ abort: function() {
2660
+ clearTimeout( this._timer );
2661
+ return this.exec('abort');
2662
+ },
2663
+
2664
+ destroy: function() {
2665
+ this.trigger('destroy');
2666
+ this.off();
2667
+ this.exec('destroy');
2668
+ this.disconnectRuntime();
2669
+ },
2670
+
2671
+ getResponse: function() {
2672
+ return this.exec('getResponse');
2673
+ },
2674
+
2675
+ getResponseAsJson: function() {
2676
+ return this.exec('getResponseAsJson');
2677
+ },
2678
+
2679
+ getStatus: function() {
2680
+ return this.exec('getStatus');
2681
+ },
2682
+
2683
+ _timeout: function() {
2684
+ var me = this,
2685
+ duration = me.options.timeout;
2686
+
2687
+ if ( !duration ) {
2688
+ return;
2689
+ }
2690
+
2691
+ clearTimeout( me._timer );
2692
+ me._timer = setTimeout(function() {
2693
+ me.abort();
2694
+ me.trigger( 'error', 'timeout' );
2695
+ }, duration );
2696
+ }
2697
+
2698
+ });
2699
+
2700
+ // 让Transport具备事件功能。
2701
+ Mediator.installTo( Transport.prototype );
2702
+
2703
+ return Transport;
2704
+ });
2705
+ /**
2706
+ * @fileOverview 负责文件上传相关。
2707
+ */
2708
+ define('widgets/upload',[
2709
+ 'base',
2710
+ 'uploader',
2711
+ 'file',
2712
+ 'lib/transport',
2713
+ 'widgets/widget'
2714
+ ], function( Base, Uploader, WUFile, Transport ) {
2715
+
2716
+ var $ = Base.$,
2717
+ isPromise = Base.isPromise,
2718
+ Status = WUFile.Status;
2719
+
2720
+ // 添加默认配置项
2721
+ $.extend( Uploader.options, {
2722
+
2723
+
2724
+ /**
2725
+ * @property {Boolean} [prepareNextFile=false]
2726
+ * @namespace options
2727
+ * @for Uploader
2728
+ * @description 是否允许在文件传输时提前把下一个文件准备好。
2729
+ * 对于一个文件的准备工作比较耗时,比如图片压缩,md5序列化。
2730
+ * 如果能提前在当前文件传输期处理,可以节省总体耗时。
2731
+ */
2732
+ prepareNextFile: false,
2733
+
2734
+ /**
2735
+ * @property {Boolean} [chunked=false]
2736
+ * @namespace options
2737
+ * @for Uploader
2738
+ * @description 是否要分片处理大文件上传。
2739
+ */
2740
+ chunked: false,
2741
+
2742
+ /**
2743
+ * @property {Boolean} [chunkSize=5242880]
2744
+ * @namespace options
2745
+ * @for Uploader
2746
+ * @description 如果要分片,分多大一片? 默认大小为5M.
2747
+ */
2748
+ chunkSize: 5 * 1024 * 1024,
2749
+
2750
+ /**
2751
+ * @property {Boolean} [chunkRetry=2]
2752
+ * @namespace options
2753
+ * @for Uploader
2754
+ * @description 如果某个分片由于网络问题出错,允许自动重传多少次?
2755
+ */
2756
+ chunkRetry: 2,
2757
+
2758
+ /**
2759
+ * @property {Boolean} [threads=3]
2760
+ * @namespace options
2761
+ * @for Uploader
2762
+ * @description 上传并发数。允许同时最大上传进程数。
2763
+ */
2764
+ threads: 3,
2765
+
2766
+
2767
+ /**
2768
+ * @property {Object} [formData]
2769
+ * @namespace options
2770
+ * @for Uploader
2771
+ * @description 文件上传请求的参数表,每次发送都会发送此对象中的参数。
2772
+ */
2773
+ formData: null
2774
+
2775
+ /**
2776
+ * @property {Object} [fileVal='file']
2777
+ * @namespace options
2778
+ * @for Uploader
2779
+ * @description 设置文件上传域的name。
2780
+ */
2781
+
2782
+ /**
2783
+ * @property {Object} [method='POST']
2784
+ * @namespace options
2785
+ * @for Uploader
2786
+ * @description 文件上传方式,`POST`或者`GET`。
2787
+ */
2788
+
2789
+ /**
2790
+ * @property {Object} [sendAsBinary=false]
2791
+ * @namespace options
2792
+ * @for Uploader
2793
+ * @description 是否已二进制的流的方式发送文件,这样整个上传内容`php://input`都为文件内容,
2794
+ * 其他参数在$_GET数组中。
2795
+ */
2796
+ });
2797
+
2798
+ // 负责将文件切片。
2799
+ function CuteFile( file, chunkSize ) {
2800
+ var pending = [],
2801
+ blob = file.source,
2802
+ total = blob.size,
2803
+ chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,
2804
+ start = 0,
2805
+ index = 0,
2806
+ len;
2807
+
2808
+ while ( index < chunks ) {
2809
+ len = Math.min( chunkSize, total - start );
2810
+
2811
+ pending.push({
2812
+ file: file,
2813
+ start: start,
2814
+ end: chunkSize ? (start + len) : total,
2815
+ total: total,
2816
+ chunks: chunks,
2817
+ chunk: index++
2818
+ });
2819
+ start += len;
2820
+ }
2821
+
2822
+ file.blocks = pending.concat();
2823
+ file.remaning = pending.length;
2824
+
2825
+ return {
2826
+ file: file,
2827
+
2828
+ has: function() {
2829
+ return !!pending.length;
2830
+ },
2831
+
2832
+ fetch: function() {
2833
+ return pending.shift();
2834
+ }
2835
+ };
2836
+ }
2837
+
2838
+ Uploader.register({
2839
+ 'start-upload': 'start',
2840
+ 'stop-upload': 'stop',
2841
+ 'skip-file': 'skipFile',
2842
+ 'is-in-progress': 'isInProgress'
2843
+ }, {
2844
+
2845
+ init: function() {
2846
+ var owner = this.owner;
2847
+
2848
+ this.runing = false;
2849
+
2850
+ // 记录当前正在传的数据,跟threads相关
2851
+ this.pool = [];
2852
+
2853
+ // 缓存即将上传的文件。
2854
+ this.pending = [];
2855
+
2856
+ // 跟踪还有多少分片没有完成上传。
2857
+ this.remaning = 0;
2858
+ this.__tick = Base.bindFn( this._tick, this );
2859
+
2860
+ owner.on( 'uploadComplete', function( file ) {
2861
+ // 把其他块取消了。
2862
+ file.blocks && $.each( file.blocks, function( _, v ) {
2863
+ v.transport && (v.transport.abort(), v.transport.destroy());
2864
+ delete v.transport;
2865
+ });
2866
+
2867
+ delete file.blocks;
2868
+ delete file.remaning;
2869
+ });
2870
+ },
2871
+
2872
+ /**
2873
+ * @event startUpload
2874
+ * @description 当开始上传流程时触发。
2875
+ * @for Uploader
2876
+ */
2877
+
2878
+ /**
2879
+ * 开始上传。此方法可以从初始状态调用开始上传流程,也可以从暂停状态调用,继续上传流程。
2880
+ * @grammar upload() => undefined
2881
+ * @method upload
2882
+ * @for Uploader
2883
+ */
2884
+ start: function() {
2885
+ var me = this;
2886
+
2887
+ // 移出invalid的文件
2888
+ $.each( me.request( 'get-files', Status.INVALID ), function() {
2889
+ me.request( 'remove-file', this );
2890
+ });
2891
+
2892
+ if ( me.runing ) {
2893
+ return;
2894
+ }
2895
+
2896
+ me.runing = true;
2897
+
2898
+ // 如果有暂停的,则续传
2899
+ $.each( me.pool, function( _, v ) {
2900
+ var file = v.file;
2901
+
2902
+ if ( file.getStatus() === Status.INTERRUPT ) {
2903
+ file.setStatus( Status.PROGRESS );
2904
+ me._trigged = false;
2905
+ v.transport && v.transport.send();
2906
+ }
2907
+ });
2908
+
2909
+ me._trigged = false;
2910
+ me.owner.trigger('startUpload');
2911
+ Base.nextTick( me.__tick );
2912
+ },
2913
+
2914
+ /**
2915
+ * @event stopUpload
2916
+ * @description 当开始上传流程暂停时触发。
2917
+ * @for Uploader
2918
+ */
2919
+
2920
+ /**
2921
+ * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。
2922
+ * @grammar stop() => undefined
2923
+ * @grammar stop( true ) => undefined
2924
+ * @method stop
2925
+ * @for Uploader
2926
+ */
2927
+ stop: function( interrupt ) {
2928
+ var me = this;
2929
+
2930
+ if ( me.runing === false ) {
2931
+ return;
2932
+ }
2933
+
2934
+ me.runing = false;
2935
+
2936
+ interrupt && $.each( me.pool, function( _, v ) {
2937
+ v.transport && v.transport.abort();
2938
+ v.file.setStatus( Status.INTERRUPT );
2939
+ });
2940
+
2941
+ me.owner.trigger('stopUpload');
2942
+ },
2943
+
2944
+ /**
2945
+ * 判断`Uplaode`r是否正在上传中。
2946
+ * @grammar isInProgress() => Boolean
2947
+ * @method isInProgress
2948
+ * @for Uploader
2949
+ */
2950
+ isInProgress: function() {
2951
+ return !!this.runing;
2952
+ },
2953
+
2954
+ getStats: function() {
2955
+ return this.request('get-stats');
2956
+ },
2957
+
2958
+ /**
2959
+ * 掉过一个文件上传,直接标记指定文件为已上传状态。
2960
+ * @grammar skipFile( file ) => undefined
2961
+ * @method skipFile
2962
+ * @for Uploader
2963
+ */
2964
+ skipFile: function( file, status ) {
2965
+ file = this.request( 'get-file', file );
2966
+
2967
+ file.setStatus( status || Status.COMPLETE );
2968
+ file.skipped = true;
2969
+
2970
+ // 如果正在上传。
2971
+ file.blocks && $.each( file.blocks, function( _, v ) {
2972
+ var _tr = v.transport;
2973
+
2974
+ if ( _tr ) {
2975
+ _tr.abort();
2976
+ _tr.destroy();
2977
+ delete v.transport;
2978
+ }
2979
+ });
2980
+
2981
+ this.owner.trigger( 'uploadSkip', file );
2982
+ },
2983
+
2984
+ /**
2985
+ * @event uploadFinished
2986
+ * @description 当所有文件上传结束时触发。
2987
+ * @for Uploader
2988
+ */
2989
+ _tick: function() {
2990
+ var me = this,
2991
+ opts = me.options,
2992
+ fn, val;
2993
+
2994
+ // 上一个promise还没有结束,则等待完成后再执行。
2995
+ if ( me._promise ) {
2996
+ return me._promise.always( me.__tick );
2997
+ }
2998
+
2999
+ // 还有位置,且还有文件要处理的话。
3000
+ if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {
3001
+ me._trigged = false;
3002
+
3003
+ fn = function( val ) {
3004
+ me._promise = null;
3005
+
3006
+ // 有可能是reject过来的,所以要检测val的类型。
3007
+ val && val.file && me._startSend( val );
3008
+ Base.nextTick( me.__tick );
3009
+ };
3010
+
3011
+ me._promise = isPromise( val ) ? val.always( fn ) : fn( val );
3012
+
3013
+ // 没有要上传的了,且没有正在传输的了。
3014
+ } else if ( !me.remaning && !me.getStats().numOfQueue ) {
3015
+ me.runing = false;
3016
+
3017
+ me._trigged || Base.nextTick(function() {
3018
+ me.owner.trigger('uploadFinished');
3019
+ });
3020
+ me._trigged = true;
3021
+ }
3022
+ },
3023
+
3024
+ _nextBlock: function() {
3025
+ var me = this,
3026
+ act = me._act,
3027
+ opts = me.options,
3028
+ next, done;
3029
+
3030
+ // 如果当前文件还有没有需要传输的,则直接返回剩下的。
3031
+ if ( act && act.has() &&
3032
+ act.file.getStatus() === Status.PROGRESS ) {
3033
+
3034
+ // 是否提前准备下一个文件
3035
+ if ( opts.prepareNextFile && !me.pending.length ) {
3036
+ me._prepareNextFile();
3037
+ }
3038
+
3039
+ return act.fetch();
3040
+
3041
+ // 否则,如果正在运行,则准备下一个文件,并等待完成后返回下个分片。
3042
+ } else if ( me.runing ) {
3043
+
3044
+ // 如果缓存中有,则直接在缓存中取,没有则去queue中取。
3045
+ if ( !me.pending.length && me.getStats().numOfQueue ) {
3046
+ me._prepareNextFile();
3047
+ }
3048
+
3049
+ next = me.pending.shift();
3050
+ done = function( file ) {
3051
+ if ( !file ) {
3052
+ return null;
3053
+ }
3054
+
3055
+ act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );
3056
+ me._act = act;
3057
+ return act.fetch();
3058
+ };
3059
+
3060
+ // 文件可能还在prepare中,也有可能已经完全准备好了。
3061
+ return isPromise( next ) ?
3062
+ next[ next.pipe ? 'pipe' : 'then']( done ) :
3063
+ done( next );
3064
+ }
3065
+ },
3066
+
3067
+
3068
+ /**
3069
+ * @event uploadStart
3070
+ * @param {File} file File对象
3071
+ * @description 某个文件开始上传前触发,一个文件只会触发一次。
3072
+ * @for Uploader
3073
+ */
3074
+ _prepareNextFile: function() {
3075
+ var me = this,
3076
+ file = me.request('fetch-file'),
3077
+ pending = me.pending,
3078
+ promise;
3079
+
3080
+ if ( file ) {
3081
+ promise = me.request( 'before-send-file', file, function() {
3082
+
3083
+ // 有可能文件被skip掉了。文件被skip掉后,状态坑定不是Queued.
3084
+ if ( file.getStatus() === Status.QUEUED ) {
3085
+ me.owner.trigger( 'uploadStart', file );
3086
+ file.setStatus( Status.PROGRESS );
3087
+ return file;
3088
+ }
3089
+
3090
+ return me._finishFile( file );
3091
+ });
3092
+
3093
+ // 如果还在pending中,则替换成文件本身。
3094
+ promise.done(function() {
3095
+ var idx = $.inArray( promise, pending );
3096
+
3097
+ ~idx && pending.splice( idx, 1, file );
3098
+ });
3099
+
3100
+ // befeore-send-file的钩子就有错误发生。
3101
+ promise.fail(function( reason ) {
3102
+ file.setStatus( Status.ERROR, reason );
3103
+ me.owner.trigger( 'uploadError', file, reason );
3104
+ me.owner.trigger( 'uploadComplete', file );
3105
+ });
3106
+
3107
+ pending.push( promise );
3108
+ }
3109
+ },
3110
+
3111
+ // 让出位置了,可以让其他分片开始上传
3112
+ _popBlock: function( block ) {
3113
+ var idx = $.inArray( block, this.pool );
3114
+
3115
+ this.pool.splice( idx, 1 );
3116
+ block.file.remaning--;
3117
+ this.remaning--;
3118
+ },
3119
+
3120
+ // 开始上传,可以被掉过。如果promise被reject了,则表示跳过此分片。
3121
+ _startSend: function( block ) {
3122
+ var me = this,
3123
+ file = block.file,
3124
+ promise;
3125
+
3126
+ me.pool.push( block );
3127
+ me.remaning++;
3128
+
3129
+ // 如果没有分片,则直接使用原始的。
3130
+ // 不会丢失content-type信息。
3131
+ block.blob = block.chunks === 1 ? file.source :
3132
+ file.source.slice( block.start, block.end );
3133
+
3134
+ // hook, 每个分片发送之前可能要做些异步的事情。
3135
+ promise = me.request( 'before-send', block, function() {
3136
+
3137
+ // 有可能文件已经上传出错了,所以不需要再传输了。
3138
+ if ( file.getStatus() === Status.PROGRESS ) {
3139
+ me._doSend( block );
3140
+ } else {
3141
+ me._popBlock( block );
3142
+ Base.nextTick( me.__tick );
3143
+ }
3144
+ });
3145
+
3146
+ // 如果为fail了,则跳过此分片。
3147
+ promise.fail(function() {
3148
+ if ( file.remaning === 1 ) {
3149
+ me._finishFile( file ).always(function() {
3150
+ block.percentage = 1;
3151
+ me._popBlock( block );
3152
+ me.owner.trigger( 'uploadComplete', file );
3153
+ Base.nextTick( me.__tick );
3154
+ });
3155
+ } else {
3156
+ block.percentage = 1;
3157
+ me._popBlock( block );
3158
+ Base.nextTick( me.__tick );
3159
+ }
3160
+ });
3161
+ },
3162
+
3163
+
3164
+ /**
3165
+ * @event uploadBeforeSend
3166
+ * @param {Object} object
3167
+ * @param {Object} data 默认的上传参数,可以扩展此对象来控制上传参数。
3168
+ * @description 当某个文件的分块在发送前触发,主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次。
3169
+ * @for Uploader
3170
+ */
3171
+
3172
+ /**
3173
+ * @event uploadAccept
3174
+ * @param {Object} object
3175
+ * @param {Object} ret 服务端的返回数据,json格式,如果服务端不是json格式,从ret._raw中取数据,自行解析。
3176
+ * @description 当某个文件上传到服务端响应后,会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。
3177
+ * @for Uploader
3178
+ */
3179
+
3180
+ /**
3181
+ * @event uploadProgress
3182
+ * @param {File} file File对象
3183
+ * @param {Number} percentage 上传进度
3184
+ * @description 上传过程中触发,携带上传进度。
3185
+ * @for Uploader
3186
+ */
3187
+
3188
+
3189
+ /**
3190
+ * @event uploadError
3191
+ * @param {File} file File对象
3192
+ * @param {String} reason 出错的code
3193
+ * @description 当文件上传出错时触发。
3194
+ * @for Uploader
3195
+ */
3196
+
3197
+ /**
3198
+ * @event uploadSuccess
3199
+ * @param {File} file File对象
3200
+ * @param {Object} response 服务端返回的数据
3201
+ * @description 当文件上传成功时触发。
3202
+ * @for Uploader
3203
+ */
3204
+
3205
+ /**
3206
+ * @event uploadComplete
3207
+ * @param {File} [file] File对象
3208
+ * @description 不管成功或者失败,文件上传完成时触发。
3209
+ * @for Uploader
3210
+ */
3211
+
3212
+ // 做上传操作。
3213
+ _doSend: function( block ) {
3214
+ var me = this,
3215
+ owner = me.owner,
3216
+ opts = me.options,
3217
+ file = block.file,
3218
+ tr = new Transport( opts ),
3219
+ data = $.extend({}, opts.formData ),
3220
+ headers = $.extend({}, opts.headers ),
3221
+ requestAccept, ret;
3222
+
3223
+ block.transport = tr;
3224
+
3225
+ tr.on( 'destroy', function() {
3226
+ delete block.transport;
3227
+ me._popBlock( block );
3228
+ Base.nextTick( me.__tick );
3229
+ });
3230
+
3231
+ // 广播上传进度。以文件为单位。
3232
+ tr.on( 'progress', function( percentage ) {
3233
+ var totalPercent = 0,
3234
+ uploaded = 0;
3235
+
3236
+ // 可能没有abort掉,progress还是执行进来了。
3237
+ // if ( !file.blocks ) {
3238
+ // return;
3239
+ // }
3240
+
3241
+ totalPercent = block.percentage = percentage;
3242
+
3243
+ if ( block.chunks > 1 ) { // 计算文件的整体速度。
3244
+ $.each( file.blocks, function( _, v ) {
3245
+ uploaded += (v.percentage || 0) * (v.end - v.start);
3246
+ });
3247
+
3248
+ totalPercent = uploaded / file.size;
3249
+ }
3250
+
3251
+ owner.trigger( 'uploadProgress', file, totalPercent || 0 );
3252
+ });
3253
+
3254
+ // 用来询问,是否返回的结果是有错误的。
3255
+ requestAccept = function( reject ) {
3256
+ var fn;
3257
+
3258
+ ret = tr.getResponseAsJson() || {};
3259
+ ret._raw = tr.getResponse();
3260
+ fn = function( value ) {
3261
+ reject = value;
3262
+ };
3263
+
3264
+ // 服务端响应了,不代表成功了,询问是否响应正确。
3265
+ if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {
3266
+ reject = reject || 'server';
3267
+ }
3268
+
3269
+ return reject;
3270
+ };
3271
+
3272
+ // 尝试重试,然后广播文件上传出错。
3273
+ tr.on( 'error', function( type, flag ) {
3274
+ block.retried = block.retried || 0;
3275
+
3276
+ // 自动重试
3277
+ if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&
3278
+ block.retried < opts.chunkRetry ) {
3279
+
3280
+ block.retried++;
3281
+ tr.send();
3282
+
3283
+ } else {
3284
+
3285
+ // http status 500 ~ 600
3286
+ if ( !flag && type === 'server' ) {
3287
+ type = requestAccept( type );
3288
+ }
3289
+
3290
+ file.setStatus( Status.ERROR, type );
3291
+ owner.trigger( 'uploadError', file, type );
3292
+ owner.trigger( 'uploadComplete', file );
3293
+ }
3294
+ });
3295
+
3296
+ // 上传成功
3297
+ tr.on( 'load', function() {
3298
+ var reason;
3299
+
3300
+ // 如果非预期,转向上传出错。
3301
+ if ( (reason = requestAccept()) ) {
3302
+ tr.trigger( 'error', reason, true );
3303
+ return;
3304
+ }
3305
+
3306
+ // 全部上传完成。
3307
+ if ( file.remaning === 1 ) {
3308
+ me._finishFile( file, ret );
3309
+ } else {
3310
+ tr.destroy();
3311
+ }
3312
+ });
3313
+
3314
+ // 配置默认的上传字段。
3315
+ data = $.extend( data, {
3316
+ id: file.id,
3317
+ name: file.name,
3318
+ type: file.type,
3319
+ lastModifiedDate: file.lastModifiedDate,
3320
+ size: file.size
3321
+ });
3322
+
3323
+ block.chunks > 1 && $.extend( data, {
3324
+ chunks: block.chunks,
3325
+ chunk: block.chunk
3326
+ });
3327
+
3328
+ // 在发送之间可以添加字段什么的。。。
3329
+ // 如果默认的字段不够使用,可以通过监听此事件来扩展
3330
+ owner.trigger( 'uploadBeforeSend', block, data, headers );
3331
+
3332
+ // 开始发送。
3333
+ tr.appendBlob( opts.fileVal, block.blob, file.name );
3334
+ tr.append( data );
3335
+ tr.setRequestHeader( headers );
3336
+ tr.send();
3337
+ },
3338
+
3339
+ // 完成上传。
3340
+ _finishFile: function( file, ret, hds ) {
3341
+ var owner = this.owner;
3342
+
3343
+ return owner
3344
+ .request( 'after-send-file', arguments, function() {
3345
+ file.setStatus( Status.COMPLETE );
3346
+ owner.trigger( 'uploadSuccess', file, ret, hds );
3347
+ })
3348
+ .fail(function( reason ) {
3349
+
3350
+ // 如果外部已经标记为invalid什么的,不再改状态。
3351
+ if ( file.getStatus() === Status.PROGRESS ) {
3352
+ file.setStatus( Status.ERROR, reason );
3353
+ }
3354
+
3355
+ owner.trigger( 'uploadError', file, reason );
3356
+ })
3357
+ .always(function() {
3358
+ owner.trigger( 'uploadComplete', file );
3359
+ });
3360
+ }
3361
+
3362
+ });
3363
+ });
3364
+ /**
3365
+ * @fileOverview 各种验证,包括文件总大小是否超出、单文件是否超出和文件是否重复。
3366
+ */
3367
+
3368
+ define('widgets/validator',[
3369
+ 'base',
3370
+ 'uploader',
3371
+ 'file',
3372
+ 'widgets/widget'
3373
+ ], function( Base, Uploader, WUFile ) {
3374
+
3375
+ var $ = Base.$,
3376
+ validators = {},
3377
+ api;
3378
+
3379
+ /**
3380
+ * @event error
3381
+ * @param {String} type 错误类型。
3382
+ * @description 当validate不通过时,会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误,目前有以下错误会在特定的情况下派送错来。
3383
+ *
3384
+ * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。
3385
+ * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。
3386
+ * @for Uploader
3387
+ */
3388
+
3389
+ // 暴露给外面的api
3390
+ api = {
3391
+
3392
+ // 添加验证器
3393
+ addValidator: function( type, cb ) {
3394
+ validators[ type ] = cb;
3395
+ },
3396
+
3397
+ // 移除验证器
3398
+ removeValidator: function( type ) {
3399
+ delete validators[ type ];
3400
+ }
3401
+ };
3402
+
3403
+ // 在Uploader初始化的时候启动Validators的初始化
3404
+ Uploader.register({
3405
+ init: function() {
3406
+ var me = this;
3407
+ $.each( validators, function() {
3408
+ this.call( me.owner );
3409
+ });
3410
+ }
3411
+ });
3412
+
3413
+ /**
3414
+ * @property {int} [fileNumLimit=undefined]
3415
+ * @namespace options
3416
+ * @for Uploader
3417
+ * @description 验证文件总数量, 超出则不允许加入队列。
3418
+ */
3419
+ api.addValidator( 'fileNumLimit', function() {
3420
+ var uploader = this,
3421
+ opts = uploader.options,
3422
+ count = 0,
3423
+ max = opts.fileNumLimit >> 0,
3424
+ flag = true;
3425
+
3426
+ if ( !max ) {
3427
+ return;
3428
+ }
3429
+
3430
+ uploader.on( 'beforeFileQueued', function( file ) {
3431
+
3432
+ if ( count >= max && flag ) {
3433
+ flag = false;
3434
+ this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );
3435
+ setTimeout(function() {
3436
+ flag = true;
3437
+ }, 1 );
3438
+ }
3439
+
3440
+ return count >= max ? false : true;
3441
+ });
3442
+
3443
+ uploader.on( 'fileQueued', function() {
3444
+ count++;
3445
+ });
3446
+
3447
+ uploader.on( 'fileDequeued', function() {
3448
+ count--;
3449
+ });
3450
+
3451
+ uploader.on( 'uploadFinished', function() {
3452
+ count = 0;
3453
+ });
3454
+ });
3455
+
3456
+
3457
+ /**
3458
+ * @property {int} [fileSizeLimit=undefined]
3459
+ * @namespace options
3460
+ * @for Uploader
3461
+ * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。
3462
+ */
3463
+ api.addValidator( 'fileSizeLimit', function() {
3464
+ var uploader = this,
3465
+ opts = uploader.options,
3466
+ count = 0,
3467
+ max = opts.fileSizeLimit >> 0,
3468
+ flag = true;
3469
+
3470
+ if ( !max ) {
3471
+ return;
3472
+ }
3473
+
3474
+ uploader.on( 'beforeFileQueued', function( file ) {
3475
+ var invalid = count + file.size > max;
3476
+
3477
+ if ( invalid && flag ) {
3478
+ flag = false;
3479
+ this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );
3480
+ setTimeout(function() {
3481
+ flag = true;
3482
+ }, 1 );
3483
+ }
3484
+
3485
+ return invalid ? false : true;
3486
+ });
3487
+
3488
+ uploader.on( 'fileQueued', function( file ) {
3489
+ count += file.size;
3490
+ });
3491
+
3492
+ uploader.on( 'fileDequeued', function( file ) {
3493
+ count -= file.size;
3494
+ });
3495
+
3496
+ uploader.on( 'uploadFinished', function() {
3497
+ count = 0;
3498
+ });
3499
+ });
3500
+
3501
+ /**
3502
+ * @property {int} [fileSingleSizeLimit=undefined]
3503
+ * @namespace options
3504
+ * @for Uploader
3505
+ * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。
3506
+ */
3507
+ api.addValidator( 'fileSingleSizeLimit', function() {
3508
+ var uploader = this,
3509
+ opts = uploader.options,
3510
+ max = opts.fileSingleSizeLimit;
3511
+
3512
+ if ( !max ) {
3513
+ return;
3514
+ }
3515
+
3516
+ uploader.on( 'beforeFileQueued', function( file ) {
3517
+
3518
+ if ( file.size > max ) {
3519
+ file.setStatus( WUFile.Status.INVALID, 'exceed_size' );
3520
+ this.trigger( 'error', 'F_EXCEED_SIZE', file );
3521
+ return false;
3522
+ }
3523
+
3524
+ });
3525
+
3526
+ });
3527
+
3528
+ /**
3529
+ * @property {int} [duplicate=undefined]
3530
+ * @namespace options
3531
+ * @for Uploader
3532
+ * @description 去重, 根据文件名字、文件大小和最后修改时间来生成hash Key.
3533
+ */
3534
+ api.addValidator( 'duplicate', function() {
3535
+ var uploader = this,
3536
+ opts = uploader.options,
3537
+ mapping = {};
3538
+
3539
+ if ( opts.duplicate ) {
3540
+ return;
3541
+ }
3542
+
3543
+ function hashString( str ) {
3544
+ var hash = 0,
3545
+ i = 0,
3546
+ len = str.length,
3547
+ _char;
3548
+
3549
+ for ( ; i < len; i++ ) {
3550
+ _char = str.charCodeAt( i );
3551
+ hash = _char + (hash << 6) + (hash << 16) - hash;
3552
+ }
3553
+
3554
+ return hash;
3555
+ }
3556
+
3557
+ uploader.on( 'beforeFileQueued', function( file ) {
3558
+ var hash = file.__hash || (file.__hash = hashString( file.name +
3559
+ file.size + file.lastModifiedDate ));
3560
+
3561
+ // 已经重复了
3562
+ if ( mapping[ hash ] ) {
3563
+ this.trigger( 'error', 'F_DUPLICATE', file );
3564
+ return false;
3565
+ }
3566
+ });
3567
+
3568
+ uploader.on( 'fileQueued', function( file ) {
3569
+ var hash = file.__hash;
3570
+
3571
+ hash && (mapping[ hash ] = true);
3572
+ });
3573
+
3574
+ uploader.on( 'fileDequeued', function( file ) {
3575
+ var hash = file.__hash;
3576
+
3577
+ hash && (delete mapping[ hash ]);
3578
+ });
3579
+ });
3580
+
3581
+ return api;
3582
+ });
3583
+
3584
+ /**
3585
+ * @fileOverview Runtime管理器,负责Runtime的选择, 连接
3586
+ */
3587
+ define('runtime/compbase',[],function() {
3588
+
3589
+ function CompBase( owner, runtime ) {
3590
+
3591
+ this.owner = owner;
3592
+ this.options = owner.options;
3593
+
3594
+ this.getRuntime = function() {
3595
+ return runtime;
3596
+ };
3597
+
3598
+ this.getRuid = function() {
3599
+ return runtime.uid;
3600
+ };
3601
+
3602
+ this.trigger = function() {
3603
+ return owner.trigger.apply( owner, arguments );
3604
+ };
3605
+ }
3606
+
3607
+ return CompBase;
3608
+ });
3609
+ /**
3610
+ * @fileOverview Html5Runtime
3611
+ */
3612
+ define('runtime/html5/runtime',[
3613
+ 'base',
3614
+ 'runtime/runtime',
3615
+ 'runtime/compbase'
3616
+ ], function( Base, Runtime, CompBase ) {
3617
+
3618
+ var type = 'html5',
3619
+ components = {};
3620
+
3621
+ function Html5Runtime() {
3622
+ var pool = {},
3623
+ me = this,
3624
+ destory = this.destory;
3625
+
3626
+ Runtime.apply( me, arguments );
3627
+ me.type = type;
3628
+
3629
+
3630
+ // 这个方法的调用者,实际上是RuntimeClient
3631
+ me.exec = function( comp, fn/*, args...*/) {
3632
+ var client = this,
3633
+ uid = client.uid,
3634
+ args = Base.slice( arguments, 2 ),
3635
+ instance;
3636
+
3637
+ if ( components[ comp ] ) {
3638
+ instance = pool[ uid ] = pool[ uid ] ||
3639
+ new components[ comp ]( client, me );
3640
+
3641
+ if ( instance[ fn ] ) {
3642
+ return instance[ fn ].apply( instance, args );
3643
+ }
3644
+ }
3645
+ };
3646
+
3647
+ me.destory = function() {
3648
+ // @todo 删除池子中的所有实例
3649
+ return destory && destory.apply( this, arguments );
3650
+ };
3651
+ }
3652
+
3653
+ Base.inherits( Runtime, {
3654
+ constructor: Html5Runtime,
3655
+
3656
+ // 不需要连接其他程序,直接执行callback
3657
+ init: function() {
3658
+ var me = this;
3659
+ setTimeout(function() {
3660
+ me.trigger('ready');
3661
+ }, 1 );
3662
+ }
3663
+
3664
+ });
3665
+
3666
+ // 注册Components
3667
+ Html5Runtime.register = function( name, component ) {
3668
+ var klass = components[ name ] = Base.inherits( CompBase, component );
3669
+ return klass;
3670
+ };
3671
+
3672
+ // 注册html5运行时。
3673
+ // 只有在支持的前提下注册。
3674
+ if ( window.Blob && window.FileReader && window.DataView ) {
3675
+ Runtime.addRuntime( type, Html5Runtime );
3676
+ }
3677
+
3678
+ return Html5Runtime;
3679
+ });
3680
+ /**
3681
+ * @fileOverview Blob Html实现
3682
+ */
3683
+ define('runtime/html5/blob',[
3684
+ 'runtime/html5/runtime',
3685
+ 'lib/blob'
3686
+ ], function( Html5Runtime, Blob ) {
3687
+
3688
+ return Html5Runtime.register( 'Blob', {
3689
+ slice: function( start, end ) {
3690
+ var blob = this.owner.source,
3691
+ slice = blob.slice || blob.webkitSlice || blob.mozSlice;
3692
+
3693
+ blob = slice.call( blob, start, end );
3694
+
3695
+ return new Blob( this.getRuid(), blob );
3696
+ }
3697
+ });
3698
+ });
3699
+ /**
3700
+ * @fileOverview FilePaste
3701
+ */
3702
+ define('runtime/html5/dnd',[
3703
+ 'base',
3704
+ 'runtime/html5/runtime',
3705
+ 'lib/file'
3706
+ ], function( Base, Html5Runtime, File ) {
3707
+
3708
+ var $ = Base.$,
3709
+ prefix = 'webuploader-dnd-';
3710
+
3711
+ return Html5Runtime.register( 'DragAndDrop', {
3712
+ init: function() {
3713
+ var elem = this.elem = this.options.container;
3714
+
3715
+ this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );
3716
+ this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );
3717
+ this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );
3718
+ this.dropHandler = Base.bindFn( this._dropHandler, this );
3719
+ this.dndOver = false;
3720
+
3721
+ elem.on( 'dragenter', this.dragEnterHandler );
3722
+ elem.on( 'dragover', this.dragOverHandler );
3723
+ elem.on( 'dragleave', this.dragLeaveHandler );
3724
+ elem.on( 'drop', this.dropHandler );
3725
+
3726
+ if ( this.options.disableGlobalDnd ) {
3727
+ $( document ).on( 'dragover', this.dragOverHandler );
3728
+ $( document ).on( 'drop', this.dropHandler );
3729
+ }
3730
+ },
3731
+
3732
+ _dragEnterHandler: function( e ) {
3733
+ var me = this,
3734
+ denied = me._denied || false,
3735
+ items;
3736
+
3737
+ e = e.originalEvent || e;
3738
+
3739
+ if ( !me.dndOver ) {
3740
+ me.dndOver = true;
3741
+
3742
+ // 注意只有 chrome 支持。
3743
+ items = e.dataTransfer.items;
3744
+
3745
+ if ( items && items.length ) {
3746
+ me._denied = denied = !me.trigger( 'accept', items );
3747
+ }
3748
+
3749
+ me.elem.addClass( prefix + 'over' );
3750
+ me.elem[ denied ? 'addClass' :
3751
+ 'removeClass' ]( prefix + 'denied' );
3752
+ }
3753
+
3754
+
3755
+ e.dataTransfer.dropEffect = denied ? 'none' : 'copy';
3756
+
3757
+ return false;
3758
+ },
3759
+
3760
+ _dragOverHandler: function( e ) {
3761
+ // 只处理框内的。
3762
+ var parentElem = this.elem.parent().get( 0 );
3763
+ if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {
3764
+ return false;
3765
+ }
3766
+
3767
+ clearTimeout( this._leaveTimer );
3768
+ this._dragEnterHandler.call( this, e );
3769
+
3770
+ return false;
3771
+ },
3772
+
3773
+ _dragLeaveHandler: function() {
3774
+ var me = this,
3775
+ handler;
3776
+
3777
+ handler = function() {
3778
+ me.dndOver = false;
3779
+ me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );
3780
+ };
3781
+
3782
+ clearTimeout( me._leaveTimer );
3783
+ me._leaveTimer = setTimeout( handler, 100 );
3784
+ return false;
3785
+ },
3786
+
3787
+ _dropHandler: function( e ) {
3788
+ var me = this,
3789
+ ruid = me.getRuid(),
3790
+ parentElem = me.elem.parent().get( 0 );
3791
+
3792
+ // 只处理框内的。
3793
+ if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {
3794
+ return false;
3795
+ }
3796
+
3797
+ me._getTansferFiles( e, function( results ) {
3798
+ me.trigger( 'drop', $.map( results, function( file ) {
3799
+ return new File( ruid, file );
3800
+ }) );
3801
+ });
3802
+
3803
+ me.dndOver = false;
3804
+ me.elem.removeClass( prefix + 'over' );
3805
+ return false;
3806
+ },
3807
+
3808
+ // 如果传入 callback 则去查看文件夹,否则只管当前文件夹。
3809
+ _getTansferFiles: function( e, callback ) {
3810
+ var results = [],
3811
+ promises = [],
3812
+ items, files, dataTransfer, file, item, i, len, canAccessFolder;
3813
+
3814
+ e = e.originalEvent || e;
3815
+
3816
+ dataTransfer = e.dataTransfer;
3817
+ items = dataTransfer.items;
3818
+ files = dataTransfer.files;
3819
+
3820
+ canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);
3821
+
3822
+ for ( i = 0, len = files.length; i < len; i++ ) {
3823
+ file = files[ i ];
3824
+ item = items && items[ i ];
3825
+
3826
+ if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {
3827
+
3828
+ promises.push( this._traverseDirectoryTree(
3829
+ item.webkitGetAsEntry(), results ) );
3830
+ } else {
3831
+ results.push( file );
3832
+ }
3833
+ }
3834
+
3835
+ Base.when.apply( Base, promises ).done(function() {
3836
+
3837
+ if ( !results.length ) {
3838
+ return;
3839
+ }
3840
+
3841
+ callback( results );
3842
+ });
3843
+ },
3844
+
3845
+ _traverseDirectoryTree: function( entry, results ) {
3846
+ var deferred = Base.Deferred(),
3847
+ me = this;
3848
+
3849
+ if ( entry.isFile ) {
3850
+ entry.file(function( file ) {
3851
+ results.push( file );
3852
+ deferred.resolve();
3853
+ });
3854
+ } else if ( entry.isDirectory ) {
3855
+ entry.createReader().readEntries(function( entries ) {
3856
+ var len = entries.length,
3857
+ promises = [],
3858
+ arr = [], // 为了保证顺序。
3859
+ i;
3860
+
3861
+ for ( i = 0; i < len; i++ ) {
3862
+ promises.push( me._traverseDirectoryTree(
3863
+ entries[ i ], arr ) );
3864
+ }
3865
+
3866
+ Base.when.apply( Base, promises ).then(function() {
3867
+ results.push.apply( results, arr );
3868
+ deferred.resolve();
3869
+ }, deferred.reject );
3870
+ });
3871
+ }
3872
+
3873
+ return deferred.promise();
3874
+ },
3875
+
3876
+ destroy: function() {
3877
+ var elem = this.elem;
3878
+
3879
+ elem.off( 'dragenter', this.dragEnterHandler );
3880
+ elem.off( 'dragover', this.dragEnterHandler );
3881
+ elem.off( 'dragleave', this.dragLeaveHandler );
3882
+ elem.off( 'drop', this.dropHandler );
3883
+
3884
+ if ( this.options.disableGlobalDnd ) {
3885
+ $( document ).off( 'dragover', this.dragOverHandler );
3886
+ $( document ).off( 'drop', this.dropHandler );
3887
+ }
3888
+ }
3889
+ });
3890
+ });
3891
+
3892
+ /**
3893
+ * @fileOverview FilePaste
3894
+ */
3895
+ define('runtime/html5/filepaste',[
3896
+ 'base',
3897
+ 'runtime/html5/runtime',
3898
+ 'lib/file'
3899
+ ], function( Base, Html5Runtime, File ) {
3900
+
3901
+ return Html5Runtime.register( 'FilePaste', {
3902
+ init: function() {
3903
+ var opts = this.options,
3904
+ elem = this.elem = opts.container,
3905
+ accept = '.*',
3906
+ arr, i, len, item;
3907
+
3908
+ // accetp的mimeTypes中生成匹配正则。
3909
+ if ( opts.accept ) {
3910
+ arr = [];
3911
+
3912
+ for ( i = 0, len = opts.accept.length; i < len; i++ ) {
3913
+ item = opts.accept[ i ].mimeTypes;
3914
+ item && arr.push( item );
3915
+ }
3916
+
3917
+ if ( arr.length ) {
3918
+ accept = arr.join(',');
3919
+ accept = accept.replace( /,/g, '|' ).replace( /\*/g, '.*' );
3920
+ }
3921
+ }
3922
+ this.accept = accept = new RegExp( accept, 'i' );
3923
+ this.hander = Base.bindFn( this._pasteHander, this );
3924
+ elem.on( 'paste', this.hander );
3925
+ },
3926
+
3927
+ _pasteHander: function( e ) {
3928
+ var allowed = [],
3929
+ ruid = this.getRuid(),
3930
+ items, item, blob, i, len;
3931
+
3932
+ e = e.originalEvent || e;
3933
+ items = e.clipboardData.items;
3934
+
3935
+ for ( i = 0, len = items.length; i < len; i++ ) {
3936
+ item = items[ i ];
3937
+
3938
+ if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {
3939
+ continue;
3940
+ }
3941
+
3942
+ allowed.push( new File( ruid, blob ) );
3943
+ }
3944
+
3945
+ if ( allowed.length ) {
3946
+ // 不阻止非文件粘贴(文字粘贴)的事件冒泡
3947
+ e.preventDefault();
3948
+ e.stopPropagation();
3949
+ this.trigger( 'paste', allowed );
3950
+ }
3951
+ },
3952
+
3953
+ destroy: function() {
3954
+ this.elem.off( 'paste', this.hander );
3955
+ }
3956
+ });
3957
+ });
3958
+
3959
+ /**
3960
+ * @fileOverview FilePicker
3961
+ */
3962
+ define('runtime/html5/filepicker',[
3963
+ 'base',
3964
+ 'runtime/html5/runtime'
3965
+ ], function( Base, Html5Runtime ) {
3966
+
3967
+ var $ = Base.$;
3968
+
3969
+ return Html5Runtime.register( 'FilePicker', {
3970
+ init: function() {
3971
+ var container = this.getRuntime().getContainer(),
3972
+ me = this,
3973
+ owner = me.owner,
3974
+ opts = me.options,
3975
+ lable = $( document.createElement('label') ),
3976
+ input = $( document.createElement('input') ),
3977
+ arr, i, len, mouseHandler;
3978
+
3979
+ input.attr( 'type', 'file' );
3980
+ input.attr( 'name', opts.name );
3981
+ input.addClass('webuploader-element-invisible');
3982
+
3983
+ lable.on( 'click', function() {
3984
+ input.trigger('click');
3985
+ });
3986
+
3987
+ lable.css({
3988
+ opacity: 0,
3989
+ width: '100%',
3990
+ height: '100%',
3991
+ display: 'block',
3992
+ cursor: 'pointer',
3993
+ background: '#ffffff'
3994
+ });
3995
+
3996
+ if ( opts.multiple ) {
3997
+ input.attr( 'multiple', 'multiple' );
3998
+ }
3999
+
4000
+ // @todo Firefox不支持单独指定后缀
4001
+ if ( opts.accept && opts.accept.length > 0 ) {
4002
+ arr = [];
4003
+
4004
+ for ( i = 0, len = opts.accept.length; i < len; i++ ) {
4005
+ arr.push( opts.accept[ i ].mimeTypes );
4006
+ }
4007
+
4008
+ input.attr( 'accept', arr.join(',') );
4009
+ }
4010
+
4011
+ container.append( input );
4012
+ container.append( lable );
4013
+
4014
+ mouseHandler = function( e ) {
4015
+ owner.trigger( e.type );
4016
+ };
4017
+
4018
+ input.on( 'change', function( e ) {
4019
+ var fn = arguments.callee,
4020
+ clone;
4021
+
4022
+ me.files = e.target.files;
4023
+
4024
+ // reset input
4025
+ clone = this.cloneNode( true );
4026
+ this.parentNode.replaceChild( clone, this );
4027
+
4028
+ input.off();
4029
+ input = $( clone ).on( 'change', fn )
4030
+ .on( 'mouseenter mouseleave', mouseHandler );
4031
+
4032
+ owner.trigger('change');
4033
+ });
4034
+
4035
+ lable.on( 'mouseenter mouseleave', mouseHandler );
4036
+
4037
+ },
4038
+
4039
+
4040
+ getFiles: function() {
4041
+ return this.files;
4042
+ },
4043
+
4044
+ destroy: function() {
4045
+ // todo
4046
+ }
4047
+ });
4048
+ });
4049
+ /**
4050
+ * @fileOverview Transport
4051
+ * @todo 支持chunked传输,优势:
4052
+ * 可以将大文件分成小块,挨个传输,可以提高大文件成功率,当失败的时候,也只需要重传那小部分,
4053
+ * 而不需要重头再传一次。另外断点续传也需要用chunked方式。
4054
+ */
4055
+ define('runtime/html5/transport',[
4056
+ 'base',
4057
+ 'runtime/html5/runtime'
4058
+ ], function( Base, Html5Runtime ) {
4059
+
4060
+ var noop = Base.noop,
4061
+ $ = Base.$;
4062
+
4063
+ return Html5Runtime.register( 'Transport', {
4064
+ init: function() {
4065
+ this._status = 0;
4066
+ this._response = null;
4067
+ },
4068
+
4069
+ send: function() {
4070
+ var owner = this.owner,
4071
+ opts = this.options,
4072
+ xhr = this._initAjax(),
4073
+ blob = owner._blob,
4074
+ server = opts.server,
4075
+ formData, binary, fr;
4076
+
4077
+ if ( opts.sendAsBinary ) {
4078
+ server += (/\?/.test( server ) ? '&' : '?') +
4079
+ $.param( owner._formData );
4080
+
4081
+ binary = blob.getSource();
4082
+ } else {
4083
+ formData = new FormData();
4084
+ $.each( owner._formData, function( k, v ) {
4085
+ formData.append( k, v );
4086
+ });
4087
+
4088
+ formData.append( opts.fileVal, blob.getSource(),
4089
+ opts.filename || owner._formData.name || '' );
4090
+ }
4091
+
4092
+ if ( opts.withCredentials && 'withCredentials' in xhr ) {
4093
+ xhr.open( opts.method, server, true );
4094
+ xhr.withCredentials = true;
4095
+ } else {
4096
+ xhr.open( opts.method, server );
4097
+ }
4098
+
4099
+ this._setRequestHeader( xhr, opts.headers );
4100
+
4101
+ if ( binary ) {
4102
+ xhr.overrideMimeType('application/octet-stream');
4103
+
4104
+ // android直接发送blob会导致服务端接收到的是空文件。
4105
+ // bug详情。
4106
+ // https://code.google.com/p/android/issues/detail?id=39882
4107
+ // 所以先用fileReader读取出来再通过arraybuffer的方式发送。
4108
+ if ( Base.os.android ) {
4109
+ fr = new FileReader();
4110
+
4111
+ fr.onload = function() {
4112
+ xhr.send( this.result );
4113
+ fr = fr.onload = null;
4114
+ };
4115
+
4116
+ fr.readAsArrayBuffer( binary );
4117
+ } else {
4118
+ xhr.send( binary );
4119
+ }
4120
+ } else {
4121
+ xhr.send( formData );
4122
+ }
4123
+ },
4124
+
4125
+ getResponse: function() {
4126
+ return this._response;
4127
+ },
4128
+
4129
+ getResponseAsJson: function() {
4130
+ return this._parseJson( this._response );
4131
+ },
4132
+
4133
+ getStatus: function() {
4134
+ return this._status;
4135
+ },
4136
+
4137
+ abort: function() {
4138
+ var xhr = this._xhr;
4139
+
4140
+ if ( xhr ) {
4141
+ xhr.upload.onprogress = noop;
4142
+ xhr.onreadystatechange = noop;
4143
+ xhr.abort();
4144
+
4145
+ this._xhr = xhr = null;
4146
+ }
4147
+ },
4148
+
4149
+ destroy: function() {
4150
+ this.abort();
4151
+ },
4152
+
4153
+ _initAjax: function() {
4154
+ var me = this,
4155
+ xhr = new XMLHttpRequest(),
4156
+ opts = this.options;
4157
+
4158
+ if ( opts.withCredentials && !('withCredentials' in xhr) &&
4159
+ typeof XDomainRequest !== 'undefined' ) {
4160
+ xhr = new XDomainRequest();
4161
+ }
4162
+
4163
+ xhr.upload.onprogress = function( e ) {
4164
+ var percentage = 0;
4165
+
4166
+ if ( e.lengthComputable ) {
4167
+ percentage = e.loaded / e.total;
4168
+ }
4169
+
4170
+ return me.trigger( 'progress', percentage );
4171
+ };
4172
+
4173
+ xhr.onreadystatechange = function() {
4174
+
4175
+ if ( xhr.readyState !== 4 ) {
4176
+ return;
4177
+ }
4178
+
4179
+ xhr.upload.onprogress = noop;
4180
+ xhr.onreadystatechange = noop;
4181
+ me._xhr = null;
4182
+ me._status = xhr.status;
4183
+
4184
+ if ( xhr.status >= 200 && xhr.status < 300 ) {
4185
+ me._response = xhr.responseText;
4186
+ return me.trigger('load');
4187
+ } else if ( xhr.status >= 500 && xhr.status < 600 ) {
4188
+ me._response = xhr.responseText;
4189
+ return me.trigger( 'error', 'server' );
4190
+ }
4191
+
4192
+
4193
+ return me.trigger( 'error', me._status ? 'http' : 'abort' );
4194
+ };
4195
+
4196
+ me._xhr = xhr;
4197
+ return xhr;
4198
+ },
4199
+
4200
+ _setRequestHeader: function( xhr, headers ) {
4201
+ $.each( headers, function( key, val ) {
4202
+ xhr.setRequestHeader( key, val );
4203
+ });
4204
+ },
4205
+
4206
+ _parseJson: function( str ) {
4207
+ var json;
4208
+
4209
+ try {
4210
+ json = JSON.parse( str );
4211
+ } catch ( ex ) {
4212
+ json = {};
4213
+ }
4214
+
4215
+ return json;
4216
+ }
4217
+ });
4218
+ });
4219
+ /**
4220
+ * @fileOverview FlashRuntime
4221
+ */
4222
+ define('runtime/flash/runtime',[
4223
+ 'base',
4224
+ 'runtime/runtime',
4225
+ 'runtime/compbase'
4226
+ ], function( Base, Runtime, CompBase ) {
4227
+
4228
+ var $ = Base.$,
4229
+ type = 'flash',
4230
+ components = {};
4231
+
4232
+
4233
+ function getFlashVersion() {
4234
+ var version;
4235
+
4236
+ try {
4237
+ version = navigator.plugins[ 'Shockwave Flash' ];
4238
+ version = version.description;
4239
+ } catch ( ex ) {
4240
+ try {
4241
+ version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')
4242
+ .GetVariable('$version');
4243
+ } catch ( ex2 ) {
4244
+ version = '0.0';
4245
+ }
4246
+ }
4247
+ version = version.match( /\d+/g );
4248
+ return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );
4249
+ }
4250
+
4251
+ function FlashRuntime() {
4252
+ var pool = {},
4253
+ clients = {},
4254
+ destory = this.destory,
4255
+ me = this,
4256
+ jsreciver = Base.guid('webuploader_');
4257
+
4258
+ Runtime.apply( me, arguments );
4259
+ me.type = type;
4260
+
4261
+
4262
+ // 这个方法的调用者,实际上是RuntimeClient
4263
+ me.exec = function( comp, fn/*, args...*/ ) {
4264
+ var client = this,
4265
+ uid = client.uid,
4266
+ args = Base.slice( arguments, 2 ),
4267
+ instance;
4268
+
4269
+ clients[ uid ] = client;
4270
+
4271
+ if ( components[ comp ] ) {
4272
+ if ( !pool[ uid ] ) {
4273
+ pool[ uid ] = new components[ comp ]( client, me );
4274
+ }
4275
+
4276
+ instance = pool[ uid ];
4277
+
4278
+ if ( instance[ fn ] ) {
4279
+ return instance[ fn ].apply( instance, args );
4280
+ }
4281
+ }
4282
+
4283
+ return me.flashExec.apply( client, arguments );
4284
+ };
4285
+
4286
+ function handler( evt, obj ) {
4287
+ var type = evt.type || evt,
4288
+ parts, uid;
4289
+
4290
+ parts = type.split('::');
4291
+ uid = parts[ 0 ];
4292
+ type = parts[ 1 ];
4293
+
4294
+ // console.log.apply( console, arguments );
4295
+
4296
+ if ( type === 'Ready' && uid === me.uid ) {
4297
+ me.trigger('ready');
4298
+ } else if ( clients[ uid ] ) {
4299
+ clients[ uid ].trigger( type.toLowerCase(), evt, obj );
4300
+ }
4301
+
4302
+ // Base.log( evt, obj );
4303
+ }
4304
+
4305
+ // flash的接受器。
4306
+ window[ jsreciver ] = function() {
4307
+ var args = arguments;
4308
+
4309
+ // 为了能捕获得到。
4310
+ setTimeout(function() {
4311
+ handler.apply( null, args );
4312
+ }, 1 );
4313
+ };
4314
+
4315
+ this.jsreciver = jsreciver;
4316
+
4317
+ this.destory = function() {
4318
+ // @todo 删除池子中的所有实例
4319
+ return destory && destory.apply( this, arguments );
4320
+ };
4321
+
4322
+ this.flashExec = function( comp, fn ) {
4323
+ var flash = me.getFlash(),
4324
+ args = Base.slice( arguments, 2 );
4325
+
4326
+ return flash.exec( this.uid, comp, fn, args );
4327
+ };
4328
+
4329
+ // @todo
4330
+ }
4331
+
4332
+ Base.inherits( Runtime, {
4333
+ constructor: FlashRuntime,
4334
+
4335
+ init: function() {
4336
+ var container = this.getContainer(),
4337
+ opts = this.options,
4338
+ html;
4339
+
4340
+ // if not the minimal height, shims are not initialized
4341
+ // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)
4342
+ container.css({
4343
+ position: 'absolute',
4344
+ top: '-8px',
4345
+ left: '-8px',
4346
+ width: '9px',
4347
+ height: '9px',
4348
+ overflow: 'hidden'
4349
+ });
4350
+
4351
+ // insert flash object
4352
+ html = '<object id="' + this.uid + '" type="application/' +
4353
+ 'x-shockwave-flash" data="' + opts.swf + '" ';
4354
+
4355
+ if ( Base.browser.ie ) {
4356
+ html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
4357
+ }
4358
+
4359
+ html += 'width="100%" height="100%" style="outline:0">' +
4360
+ '<param name="movie" value="' + opts.swf + '" />' +
4361
+ '<param name="flashvars" value="uid=' + this.uid +
4362
+ '&jsreciver=' + this.jsreciver + '" />' +
4363
+ '<param name="wmode" value="transparent" />' +
4364
+ '<param name="allowscriptaccess" value="always" />' +
4365
+ '</object>';
4366
+
4367
+ container.html( html );
4368
+ },
4369
+
4370
+ getFlash: function() {
4371
+ if ( this._flash ) {
4372
+ return this._flash;
4373
+ }
4374
+
4375
+ this._flash = $( '#' + this.uid ).get( 0 );
4376
+ return this._flash;
4377
+ }
4378
+
4379
+ });
4380
+
4381
+ FlashRuntime.register = function( name, component ) {
4382
+ component = components[ name ] = Base.inherits( CompBase, $.extend({
4383
+
4384
+ // @todo fix this later
4385
+ flashExec: function() {
4386
+ var owner = this.owner,
4387
+ runtime = this.getRuntime();
4388
+
4389
+ return runtime.flashExec.apply( owner, arguments );
4390
+ }
4391
+ }, component ) );
4392
+
4393
+ return component;
4394
+ };
4395
+
4396
+ if ( getFlashVersion() >= 11.4 ) {
4397
+ Runtime.addRuntime( type, FlashRuntime );
4398
+ }
4399
+
4400
+ return FlashRuntime;
4401
+ });
4402
+ /**
4403
+ * @fileOverview FilePicker
4404
+ */
4405
+ define('runtime/flash/filepicker',[
4406
+ 'base',
4407
+ 'runtime/flash/runtime'
4408
+ ], function( Base, FlashRuntime ) {
4409
+ var $ = Base.$;
4410
+
4411
+ return FlashRuntime.register( 'FilePicker', {
4412
+ init: function( opts ) {
4413
+ var copy = $.extend({}, opts ),
4414
+ len, i;
4415
+
4416
+ // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.
4417
+ len = copy.accept && copy.accept.length;
4418
+ for ( i = 0; i < len; i++ ) {
4419
+ if ( !copy.accept[ i ].title ) {
4420
+ copy.accept[ i ].title = 'Files';
4421
+ }
4422
+ }
4423
+
4424
+ delete copy.button;
4425
+ delete copy.container;
4426
+
4427
+ this.flashExec( 'FilePicker', 'init', copy );
4428
+ },
4429
+
4430
+ destroy: function() {
4431
+ // todo
4432
+ }
4433
+ });
4434
+ });
4435
+ /**
4436
+ * @fileOverview Transport flash实现
4437
+ */
4438
+ define('runtime/flash/transport',[
4439
+ 'base',
4440
+ 'runtime/flash/runtime',
4441
+ 'runtime/client'
4442
+ ], function( Base, FlashRuntime, RuntimeClient ) {
4443
+ var $ = Base.$;
4444
+
4445
+ return FlashRuntime.register( 'Transport', {
4446
+ init: function() {
4447
+ this._status = 0;
4448
+ this._response = null;
4449
+ this._responseJson = null;
4450
+ },
4451
+
4452
+ send: function() {
4453
+ var owner = this.owner,
4454
+ opts = this.options,
4455
+ xhr = this._initAjax(),
4456
+ blob = owner._blob,
4457
+ server = opts.server,
4458
+ binary;
4459
+
4460
+ xhr.connectRuntime( blob.ruid );
4461
+
4462
+ if ( opts.sendAsBinary ) {
4463
+ server += (/\?/.test( server ) ? '&' : '?') +
4464
+ $.param( owner._formData );
4465
+
4466
+ binary = blob.uid;
4467
+ } else {
4468
+ $.each( owner._formData, function( k, v ) {
4469
+ xhr.exec( 'append', k, v );
4470
+ });
4471
+
4472
+ xhr.exec( 'appendBlob', opts.fileVal, blob.uid,
4473
+ opts.filename || owner._formData.name || '' );
4474
+ }
4475
+
4476
+ this._setRequestHeader( xhr, opts.headers );
4477
+ xhr.exec( 'send', {
4478
+ method: opts.method,
4479
+ url: server
4480
+ }, binary );
4481
+ },
4482
+
4483
+ getStatus: function() {
4484
+ return this._status;
4485
+ },
4486
+
4487
+ getResponse: function() {
4488
+ return this._response;
4489
+ },
4490
+
4491
+ getResponseAsJson: function() {
4492
+ return this._responseJson;
4493
+ },
4494
+
4495
+ abort: function() {
4496
+ var xhr = this._xhr;
4497
+
4498
+ if ( xhr ) {
4499
+ xhr.exec('abort');
4500
+ xhr.destroy();
4501
+ this._xhr = xhr = null;
4502
+ }
4503
+ },
4504
+
4505
+ destroy: function() {
4506
+ this.abort();
4507
+ },
4508
+
4509
+ _initAjax: function() {
4510
+ var me = this,
4511
+ xhr = new RuntimeClient('XMLHttpRequest');
4512
+
4513
+ xhr.on( 'uploadprogress progress', function( e ) {
4514
+ return me.trigger( 'progress', e.loaded / e.total );
4515
+ });
4516
+
4517
+ xhr.on( 'load', function() {
4518
+ var status = xhr.exec('getStatus'),
4519
+ err = '';
4520
+
4521
+ xhr.off();
4522
+ me._xhr = null;
4523
+
4524
+ if ( status >= 200 && status < 300 ) {
4525
+ me._response = xhr.exec('getResponse');
4526
+ me._responseJson = xhr.exec('getResponseAsJson');
4527
+ } else if ( status >= 500 && status < 600 ) {
4528
+ me._response = xhr.exec('getResponse');
4529
+ me._responseJson = xhr.exec('getResponseAsJson');
4530
+ err = 'server';
4531
+ } else {
4532
+ err = 'http';
4533
+ }
4534
+
4535
+ xhr.destroy();
4536
+ xhr = null;
4537
+
4538
+ return err ? me.trigger( 'error', err ) : me.trigger('load');
4539
+ });
4540
+
4541
+ xhr.on( 'error', function() {
4542
+ xhr.off();
4543
+ me._xhr = null;
4544
+ me.trigger( 'error', 'http' );
4545
+ });
4546
+
4547
+ me._xhr = xhr;
4548
+ return xhr;
4549
+ },
4550
+
4551
+ _setRequestHeader: function( xhr, headers ) {
4552
+ $.each( headers, function( key, val ) {
4553
+ xhr.exec( 'setRequestHeader', key, val );
4554
+ });
4555
+ }
4556
+ });
4557
+ });
4558
+ /**
4559
+ * @fileOverview 没有图像处理的版本。
4560
+ */
4561
+ define('preset/withoutimage',[
4562
+ 'base',
4563
+
4564
+ // widgets
4565
+ 'widgets/filednd',
4566
+ 'widgets/filepaste',
4567
+ 'widgets/filepicker',
4568
+ 'widgets/queue',
4569
+ 'widgets/runtime',
4570
+ 'widgets/upload',
4571
+ 'widgets/validator',
4572
+
4573
+ // runtimes
4574
+ // html5
4575
+ 'runtime/html5/blob',
4576
+ 'runtime/html5/dnd',
4577
+ 'runtime/html5/filepaste',
4578
+ 'runtime/html5/filepicker',
4579
+ 'runtime/html5/transport',
4580
+
4581
+ // flash
4582
+ 'runtime/flash/filepicker',
4583
+ 'runtime/flash/transport'
4584
+ ], function( Base ) {
4585
+ return Base;
4586
+ });
4587
+ define('webuploader',[
4588
+ 'preset/withoutimage'
4589
+ ], function( preset ) {
4590
+ return preset;
4591
+ });
4592
+ return require('webuploader');
4593
+ });