baidu_ueditor_rails5 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/baidu_ueditor.js +1 -1
- data/app/assets/javascripts/ueditor/dialogs/anchor/anchor.html +40 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/attachment.css +681 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/attachment.html +60 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/attachment.js +754 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_chm.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_default.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_doc.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_exe.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_jpg.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_mp3.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_mv.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_pdf.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_ppt.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_psd.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_rar.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_txt.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/fileTypeImages/icon_xls.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/alignicon.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/alignicon.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/bg.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/file-icons.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/file-icons.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/icons.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/icons.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/image.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/progress.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/success.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/attachment/images/success.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/background/background.css +94 -0
- data/app/assets/javascripts/ueditor/dialogs/background/background.html +56 -0
- data/app/assets/javascripts/ueditor/dialogs/background/background.js +376 -0
- data/app/assets/javascripts/ueditor/dialogs/background/images/bg.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/background/images/success.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/chart.config.js +65 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/charts.css +165 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/charts.html +89 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/charts.js +519 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/images/charts0.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/images/charts1.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/images/charts2.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/images/charts3.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/images/charts4.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/charts/images/charts5.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/emotion.css +43 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/emotion.html +54 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/emotion.js +186 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/0.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/bface.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/cface.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/fface.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/jxface2.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/neweditor-tab-bg.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/tface.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/wface.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/emotion/images/yface.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/gmap/gmap.html +89 -0
- data/app/assets/javascripts/ueditor/dialogs/help/help.css +7 -0
- data/app/assets/javascripts/ueditor/dialogs/help/help.html +82 -0
- data/app/assets/javascripts/ueditor/dialogs/help/help.js +56 -0
- data/app/assets/javascripts/ueditor/dialogs/image/image.css +894 -0
- data/app/assets/javascripts/ueditor/dialogs/image/image.html +120 -0
- data/app/assets/javascripts/ueditor/dialogs/image/image.js +1142 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/alignicon.jpg +0 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/bg.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/icons.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/icons.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/image.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/progress.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/success.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/image/images/success.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/insertframe/insertframe.html +98 -0
- data/app/assets/javascripts/ueditor/dialogs/internal.js +81 -0
- data/app/assets/javascripts/ueditor/dialogs/link/link.html +126 -0
- data/app/assets/javascripts/ueditor/dialogs/map/map.html +135 -0
- data/app/assets/javascripts/ueditor/dialogs/map/show.html +118 -0
- data/app/assets/javascripts/ueditor/dialogs/music/music.css +30 -0
- data/app/assets/javascripts/ueditor/dialogs/music/music.html +32 -0
- data/app/assets/javascripts/ueditor/dialogs/music/music.js +192 -0
- data/app/assets/javascripts/ueditor/dialogs/preview/preview.html +40 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/addimg.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/brush.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/delimg.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/delimgH.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/empty.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/emptyH.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/eraser.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/redo.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/redoH.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/scale.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/scaleH.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/size.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/undo.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/images/undoH.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/scrawl.css +72 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/scrawl.html +95 -0
- data/app/assets/javascripts/ueditor/dialogs/scrawl/scrawl.js +671 -0
- data/app/assets/javascripts/ueditor/dialogs/searchreplace/searchreplace.html +102 -0
- data/app/assets/javascripts/ueditor/dialogs/searchreplace/searchreplace.js +164 -0
- data/app/assets/javascripts/ueditor/dialogs/snapscreen/snapscreen.html +58 -0
- data/app/assets/javascripts/ueditor/dialogs/spechars/spechars.html +21 -0
- data/app/assets/javascripts/ueditor/dialogs/spechars/spechars.js +57 -0
- data/app/assets/javascripts/ueditor/dialogs/table/dragicon.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/table/edittable.css +84 -0
- data/app/assets/javascripts/ueditor/dialogs/table/edittable.html +64 -0
- data/app/assets/javascripts/ueditor/dialogs/table/edittable.js +237 -0
- data/app/assets/javascripts/ueditor/dialogs/table/edittd.html +61 -0
- data/app/assets/javascripts/ueditor/dialogs/table/edittip.html +33 -0
- data/app/assets/javascripts/ueditor/dialogs/template/config.js +42 -0
- data/app/assets/javascripts/ueditor/dialogs/template/images/bg.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/template/images/pre0.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/template/images/pre1.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/template/images/pre2.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/template/images/pre3.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/template/images/pre4.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/template/template.css +18 -0
- data/app/assets/javascripts/ueditor/dialogs/template/template.html +26 -0
- data/app/assets/javascripts/ueditor/dialogs/template/template.js +53 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/bg.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/center_focus.jpg +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/file-icons.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/file-icons.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/icons.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/icons.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/image.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/left_focus.jpg +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/none_focus.jpg +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/progress.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/right_focus.jpg +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/success.gif +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/images/success.png +0 -0
- data/app/assets/javascripts/ueditor/dialogs/video/video.css +635 -0
- data/app/assets/javascripts/ueditor/dialogs/video/video.html +86 -0
- data/app/assets/javascripts/ueditor/dialogs/video/video.js +791 -0
- data/app/assets/javascripts/ueditor/dialogs/webapp/webapp.html +53 -0
- data/app/assets/javascripts/ueditor/dialogs/wordimage/fClipboard_ueditor.swf +0 -0
- data/app/assets/javascripts/ueditor/dialogs/wordimage/imageUploader.swf +0 -0
- data/app/assets/javascripts/ueditor/dialogs/wordimage/tangram.js +1495 -0
- data/app/assets/javascripts/ueditor/dialogs/wordimage/wordimage.html +111 -0
- data/app/assets/javascripts/ueditor/dialogs/wordimage/wordimage.js +157 -0
- data/app/assets/javascripts/ueditor/index.html +175 -0
- data/app/assets/javascripts/ueditor/lang/en/en.js +684 -0
- data/app/assets/javascripts/ueditor/lang/en/images/addimage.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/alldeletebtnhoverskin.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/alldeletebtnupskin.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/background.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/button.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/copy.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/deletedisable.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/deleteenable.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/listbackground.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/localimage.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/music.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/rotateleftdisable.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/rotateleftenable.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/rotaterightdisable.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/rotaterightenable.png +0 -0
- data/app/assets/javascripts/ueditor/lang/en/images/upload.png +0 -0
- data/app/assets/javascripts/ueditor/lang/zh-cn/images/copy.png +0 -0
- data/app/assets/javascripts/ueditor/lang/zh-cn/images/localimage.png +0 -0
- data/app/assets/javascripts/ueditor/lang/zh-cn/images/music.png +0 -0
- data/app/assets/javascripts/ueditor/lang/zh-cn/images/upload.png +0 -0
- data/app/assets/javascripts/ueditor/lang/zh-cn/zh-cn.js +669 -0
- data/app/assets/javascripts/ueditor/themes/default/css/ueditor.css +1903 -0
- data/app/assets/javascripts/ueditor/themes/default/css/ueditor.min.css +8 -0
- data/app/assets/javascripts/ueditor/themes/default/dialogbase.css +100 -0
- data/app/assets/javascripts/ueditor/themes/default/images/anchor.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/arrow.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/arrow_down.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/arrow_up.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/button-bg.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/cancelbutton.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/charts.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/cursor_h.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/cursor_h.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/cursor_v.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/cursor_v.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/dialog-title-bg.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/filescan.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/highlighted.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/icons-all.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/icons.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/icons.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/loaderror.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/loading.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/lock.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/neweditor-tab-bg.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/pagebreak.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/scale.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/sortable.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/spacer.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/sparator_v.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/table-cell-align.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/tangram-colorpicker.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/toolbar_bg.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/unhighlighted.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/upload.png +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/videologo.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/word.gif +0 -0
- data/app/assets/javascripts/ueditor/themes/default/images/wordpaste.png +0 -0
- data/app/assets/javascripts/ueditor/themes/iframe.css +1 -0
- data/app/assets/javascripts/ueditor/third-party/SyntaxHighlighter/shCore.js +3655 -0
- data/app/assets/javascripts/ueditor/third-party/SyntaxHighlighter/shCoreDefault.css +1 -0
- data/app/assets/javascripts/ueditor/third-party/codemirror/codemirror.css +104 -0
- data/app/assets/javascripts/ueditor/third-party/codemirror/codemirror.js +3581 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/adapters/mootools-adapter.js +13 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/adapters/mootools-adapter.src.js +313 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/adapters/prototype-adapter.js +15 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js +316 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/adapters/standalone-framework.js +17 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/adapters/standalone-framework.src.js +583 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/highcharts-more.js +50 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/highcharts-more.src.js +2430 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/highcharts.js +283 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/highcharts.src.js +16974 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/annotations.js +7 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/annotations.src.js +401 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/canvas-tools.js +133 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/canvas-tools.src.js +3113 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/data.js +17 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/data.src.js +582 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/drilldown.js +11 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/drilldown.src.js +447 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/exporting.js +22 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/exporting.src.js +709 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/funnel.js +12 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/funnel.src.js +289 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/heatmap.js +1 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/heatmap.src.js +53 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/map.js +27 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/map.src.js +1002 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/no-data-to-display.js +12 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/modules/no-data-to-display.src.js +128 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/themes/dark-blue.js +254 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/themes/dark-green.js +255 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/themes/gray.js +257 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/themes/grid.js +103 -0
- data/app/assets/javascripts/ueditor/third-party/highcharts/themes/skies.js +89 -0
- data/app/assets/javascripts/ueditor/third-party/jquery-1.10.2.js +9789 -0
- data/app/assets/javascripts/ueditor/third-party/jquery-1.10.2.min.js +6 -0
- data/app/assets/javascripts/ueditor/third-party/jquery-1.10.2.min.map +1 -0
- data/app/assets/javascripts/ueditor/third-party/snapscreen/UEditorSnapscreen.exe +0 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/font/vjs.eot +0 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/font/vjs.svg +65 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/font/vjs.ttf +0 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/font/vjs.woff +0 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/video-js.css +766 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/video-js.min.css +5 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/video-js.swf +0 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/video.dev.js +7108 -0
- data/app/assets/javascripts/ueditor/third-party/video-js/video.js +129 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/Uploader.swf +0 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.css +28 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.custom.js +5670 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.custom.min.js +2 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.flashonly.js +4176 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.flashonly.min.js +2 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.html5only.js +5559 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.html5only.min.js +2 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.js +6733 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.min.js +2 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.withoutimage.js +4593 -0
- data/app/assets/javascripts/ueditor/third-party/webuploader/webuploader.withoutimage.min.js +2 -0
- data/app/assets/javascripts/ueditor/third-party/xss.min.js +1 -0
- data/app/assets/javascripts/ueditor/third-party/zeroclipboard/ZeroClipboard.js +1256 -0
- data/app/assets/javascripts/ueditor/third-party/zeroclipboard/ZeroClipboard.min.js +9 -0
- data/app/assets/javascripts/ueditor/third-party/zeroclipboard/ZeroClipboard.swf +0 -0
- data/app/assets/javascripts/ueditor/ueditor.all.js +29568 -0
- data/app/assets/javascripts/ueditor/ueditor.all.min.js +18 -0
- data/app/assets/javascripts/ueditor/ueditor.config.js +497 -0
- data/app/assets/javascripts/ueditor/ueditor.parse.js +1022 -0
- data/app/assets/javascripts/ueditor/ueditor.parse.min.js +7 -0
- data/app/assets/javascripts/{ueditor → ueditor_custom}/preinit.js.erb +0 -0
- data/lib/baidu_ueditor_rails/version.rb +1 -1
- metadata +292 -21
@@ -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/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/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/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("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/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)
|
2
|
+
},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/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/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/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("webuploader",["base","widgets/filepicker","widgets/image","widgets/queue","widgets/runtime","widgets/upload","runtime/html5/blob","runtime/html5/filepicker","runtime/html5/imagemeta/exif","runtime/html5/image","runtime/html5/androidpatch","runtime/html5/transport"],function(a){return a}),c("webuploader")});
|
@@ -0,0 +1,4176 @@
|
|
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 Blob
|
1133
|
+
*/
|
1134
|
+
define('lib/blob',[
|
1135
|
+
'base',
|
1136
|
+
'runtime/client'
|
1137
|
+
], function( Base, RuntimeClient ) {
|
1138
|
+
|
1139
|
+
function Blob( ruid, source ) {
|
1140
|
+
var me = this;
|
1141
|
+
|
1142
|
+
me.source = source;
|
1143
|
+
me.ruid = ruid;
|
1144
|
+
|
1145
|
+
RuntimeClient.call( me, 'Blob' );
|
1146
|
+
|
1147
|
+
this.uid = source.uid || this.uid;
|
1148
|
+
this.type = source.type || '';
|
1149
|
+
this.size = source.size || 0;
|
1150
|
+
|
1151
|
+
if ( ruid ) {
|
1152
|
+
me.connectRuntime( ruid );
|
1153
|
+
}
|
1154
|
+
}
|
1155
|
+
|
1156
|
+
Base.inherits( RuntimeClient, {
|
1157
|
+
constructor: Blob,
|
1158
|
+
|
1159
|
+
slice: function( start, end ) {
|
1160
|
+
return this.exec( 'slice', start, end );
|
1161
|
+
},
|
1162
|
+
|
1163
|
+
getSource: function() {
|
1164
|
+
return this.source;
|
1165
|
+
}
|
1166
|
+
});
|
1167
|
+
|
1168
|
+
return Blob;
|
1169
|
+
});
|
1170
|
+
/**
|
1171
|
+
* 为了统一化Flash的File和HTML5的File而存在。
|
1172
|
+
* 以至于要调用Flash里面的File,也可以像调用HTML5版本的File一下。
|
1173
|
+
* @fileOverview File
|
1174
|
+
*/
|
1175
|
+
define('lib/file',[
|
1176
|
+
'base',
|
1177
|
+
'lib/blob'
|
1178
|
+
], function( Base, Blob ) {
|
1179
|
+
|
1180
|
+
var uid = 1,
|
1181
|
+
rExt = /\.([^.]+)$/;
|
1182
|
+
|
1183
|
+
function File( ruid, file ) {
|
1184
|
+
var ext;
|
1185
|
+
|
1186
|
+
Blob.apply( this, arguments );
|
1187
|
+
this.name = file.name || ('untitled' + uid++);
|
1188
|
+
ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';
|
1189
|
+
|
1190
|
+
// todo 支持其他类型文件的转换。
|
1191
|
+
|
1192
|
+
// 如果有mimetype, 但是文件名里面没有找出后缀规律
|
1193
|
+
if ( !ext && this.type ) {
|
1194
|
+
ext = /\/(jpg|jpeg|png|gif|bmp)$/i.exec( this.type ) ?
|
1195
|
+
RegExp.$1.toLowerCase() : '';
|
1196
|
+
this.name += '.' + ext;
|
1197
|
+
}
|
1198
|
+
|
1199
|
+
// 如果没有指定mimetype, 但是知道文件后缀。
|
1200
|
+
if ( !this.type && ~'jpg,jpeg,png,gif,bmp'.indexOf( ext ) ) {
|
1201
|
+
this.type = 'image/' + (ext === 'jpg' ? 'jpeg' : ext);
|
1202
|
+
}
|
1203
|
+
|
1204
|
+
this.ext = ext;
|
1205
|
+
this.lastModifiedDate = file.lastModifiedDate ||
|
1206
|
+
(new Date()).toLocaleString();
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
return Base.inherits( Blob, File );
|
1210
|
+
});
|
1211
|
+
|
1212
|
+
/**
|
1213
|
+
* @fileOverview 错误信息
|
1214
|
+
*/
|
1215
|
+
define('lib/filepicker',[
|
1216
|
+
'base',
|
1217
|
+
'runtime/client',
|
1218
|
+
'lib/file'
|
1219
|
+
], function( Base, RuntimeClent, File ) {
|
1220
|
+
|
1221
|
+
var $ = Base.$;
|
1222
|
+
|
1223
|
+
function FilePicker( opts ) {
|
1224
|
+
opts = this.options = $.extend({}, FilePicker.options, opts );
|
1225
|
+
|
1226
|
+
opts.container = $( opts.id );
|
1227
|
+
|
1228
|
+
if ( !opts.container.length ) {
|
1229
|
+
throw new Error('按钮指定错误');
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
opts.innerHTML = opts.innerHTML || opts.label ||
|
1233
|
+
opts.container.html() || '';
|
1234
|
+
|
1235
|
+
opts.button = $( opts.button || document.createElement('div') );
|
1236
|
+
opts.button.html( opts.innerHTML );
|
1237
|
+
opts.container.html( opts.button );
|
1238
|
+
|
1239
|
+
RuntimeClent.call( this, 'FilePicker', true );
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
FilePicker.options = {
|
1243
|
+
button: null,
|
1244
|
+
container: null,
|
1245
|
+
label: null,
|
1246
|
+
innerHTML: null,
|
1247
|
+
multiple: true,
|
1248
|
+
accept: null,
|
1249
|
+
name: 'file'
|
1250
|
+
};
|
1251
|
+
|
1252
|
+
Base.inherits( RuntimeClent, {
|
1253
|
+
constructor: FilePicker,
|
1254
|
+
|
1255
|
+
init: function() {
|
1256
|
+
var me = this,
|
1257
|
+
opts = me.options,
|
1258
|
+
button = opts.button;
|
1259
|
+
|
1260
|
+
button.addClass('webuploader-pick');
|
1261
|
+
|
1262
|
+
me.on( 'all', function( type ) {
|
1263
|
+
var files;
|
1264
|
+
|
1265
|
+
switch ( type ) {
|
1266
|
+
case 'mouseenter':
|
1267
|
+
button.addClass('webuploader-pick-hover');
|
1268
|
+
break;
|
1269
|
+
|
1270
|
+
case 'mouseleave':
|
1271
|
+
button.removeClass('webuploader-pick-hover');
|
1272
|
+
break;
|
1273
|
+
|
1274
|
+
case 'change':
|
1275
|
+
files = me.exec('getFiles');
|
1276
|
+
me.trigger( 'select', $.map( files, function( file ) {
|
1277
|
+
file = new File( me.getRuid(), file );
|
1278
|
+
|
1279
|
+
// 记录来源。
|
1280
|
+
file._refer = opts.container;
|
1281
|
+
return file;
|
1282
|
+
}), opts.container );
|
1283
|
+
break;
|
1284
|
+
}
|
1285
|
+
});
|
1286
|
+
|
1287
|
+
me.connectRuntime( opts, function() {
|
1288
|
+
me.refresh();
|
1289
|
+
me.exec( 'init', opts );
|
1290
|
+
me.trigger('ready');
|
1291
|
+
});
|
1292
|
+
|
1293
|
+
$( window ).on( 'resize', function() {
|
1294
|
+
me.refresh();
|
1295
|
+
});
|
1296
|
+
},
|
1297
|
+
|
1298
|
+
refresh: function() {
|
1299
|
+
var shimContainer = this.getRuntime().getContainer(),
|
1300
|
+
button = this.options.button,
|
1301
|
+
width = button.outerWidth ?
|
1302
|
+
button.outerWidth() : button.width(),
|
1303
|
+
|
1304
|
+
height = button.outerHeight ?
|
1305
|
+
button.outerHeight() : button.height(),
|
1306
|
+
|
1307
|
+
pos = button.offset();
|
1308
|
+
|
1309
|
+
width && height && shimContainer.css({
|
1310
|
+
bottom: 'auto',
|
1311
|
+
right: 'auto',
|
1312
|
+
width: width + 'px',
|
1313
|
+
height: height + 'px'
|
1314
|
+
}).offset( pos );
|
1315
|
+
},
|
1316
|
+
|
1317
|
+
enable: function() {
|
1318
|
+
var btn = this.options.button;
|
1319
|
+
|
1320
|
+
btn.removeClass('webuploader-pick-disable');
|
1321
|
+
this.refresh();
|
1322
|
+
},
|
1323
|
+
|
1324
|
+
disable: function() {
|
1325
|
+
var btn = this.options.button;
|
1326
|
+
|
1327
|
+
this.getRuntime().getContainer().css({
|
1328
|
+
top: '-99999px'
|
1329
|
+
});
|
1330
|
+
|
1331
|
+
btn.addClass('webuploader-pick-disable');
|
1332
|
+
},
|
1333
|
+
|
1334
|
+
destroy: function() {
|
1335
|
+
if ( this.runtime ) {
|
1336
|
+
this.exec('destroy');
|
1337
|
+
this.disconnectRuntime();
|
1338
|
+
}
|
1339
|
+
}
|
1340
|
+
});
|
1341
|
+
|
1342
|
+
return FilePicker;
|
1343
|
+
});
|
1344
|
+
|
1345
|
+
/**
|
1346
|
+
* @fileOverview 组件基类。
|
1347
|
+
*/
|
1348
|
+
define('widgets/widget',[
|
1349
|
+
'base',
|
1350
|
+
'uploader'
|
1351
|
+
], function( Base, Uploader ) {
|
1352
|
+
|
1353
|
+
var $ = Base.$,
|
1354
|
+
_init = Uploader.prototype._init,
|
1355
|
+
IGNORE = {},
|
1356
|
+
widgetClass = [];
|
1357
|
+
|
1358
|
+
function isArrayLike( obj ) {
|
1359
|
+
if ( !obj ) {
|
1360
|
+
return false;
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
var length = obj.length,
|
1364
|
+
type = $.type( obj );
|
1365
|
+
|
1366
|
+
if ( obj.nodeType === 1 && length ) {
|
1367
|
+
return true;
|
1368
|
+
}
|
1369
|
+
|
1370
|
+
return type === 'array' || type !== 'function' && type !== 'string' &&
|
1371
|
+
(length === 0 || typeof length === 'number' && length > 0 &&
|
1372
|
+
(length - 1) in obj);
|
1373
|
+
}
|
1374
|
+
|
1375
|
+
function Widget( uploader ) {
|
1376
|
+
this.owner = uploader;
|
1377
|
+
this.options = uploader.options;
|
1378
|
+
}
|
1379
|
+
|
1380
|
+
$.extend( Widget.prototype, {
|
1381
|
+
|
1382
|
+
init: Base.noop,
|
1383
|
+
|
1384
|
+
// 类Backbone的事件监听声明,监听uploader实例上的事件
|
1385
|
+
// widget直接无法监听事件,事件只能通过uploader来传递
|
1386
|
+
invoke: function( apiName, args ) {
|
1387
|
+
|
1388
|
+
/*
|
1389
|
+
{
|
1390
|
+
'make-thumb': 'makeThumb'
|
1391
|
+
}
|
1392
|
+
*/
|
1393
|
+
var map = this.responseMap;
|
1394
|
+
|
1395
|
+
// 如果无API响应声明则忽略
|
1396
|
+
if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||
|
1397
|
+
!$.isFunction( this[ map[ apiName ] ] ) ) {
|
1398
|
+
|
1399
|
+
return IGNORE;
|
1400
|
+
}
|
1401
|
+
|
1402
|
+
return this[ map[ apiName ] ].apply( this, args );
|
1403
|
+
|
1404
|
+
},
|
1405
|
+
|
1406
|
+
/**
|
1407
|
+
* 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。
|
1408
|
+
* @method request
|
1409
|
+
* @grammar request( command, args ) => * | Promise
|
1410
|
+
* @grammar request( command, args, callback ) => Promise
|
1411
|
+
* @for Uploader
|
1412
|
+
*/
|
1413
|
+
request: function() {
|
1414
|
+
return this.owner.request.apply( this.owner, arguments );
|
1415
|
+
}
|
1416
|
+
});
|
1417
|
+
|
1418
|
+
// 扩展Uploader.
|
1419
|
+
$.extend( Uploader.prototype, {
|
1420
|
+
|
1421
|
+
// 覆写_init用来初始化widgets
|
1422
|
+
_init: function() {
|
1423
|
+
var me = this,
|
1424
|
+
widgets = me._widgets = [];
|
1425
|
+
|
1426
|
+
$.each( widgetClass, function( _, klass ) {
|
1427
|
+
widgets.push( new klass( me ) );
|
1428
|
+
});
|
1429
|
+
|
1430
|
+
return _init.apply( me, arguments );
|
1431
|
+
},
|
1432
|
+
|
1433
|
+
request: function( apiName, args, callback ) {
|
1434
|
+
var i = 0,
|
1435
|
+
widgets = this._widgets,
|
1436
|
+
len = widgets.length,
|
1437
|
+
rlts = [],
|
1438
|
+
dfds = [],
|
1439
|
+
widget, rlt, promise, key;
|
1440
|
+
|
1441
|
+
args = isArrayLike( args ) ? args : [ args ];
|
1442
|
+
|
1443
|
+
for ( ; i < len; i++ ) {
|
1444
|
+
widget = widgets[ i ];
|
1445
|
+
rlt = widget.invoke( apiName, args );
|
1446
|
+
|
1447
|
+
if ( rlt !== IGNORE ) {
|
1448
|
+
|
1449
|
+
// Deferred对象
|
1450
|
+
if ( Base.isPromise( rlt ) ) {
|
1451
|
+
dfds.push( rlt );
|
1452
|
+
} else {
|
1453
|
+
rlts.push( rlt );
|
1454
|
+
}
|
1455
|
+
}
|
1456
|
+
}
|
1457
|
+
|
1458
|
+
// 如果有callback,则用异步方式。
|
1459
|
+
if ( callback || dfds.length ) {
|
1460
|
+
promise = Base.when.apply( Base, dfds );
|
1461
|
+
key = promise.pipe ? 'pipe' : 'then';
|
1462
|
+
|
1463
|
+
// 很重要不能删除。删除了会死循环。
|
1464
|
+
// 保证执行顺序。让callback总是在下一个tick中执行。
|
1465
|
+
return promise[ key ](function() {
|
1466
|
+
var deferred = Base.Deferred(),
|
1467
|
+
args = arguments;
|
1468
|
+
|
1469
|
+
setTimeout(function() {
|
1470
|
+
deferred.resolve.apply( deferred, args );
|
1471
|
+
}, 1 );
|
1472
|
+
|
1473
|
+
return deferred.promise();
|
1474
|
+
})[ key ]( callback || Base.noop );
|
1475
|
+
} else {
|
1476
|
+
return rlts[ 0 ];
|
1477
|
+
}
|
1478
|
+
}
|
1479
|
+
});
|
1480
|
+
|
1481
|
+
/**
|
1482
|
+
* 添加组件
|
1483
|
+
* @param {object} widgetProto 组件原型,构造函数通过constructor属性定义
|
1484
|
+
* @param {object} responseMap API名称与函数实现的映射
|
1485
|
+
* @example
|
1486
|
+
* Uploader.register( {
|
1487
|
+
* init: function( options ) {},
|
1488
|
+
* makeThumb: function() {}
|
1489
|
+
* }, {
|
1490
|
+
* 'make-thumb': 'makeThumb'
|
1491
|
+
* } );
|
1492
|
+
*/
|
1493
|
+
Uploader.register = Widget.register = function( responseMap, widgetProto ) {
|
1494
|
+
var map = { init: 'init' },
|
1495
|
+
klass;
|
1496
|
+
|
1497
|
+
if ( arguments.length === 1 ) {
|
1498
|
+
widgetProto = responseMap;
|
1499
|
+
widgetProto.responseMap = map;
|
1500
|
+
} else {
|
1501
|
+
widgetProto.responseMap = $.extend( map, responseMap );
|
1502
|
+
}
|
1503
|
+
|
1504
|
+
klass = Base.inherits( Widget, widgetProto );
|
1505
|
+
widgetClass.push( klass );
|
1506
|
+
|
1507
|
+
return klass;
|
1508
|
+
};
|
1509
|
+
|
1510
|
+
return Widget;
|
1511
|
+
});
|
1512
|
+
/**
|
1513
|
+
* @fileOverview 文件选择相关
|
1514
|
+
*/
|
1515
|
+
define('widgets/filepicker',[
|
1516
|
+
'base',
|
1517
|
+
'uploader',
|
1518
|
+
'lib/filepicker',
|
1519
|
+
'widgets/widget'
|
1520
|
+
], function( Base, Uploader, FilePicker ) {
|
1521
|
+
var $ = Base.$;
|
1522
|
+
|
1523
|
+
$.extend( Uploader.options, {
|
1524
|
+
|
1525
|
+
/**
|
1526
|
+
* @property {Selector | Object} [pick=undefined]
|
1527
|
+
* @namespace options
|
1528
|
+
* @for Uploader
|
1529
|
+
* @description 指定选择文件的按钮容器,不指定则不创建按钮。
|
1530
|
+
*
|
1531
|
+
* * `id` {Seletor} 指定选择文件的按钮容器,不指定则不创建按钮。
|
1532
|
+
* * `label` {String} 请采用 `innerHTML` 代替
|
1533
|
+
* * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。
|
1534
|
+
* * `multiple` {Boolean} 是否开起同时选择多个文件能力。
|
1535
|
+
*/
|
1536
|
+
pick: null,
|
1537
|
+
|
1538
|
+
/**
|
1539
|
+
* @property {Arroy} [accept=null]
|
1540
|
+
* @namespace options
|
1541
|
+
* @for Uploader
|
1542
|
+
* @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表,所以这里需要分开指定。
|
1543
|
+
*
|
1544
|
+
* * `title` {String} 文字描述
|
1545
|
+
* * `extensions` {String} 允许的文件后缀,不带点,多个用逗号分割。
|
1546
|
+
* * `mimeTypes` {String} 多个用逗号分割。
|
1547
|
+
*
|
1548
|
+
* 如:
|
1549
|
+
*
|
1550
|
+
* ```
|
1551
|
+
* {
|
1552
|
+
* title: 'Images',
|
1553
|
+
* extensions: 'gif,jpg,jpeg,bmp,png',
|
1554
|
+
* mimeTypes: 'image/*'
|
1555
|
+
* }
|
1556
|
+
* ```
|
1557
|
+
*/
|
1558
|
+
accept: null/*{
|
1559
|
+
title: 'Images',
|
1560
|
+
extensions: 'gif,jpg,jpeg,bmp,png',
|
1561
|
+
mimeTypes: 'image/*'
|
1562
|
+
}*/
|
1563
|
+
});
|
1564
|
+
|
1565
|
+
return Uploader.register({
|
1566
|
+
'add-btn': 'addButton',
|
1567
|
+
refresh: 'refresh',
|
1568
|
+
disable: 'disable',
|
1569
|
+
enable: 'enable'
|
1570
|
+
}, {
|
1571
|
+
|
1572
|
+
init: function( opts ) {
|
1573
|
+
this.pickers = [];
|
1574
|
+
return opts.pick && this.addButton( opts.pick );
|
1575
|
+
},
|
1576
|
+
|
1577
|
+
refresh: function() {
|
1578
|
+
$.each( this.pickers, function() {
|
1579
|
+
this.refresh();
|
1580
|
+
});
|
1581
|
+
},
|
1582
|
+
|
1583
|
+
/**
|
1584
|
+
* @method addButton
|
1585
|
+
* @for Uploader
|
1586
|
+
* @grammar addButton( pick ) => Promise
|
1587
|
+
* @description
|
1588
|
+
* 添加文件选择按钮,如果一个按钮不够,需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。
|
1589
|
+
* @example
|
1590
|
+
* uploader.addButton({
|
1591
|
+
* id: '#btnContainer',
|
1592
|
+
* innerHTML: '选择文件'
|
1593
|
+
* });
|
1594
|
+
*/
|
1595
|
+
addButton: function( pick ) {
|
1596
|
+
var me = this,
|
1597
|
+
opts = me.options,
|
1598
|
+
accept = opts.accept,
|
1599
|
+
options, picker, deferred;
|
1600
|
+
|
1601
|
+
if ( !pick ) {
|
1602
|
+
return;
|
1603
|
+
}
|
1604
|
+
|
1605
|
+
deferred = Base.Deferred();
|
1606
|
+
$.isPlainObject( pick ) || (pick = {
|
1607
|
+
id: pick
|
1608
|
+
});
|
1609
|
+
|
1610
|
+
options = $.extend({}, pick, {
|
1611
|
+
accept: $.isPlainObject( accept ) ? [ accept ] : accept,
|
1612
|
+
swf: opts.swf,
|
1613
|
+
runtimeOrder: opts.runtimeOrder
|
1614
|
+
});
|
1615
|
+
|
1616
|
+
picker = new FilePicker( options );
|
1617
|
+
|
1618
|
+
picker.once( 'ready', deferred.resolve );
|
1619
|
+
picker.on( 'select', function( files ) {
|
1620
|
+
me.owner.request( 'add-file', [ files ]);
|
1621
|
+
});
|
1622
|
+
picker.init();
|
1623
|
+
|
1624
|
+
this.pickers.push( picker );
|
1625
|
+
|
1626
|
+
return deferred.promise();
|
1627
|
+
},
|
1628
|
+
|
1629
|
+
disable: function() {
|
1630
|
+
$.each( this.pickers, function() {
|
1631
|
+
this.disable();
|
1632
|
+
});
|
1633
|
+
},
|
1634
|
+
|
1635
|
+
enable: function() {
|
1636
|
+
$.each( this.pickers, function() {
|
1637
|
+
this.enable();
|
1638
|
+
});
|
1639
|
+
}
|
1640
|
+
});
|
1641
|
+
});
|
1642
|
+
/**
|
1643
|
+
* @fileOverview Image
|
1644
|
+
*/
|
1645
|
+
define('lib/image',[
|
1646
|
+
'base',
|
1647
|
+
'runtime/client',
|
1648
|
+
'lib/blob'
|
1649
|
+
], function( Base, RuntimeClient, Blob ) {
|
1650
|
+
var $ = Base.$;
|
1651
|
+
|
1652
|
+
// 构造器。
|
1653
|
+
function Image( opts ) {
|
1654
|
+
this.options = $.extend({}, Image.options, opts );
|
1655
|
+
RuntimeClient.call( this, 'Image' );
|
1656
|
+
|
1657
|
+
this.on( 'load', function() {
|
1658
|
+
this._info = this.exec('info');
|
1659
|
+
this._meta = this.exec('meta');
|
1660
|
+
});
|
1661
|
+
}
|
1662
|
+
|
1663
|
+
// 默认选项。
|
1664
|
+
Image.options = {
|
1665
|
+
|
1666
|
+
// 默认的图片处理质量
|
1667
|
+
quality: 90,
|
1668
|
+
|
1669
|
+
// 是否裁剪
|
1670
|
+
crop: false,
|
1671
|
+
|
1672
|
+
// 是否保留头部信息
|
1673
|
+
preserveHeaders: true,
|
1674
|
+
|
1675
|
+
// 是否允许放大。
|
1676
|
+
allowMagnify: true
|
1677
|
+
};
|
1678
|
+
|
1679
|
+
// 继承RuntimeClient.
|
1680
|
+
Base.inherits( RuntimeClient, {
|
1681
|
+
constructor: Image,
|
1682
|
+
|
1683
|
+
info: function( val ) {
|
1684
|
+
|
1685
|
+
// setter
|
1686
|
+
if ( val ) {
|
1687
|
+
this._info = val;
|
1688
|
+
return this;
|
1689
|
+
}
|
1690
|
+
|
1691
|
+
// getter
|
1692
|
+
return this._info;
|
1693
|
+
},
|
1694
|
+
|
1695
|
+
meta: function( val ) {
|
1696
|
+
|
1697
|
+
// setter
|
1698
|
+
if ( val ) {
|
1699
|
+
this._meta = val;
|
1700
|
+
return this;
|
1701
|
+
}
|
1702
|
+
|
1703
|
+
// getter
|
1704
|
+
return this._meta;
|
1705
|
+
},
|
1706
|
+
|
1707
|
+
loadFromBlob: function( blob ) {
|
1708
|
+
var me = this,
|
1709
|
+
ruid = blob.getRuid();
|
1710
|
+
|
1711
|
+
this.connectRuntime( ruid, function() {
|
1712
|
+
me.exec( 'init', me.options );
|
1713
|
+
me.exec( 'loadFromBlob', blob );
|
1714
|
+
});
|
1715
|
+
},
|
1716
|
+
|
1717
|
+
resize: function() {
|
1718
|
+
var args = Base.slice( arguments );
|
1719
|
+
return this.exec.apply( this, [ 'resize' ].concat( args ) );
|
1720
|
+
},
|
1721
|
+
|
1722
|
+
getAsDataUrl: function( type ) {
|
1723
|
+
return this.exec( 'getAsDataUrl', type );
|
1724
|
+
},
|
1725
|
+
|
1726
|
+
getAsBlob: function( type ) {
|
1727
|
+
var blob = this.exec( 'getAsBlob', type );
|
1728
|
+
|
1729
|
+
return new Blob( this.getRuid(), blob );
|
1730
|
+
}
|
1731
|
+
});
|
1732
|
+
|
1733
|
+
return Image;
|
1734
|
+
});
|
1735
|
+
/**
|
1736
|
+
* @fileOverview 图片操作, 负责预览图片和上传前压缩图片
|
1737
|
+
*/
|
1738
|
+
define('widgets/image',[
|
1739
|
+
'base',
|
1740
|
+
'uploader',
|
1741
|
+
'lib/image',
|
1742
|
+
'widgets/widget'
|
1743
|
+
], function( Base, Uploader, Image ) {
|
1744
|
+
|
1745
|
+
var $ = Base.$,
|
1746
|
+
throttle;
|
1747
|
+
|
1748
|
+
// 根据要处理的文件大小来节流,一次不能处理太多,会卡。
|
1749
|
+
throttle = (function( max ) {
|
1750
|
+
var occupied = 0,
|
1751
|
+
waiting = [],
|
1752
|
+
tick = function() {
|
1753
|
+
var item;
|
1754
|
+
|
1755
|
+
while ( waiting.length && occupied < max ) {
|
1756
|
+
item = waiting.shift();
|
1757
|
+
occupied += item[ 0 ];
|
1758
|
+
item[ 1 ]();
|
1759
|
+
}
|
1760
|
+
};
|
1761
|
+
|
1762
|
+
return function( emiter, size, cb ) {
|
1763
|
+
waiting.push([ size, cb ]);
|
1764
|
+
emiter.once( 'destroy', function() {
|
1765
|
+
occupied -= size;
|
1766
|
+
setTimeout( tick, 1 );
|
1767
|
+
});
|
1768
|
+
setTimeout( tick, 1 );
|
1769
|
+
};
|
1770
|
+
})( 5 * 1024 * 1024 );
|
1771
|
+
|
1772
|
+
$.extend( Uploader.options, {
|
1773
|
+
|
1774
|
+
/**
|
1775
|
+
* @property {Object} [thumb]
|
1776
|
+
* @namespace options
|
1777
|
+
* @for Uploader
|
1778
|
+
* @description 配置生成缩略图的选项。
|
1779
|
+
*
|
1780
|
+
* 默认为:
|
1781
|
+
*
|
1782
|
+
* ```javascript
|
1783
|
+
* {
|
1784
|
+
* width: 110,
|
1785
|
+
* height: 110,
|
1786
|
+
*
|
1787
|
+
* // 图片质量,只有type为`image/jpeg`的时候才有效。
|
1788
|
+
* quality: 70,
|
1789
|
+
*
|
1790
|
+
* // 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.
|
1791
|
+
* allowMagnify: true,
|
1792
|
+
*
|
1793
|
+
* // 是否允许裁剪。
|
1794
|
+
* crop: true,
|
1795
|
+
*
|
1796
|
+
* // 是否保留头部meta信息。
|
1797
|
+
* preserveHeaders: false,
|
1798
|
+
*
|
1799
|
+
* // 为空的话则保留原有图片格式。
|
1800
|
+
* // 否则强制转换成指定的类型。
|
1801
|
+
* type: 'image/jpeg'
|
1802
|
+
* }
|
1803
|
+
* ```
|
1804
|
+
*/
|
1805
|
+
thumb: {
|
1806
|
+
width: 110,
|
1807
|
+
height: 110,
|
1808
|
+
quality: 70,
|
1809
|
+
allowMagnify: true,
|
1810
|
+
crop: true,
|
1811
|
+
preserveHeaders: false,
|
1812
|
+
|
1813
|
+
// 为空的话则保留原有图片格式。
|
1814
|
+
// 否则强制转换成指定的类型。
|
1815
|
+
// IE 8下面 base64 大小不能超过 32K 否则预览失败,而非 jpeg 编码的图片很可
|
1816
|
+
// 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg
|
1817
|
+
type: 'image/jpeg'
|
1818
|
+
},
|
1819
|
+
|
1820
|
+
/**
|
1821
|
+
* @property {Object} [compress]
|
1822
|
+
* @namespace options
|
1823
|
+
* @for Uploader
|
1824
|
+
* @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。
|
1825
|
+
*
|
1826
|
+
* 默认为:
|
1827
|
+
*
|
1828
|
+
* ```javascript
|
1829
|
+
* {
|
1830
|
+
* width: 1600,
|
1831
|
+
* height: 1600,
|
1832
|
+
*
|
1833
|
+
* // 图片质量,只有type为`image/jpeg`的时候才有效。
|
1834
|
+
* quality: 90,
|
1835
|
+
*
|
1836
|
+
* // 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.
|
1837
|
+
* allowMagnify: false,
|
1838
|
+
*
|
1839
|
+
* // 是否允许裁剪。
|
1840
|
+
* crop: false,
|
1841
|
+
*
|
1842
|
+
* // 是否保留头部meta信息。
|
1843
|
+
* preserveHeaders: true
|
1844
|
+
* }
|
1845
|
+
* ```
|
1846
|
+
*/
|
1847
|
+
compress: {
|
1848
|
+
width: 1600,
|
1849
|
+
height: 1600,
|
1850
|
+
quality: 90,
|
1851
|
+
allowMagnify: false,
|
1852
|
+
crop: false,
|
1853
|
+
preserveHeaders: true
|
1854
|
+
}
|
1855
|
+
});
|
1856
|
+
|
1857
|
+
return Uploader.register({
|
1858
|
+
'make-thumb': 'makeThumb',
|
1859
|
+
'before-send-file': 'compressImage'
|
1860
|
+
}, {
|
1861
|
+
|
1862
|
+
|
1863
|
+
/**
|
1864
|
+
* 生成缩略图,此过程为异步,所以需要传入`callback`。
|
1865
|
+
* 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。
|
1866
|
+
*
|
1867
|
+
* `callback`中可以接收到两个参数。
|
1868
|
+
* * 第一个为error,如果生成缩略图有错误,此error将为真。
|
1869
|
+
* * 第二个为ret, 缩略图的Data URL值。
|
1870
|
+
*
|
1871
|
+
* **注意**
|
1872
|
+
* Date URL在IE6/7中不支持,所以不用调用此方法了,直接显示一张暂不支持预览图片好了。
|
1873
|
+
*
|
1874
|
+
*
|
1875
|
+
* @method makeThumb
|
1876
|
+
* @grammar makeThumb( file, callback ) => undefined
|
1877
|
+
* @grammar makeThumb( file, callback, width, height ) => undefined
|
1878
|
+
* @for Uploader
|
1879
|
+
* @example
|
1880
|
+
*
|
1881
|
+
* uploader.on( 'fileQueued', function( file ) {
|
1882
|
+
* var $li = ...;
|
1883
|
+
*
|
1884
|
+
* uploader.makeThumb( file, function( error, ret ) {
|
1885
|
+
* if ( error ) {
|
1886
|
+
* $li.text('预览错误');
|
1887
|
+
* } else {
|
1888
|
+
* $li.append('<img alt="" src="' + ret + '" />');
|
1889
|
+
* }
|
1890
|
+
* });
|
1891
|
+
*
|
1892
|
+
* });
|
1893
|
+
*/
|
1894
|
+
makeThumb: function( file, cb, width, height ) {
|
1895
|
+
var opts, image;
|
1896
|
+
|
1897
|
+
file = this.request( 'get-file', file );
|
1898
|
+
|
1899
|
+
// 只预览图片格式。
|
1900
|
+
if ( !file.type.match( /^image/ ) ) {
|
1901
|
+
cb( true );
|
1902
|
+
return;
|
1903
|
+
}
|
1904
|
+
|
1905
|
+
opts = $.extend({}, this.options.thumb );
|
1906
|
+
|
1907
|
+
// 如果传入的是object.
|
1908
|
+
if ( $.isPlainObject( width ) ) {
|
1909
|
+
opts = $.extend( opts, width );
|
1910
|
+
width = null;
|
1911
|
+
}
|
1912
|
+
|
1913
|
+
width = width || opts.width;
|
1914
|
+
height = height || opts.height;
|
1915
|
+
|
1916
|
+
image = new Image( opts );
|
1917
|
+
|
1918
|
+
image.once( 'load', function() {
|
1919
|
+
file._info = file._info || image.info();
|
1920
|
+
file._meta = file._meta || image.meta();
|
1921
|
+
image.resize( width, height );
|
1922
|
+
});
|
1923
|
+
|
1924
|
+
image.once( 'complete', function() {
|
1925
|
+
cb( false, image.getAsDataUrl( opts.type ) );
|
1926
|
+
image.destroy();
|
1927
|
+
});
|
1928
|
+
|
1929
|
+
image.once( 'error', function() {
|
1930
|
+
cb( true );
|
1931
|
+
image.destroy();
|
1932
|
+
});
|
1933
|
+
|
1934
|
+
throttle( image, file.source.size, function() {
|
1935
|
+
file._info && image.info( file._info );
|
1936
|
+
file._meta && image.meta( file._meta );
|
1937
|
+
image.loadFromBlob( file.source );
|
1938
|
+
});
|
1939
|
+
},
|
1940
|
+
|
1941
|
+
compressImage: function( file ) {
|
1942
|
+
var opts = this.options.compress || this.options.resize,
|
1943
|
+
compressSize = opts && opts.compressSize || 300 * 1024,
|
1944
|
+
image, deferred;
|
1945
|
+
|
1946
|
+
file = this.request( 'get-file', file );
|
1947
|
+
|
1948
|
+
// 只预览图片格式。
|
1949
|
+
if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||
|
1950
|
+
file.size < compressSize ||
|
1951
|
+
file._compressed ) {
|
1952
|
+
return;
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
opts = $.extend({}, opts );
|
1956
|
+
deferred = Base.Deferred();
|
1957
|
+
|
1958
|
+
image = new Image( opts );
|
1959
|
+
|
1960
|
+
deferred.always(function() {
|
1961
|
+
image.destroy();
|
1962
|
+
image = null;
|
1963
|
+
});
|
1964
|
+
image.once( 'error', deferred.reject );
|
1965
|
+
image.once( 'load', function() {
|
1966
|
+
file._info = file._info || image.info();
|
1967
|
+
file._meta = file._meta || image.meta();
|
1968
|
+
image.resize( opts.width, opts.height );
|
1969
|
+
});
|
1970
|
+
|
1971
|
+
image.once( 'complete', function() {
|
1972
|
+
var blob, size;
|
1973
|
+
|
1974
|
+
// 移动端 UC / qq 浏览器的无图模式下
|
1975
|
+
// ctx.getImageData 处理大图的时候会报 Exception
|
1976
|
+
// INDEX_SIZE_ERR: DOM Exception 1
|
1977
|
+
try {
|
1978
|
+
blob = image.getAsBlob( opts.type );
|
1979
|
+
|
1980
|
+
size = file.size;
|
1981
|
+
|
1982
|
+
// 如果压缩后,比原来还大则不用压缩后的。
|
1983
|
+
if ( blob.size < size ) {
|
1984
|
+
// file.source.destroy && file.source.destroy();
|
1985
|
+
file.source = blob;
|
1986
|
+
file.size = blob.size;
|
1987
|
+
|
1988
|
+
file.trigger( 'resize', blob.size, size );
|
1989
|
+
}
|
1990
|
+
|
1991
|
+
// 标记,避免重复压缩。
|
1992
|
+
file._compressed = true;
|
1993
|
+
deferred.resolve();
|
1994
|
+
} catch ( e ) {
|
1995
|
+
// 出错了直接继续,让其上传原始图片
|
1996
|
+
deferred.resolve();
|
1997
|
+
}
|
1998
|
+
});
|
1999
|
+
|
2000
|
+
file._info && image.info( file._info );
|
2001
|
+
file._meta && image.meta( file._meta );
|
2002
|
+
|
2003
|
+
image.loadFromBlob( file.source );
|
2004
|
+
return deferred.promise();
|
2005
|
+
}
|
2006
|
+
});
|
2007
|
+
});
|
2008
|
+
/**
|
2009
|
+
* @fileOverview 文件属性封装
|
2010
|
+
*/
|
2011
|
+
define('file',[
|
2012
|
+
'base',
|
2013
|
+
'mediator'
|
2014
|
+
], function( Base, Mediator ) {
|
2015
|
+
|
2016
|
+
var $ = Base.$,
|
2017
|
+
idPrefix = 'WU_FILE_',
|
2018
|
+
idSuffix = 0,
|
2019
|
+
rExt = /\.([^.]+)$/,
|
2020
|
+
statusMap = {};
|
2021
|
+
|
2022
|
+
function gid() {
|
2023
|
+
return idPrefix + idSuffix++;
|
2024
|
+
}
|
2025
|
+
|
2026
|
+
/**
|
2027
|
+
* 文件类
|
2028
|
+
* @class File
|
2029
|
+
* @constructor 构造函数
|
2030
|
+
* @grammar new File( source ) => File
|
2031
|
+
* @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。
|
2032
|
+
*/
|
2033
|
+
function WUFile( source ) {
|
2034
|
+
|
2035
|
+
/**
|
2036
|
+
* 文件名,包括扩展名(后缀)
|
2037
|
+
* @property name
|
2038
|
+
* @type {string}
|
2039
|
+
*/
|
2040
|
+
this.name = source.name || 'Untitled';
|
2041
|
+
|
2042
|
+
/**
|
2043
|
+
* 文件体积(字节)
|
2044
|
+
* @property size
|
2045
|
+
* @type {uint}
|
2046
|
+
* @default 0
|
2047
|
+
*/
|
2048
|
+
this.size = source.size || 0;
|
2049
|
+
|
2050
|
+
/**
|
2051
|
+
* 文件MIMETYPE类型,与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)
|
2052
|
+
* @property type
|
2053
|
+
* @type {string}
|
2054
|
+
* @default 'application'
|
2055
|
+
*/
|
2056
|
+
this.type = source.type || 'application';
|
2057
|
+
|
2058
|
+
/**
|
2059
|
+
* 文件最后修改日期
|
2060
|
+
* @property lastModifiedDate
|
2061
|
+
* @type {int}
|
2062
|
+
* @default 当前时间戳
|
2063
|
+
*/
|
2064
|
+
this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);
|
2065
|
+
|
2066
|
+
/**
|
2067
|
+
* 文件ID,每个对象具有唯一ID,与文件名无关
|
2068
|
+
* @property id
|
2069
|
+
* @type {string}
|
2070
|
+
*/
|
2071
|
+
this.id = gid();
|
2072
|
+
|
2073
|
+
/**
|
2074
|
+
* 文件扩展名,通过文件名获取,例如test.png的扩展名为png
|
2075
|
+
* @property ext
|
2076
|
+
* @type {string}
|
2077
|
+
*/
|
2078
|
+
this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';
|
2079
|
+
|
2080
|
+
|
2081
|
+
/**
|
2082
|
+
* 状态文字说明。在不同的status语境下有不同的用途。
|
2083
|
+
* @property statusText
|
2084
|
+
* @type {string}
|
2085
|
+
*/
|
2086
|
+
this.statusText = '';
|
2087
|
+
|
2088
|
+
// 存储文件状态,防止通过属性直接修改
|
2089
|
+
statusMap[ this.id ] = WUFile.Status.INITED;
|
2090
|
+
|
2091
|
+
this.source = source;
|
2092
|
+
this.loaded = 0;
|
2093
|
+
|
2094
|
+
this.on( 'error', function( msg ) {
|
2095
|
+
this.setStatus( WUFile.Status.ERROR, msg );
|
2096
|
+
});
|
2097
|
+
}
|
2098
|
+
|
2099
|
+
$.extend( WUFile.prototype, {
|
2100
|
+
|
2101
|
+
/**
|
2102
|
+
* 设置状态,状态变化时会触发`change`事件。
|
2103
|
+
* @method setStatus
|
2104
|
+
* @grammar setStatus( status[, statusText] );
|
2105
|
+
* @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)
|
2106
|
+
* @param {String} [statusText=''] 状态说明,常在error时使用,用http, abort,server等来标记是由于什么原因导致文件错误。
|
2107
|
+
*/
|
2108
|
+
setStatus: function( status, text ) {
|
2109
|
+
|
2110
|
+
var prevStatus = statusMap[ this.id ];
|
2111
|
+
|
2112
|
+
typeof text !== 'undefined' && (this.statusText = text);
|
2113
|
+
|
2114
|
+
if ( status !== prevStatus ) {
|
2115
|
+
statusMap[ this.id ] = status;
|
2116
|
+
/**
|
2117
|
+
* 文件状态变化
|
2118
|
+
* @event statuschange
|
2119
|
+
*/
|
2120
|
+
this.trigger( 'statuschange', status, prevStatus );
|
2121
|
+
}
|
2122
|
+
|
2123
|
+
},
|
2124
|
+
|
2125
|
+
/**
|
2126
|
+
* 获取文件状态
|
2127
|
+
* @return {File.Status}
|
2128
|
+
* @example
|
2129
|
+
文件状态具体包括以下几种类型:
|
2130
|
+
{
|
2131
|
+
// 初始化
|
2132
|
+
INITED: 0,
|
2133
|
+
// 已入队列
|
2134
|
+
QUEUED: 1,
|
2135
|
+
// 正在上传
|
2136
|
+
PROGRESS: 2,
|
2137
|
+
// 上传出错
|
2138
|
+
ERROR: 3,
|
2139
|
+
// 上传成功
|
2140
|
+
COMPLETE: 4,
|
2141
|
+
// 上传取消
|
2142
|
+
CANCELLED: 5
|
2143
|
+
}
|
2144
|
+
*/
|
2145
|
+
getStatus: function() {
|
2146
|
+
return statusMap[ this.id ];
|
2147
|
+
},
|
2148
|
+
|
2149
|
+
/**
|
2150
|
+
* 获取文件原始信息。
|
2151
|
+
* @return {*}
|
2152
|
+
*/
|
2153
|
+
getSource: function() {
|
2154
|
+
return this.source;
|
2155
|
+
},
|
2156
|
+
|
2157
|
+
destory: function() {
|
2158
|
+
delete statusMap[ this.id ];
|
2159
|
+
}
|
2160
|
+
});
|
2161
|
+
|
2162
|
+
Mediator.installTo( WUFile.prototype );
|
2163
|
+
|
2164
|
+
/**
|
2165
|
+
* 文件状态值,具体包括以下几种类型:
|
2166
|
+
* * `inited` 初始状态
|
2167
|
+
* * `queued` 已经进入队列, 等待上传
|
2168
|
+
* * `progress` 上传中
|
2169
|
+
* * `complete` 上传完成。
|
2170
|
+
* * `error` 上传出错,可重试
|
2171
|
+
* * `interrupt` 上传中断,可续传。
|
2172
|
+
* * `invalid` 文件不合格,不能重试上传。会自动从队列中移除。
|
2173
|
+
* * `cancelled` 文件被移除。
|
2174
|
+
* @property {Object} Status
|
2175
|
+
* @namespace File
|
2176
|
+
* @class File
|
2177
|
+
* @static
|
2178
|
+
*/
|
2179
|
+
WUFile.Status = {
|
2180
|
+
INITED: 'inited', // 初始状态
|
2181
|
+
QUEUED: 'queued', // 已经进入队列, 等待上传
|
2182
|
+
PROGRESS: 'progress', // 上传中
|
2183
|
+
ERROR: 'error', // 上传出错,可重试
|
2184
|
+
COMPLETE: 'complete', // 上传完成。
|
2185
|
+
CANCELLED: 'cancelled', // 上传取消。
|
2186
|
+
INTERRUPT: 'interrupt', // 上传中断,可续传。
|
2187
|
+
INVALID: 'invalid' // 文件不合格,不能重试上传。
|
2188
|
+
};
|
2189
|
+
|
2190
|
+
return WUFile;
|
2191
|
+
});
|
2192
|
+
|
2193
|
+
/**
|
2194
|
+
* @fileOverview 文件队列
|
2195
|
+
*/
|
2196
|
+
define('queue',[
|
2197
|
+
'base',
|
2198
|
+
'mediator',
|
2199
|
+
'file'
|
2200
|
+
], function( Base, Mediator, WUFile ) {
|
2201
|
+
|
2202
|
+
var $ = Base.$,
|
2203
|
+
STATUS = WUFile.Status;
|
2204
|
+
|
2205
|
+
/**
|
2206
|
+
* 文件队列, 用来存储各个状态中的文件。
|
2207
|
+
* @class Queue
|
2208
|
+
* @extends Mediator
|
2209
|
+
*/
|
2210
|
+
function Queue() {
|
2211
|
+
|
2212
|
+
/**
|
2213
|
+
* 统计文件数。
|
2214
|
+
* * `numOfQueue` 队列中的文件数。
|
2215
|
+
* * `numOfSuccess` 上传成功的文件数
|
2216
|
+
* * `numOfCancel` 被移除的文件数
|
2217
|
+
* * `numOfProgress` 正在上传中的文件数
|
2218
|
+
* * `numOfUploadFailed` 上传错误的文件数。
|
2219
|
+
* * `numOfInvalid` 无效的文件数。
|
2220
|
+
* @property {Object} stats
|
2221
|
+
*/
|
2222
|
+
this.stats = {
|
2223
|
+
numOfQueue: 0,
|
2224
|
+
numOfSuccess: 0,
|
2225
|
+
numOfCancel: 0,
|
2226
|
+
numOfProgress: 0,
|
2227
|
+
numOfUploadFailed: 0,
|
2228
|
+
numOfInvalid: 0
|
2229
|
+
};
|
2230
|
+
|
2231
|
+
// 上传队列,仅包括等待上传的文件
|
2232
|
+
this._queue = [];
|
2233
|
+
|
2234
|
+
// 存储所有文件
|
2235
|
+
this._map = {};
|
2236
|
+
}
|
2237
|
+
|
2238
|
+
$.extend( Queue.prototype, {
|
2239
|
+
|
2240
|
+
/**
|
2241
|
+
* 将新文件加入对队列尾部
|
2242
|
+
*
|
2243
|
+
* @method append
|
2244
|
+
* @param {File} file 文件对象
|
2245
|
+
*/
|
2246
|
+
append: function( file ) {
|
2247
|
+
this._queue.push( file );
|
2248
|
+
this._fileAdded( file );
|
2249
|
+
return this;
|
2250
|
+
},
|
2251
|
+
|
2252
|
+
/**
|
2253
|
+
* 将新文件加入对队列头部
|
2254
|
+
*
|
2255
|
+
* @method prepend
|
2256
|
+
* @param {File} file 文件对象
|
2257
|
+
*/
|
2258
|
+
prepend: function( file ) {
|
2259
|
+
this._queue.unshift( file );
|
2260
|
+
this._fileAdded( file );
|
2261
|
+
return this;
|
2262
|
+
},
|
2263
|
+
|
2264
|
+
/**
|
2265
|
+
* 获取文件对象
|
2266
|
+
*
|
2267
|
+
* @method getFile
|
2268
|
+
* @param {String} fileId 文件ID
|
2269
|
+
* @return {File}
|
2270
|
+
*/
|
2271
|
+
getFile: function( fileId ) {
|
2272
|
+
if ( typeof fileId !== 'string' ) {
|
2273
|
+
return fileId;
|
2274
|
+
}
|
2275
|
+
return this._map[ fileId ];
|
2276
|
+
},
|
2277
|
+
|
2278
|
+
/**
|
2279
|
+
* 从队列中取出一个指定状态的文件。
|
2280
|
+
* @grammar fetch( status ) => File
|
2281
|
+
* @method fetch
|
2282
|
+
* @param {String} status [文件状态值](#WebUploader:File:File.Status)
|
2283
|
+
* @return {File} [File](#WebUploader:File)
|
2284
|
+
*/
|
2285
|
+
fetch: function( status ) {
|
2286
|
+
var len = this._queue.length,
|
2287
|
+
i, file;
|
2288
|
+
|
2289
|
+
status = status || STATUS.QUEUED;
|
2290
|
+
|
2291
|
+
for ( i = 0; i < len; i++ ) {
|
2292
|
+
file = this._queue[ i ];
|
2293
|
+
|
2294
|
+
if ( status === file.getStatus() ) {
|
2295
|
+
return file;
|
2296
|
+
}
|
2297
|
+
}
|
2298
|
+
|
2299
|
+
return null;
|
2300
|
+
},
|
2301
|
+
|
2302
|
+
/**
|
2303
|
+
* 对队列进行排序,能够控制文件上传顺序。
|
2304
|
+
* @grammar sort( fn ) => undefined
|
2305
|
+
* @method sort
|
2306
|
+
* @param {Function} fn 排序方法
|
2307
|
+
*/
|
2308
|
+
sort: function( fn ) {
|
2309
|
+
if ( typeof fn === 'function' ) {
|
2310
|
+
this._queue.sort( fn );
|
2311
|
+
}
|
2312
|
+
},
|
2313
|
+
|
2314
|
+
/**
|
2315
|
+
* 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。
|
2316
|
+
* @grammar getFiles( [status1[, status2 ...]] ) => Array
|
2317
|
+
* @method getFiles
|
2318
|
+
* @param {String} [status] [文件状态值](#WebUploader:File:File.Status)
|
2319
|
+
*/
|
2320
|
+
getFiles: function() {
|
2321
|
+
var sts = [].slice.call( arguments, 0 ),
|
2322
|
+
ret = [],
|
2323
|
+
i = 0,
|
2324
|
+
len = this._queue.length,
|
2325
|
+
file;
|
2326
|
+
|
2327
|
+
for ( ; i < len; i++ ) {
|
2328
|
+
file = this._queue[ i ];
|
2329
|
+
|
2330
|
+
if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {
|
2331
|
+
continue;
|
2332
|
+
}
|
2333
|
+
|
2334
|
+
ret.push( file );
|
2335
|
+
}
|
2336
|
+
|
2337
|
+
return ret;
|
2338
|
+
},
|
2339
|
+
|
2340
|
+
_fileAdded: function( file ) {
|
2341
|
+
var me = this,
|
2342
|
+
existing = this._map[ file.id ];
|
2343
|
+
|
2344
|
+
if ( !existing ) {
|
2345
|
+
this._map[ file.id ] = file;
|
2346
|
+
|
2347
|
+
file.on( 'statuschange', function( cur, pre ) {
|
2348
|
+
me._onFileStatusChange( cur, pre );
|
2349
|
+
});
|
2350
|
+
}
|
2351
|
+
|
2352
|
+
file.setStatus( STATUS.QUEUED );
|
2353
|
+
},
|
2354
|
+
|
2355
|
+
_onFileStatusChange: function( curStatus, preStatus ) {
|
2356
|
+
var stats = this.stats;
|
2357
|
+
|
2358
|
+
switch ( preStatus ) {
|
2359
|
+
case STATUS.PROGRESS:
|
2360
|
+
stats.numOfProgress--;
|
2361
|
+
break;
|
2362
|
+
|
2363
|
+
case STATUS.QUEUED:
|
2364
|
+
stats.numOfQueue --;
|
2365
|
+
break;
|
2366
|
+
|
2367
|
+
case STATUS.ERROR:
|
2368
|
+
stats.numOfUploadFailed--;
|
2369
|
+
break;
|
2370
|
+
|
2371
|
+
case STATUS.INVALID:
|
2372
|
+
stats.numOfInvalid--;
|
2373
|
+
break;
|
2374
|
+
}
|
2375
|
+
|
2376
|
+
switch ( curStatus ) {
|
2377
|
+
case STATUS.QUEUED:
|
2378
|
+
stats.numOfQueue++;
|
2379
|
+
break;
|
2380
|
+
|
2381
|
+
case STATUS.PROGRESS:
|
2382
|
+
stats.numOfProgress++;
|
2383
|
+
break;
|
2384
|
+
|
2385
|
+
case STATUS.ERROR:
|
2386
|
+
stats.numOfUploadFailed++;
|
2387
|
+
break;
|
2388
|
+
|
2389
|
+
case STATUS.COMPLETE:
|
2390
|
+
stats.numOfSuccess++;
|
2391
|
+
break;
|
2392
|
+
|
2393
|
+
case STATUS.CANCELLED:
|
2394
|
+
stats.numOfCancel++;
|
2395
|
+
break;
|
2396
|
+
|
2397
|
+
case STATUS.INVALID:
|
2398
|
+
stats.numOfInvalid++;
|
2399
|
+
break;
|
2400
|
+
}
|
2401
|
+
}
|
2402
|
+
|
2403
|
+
});
|
2404
|
+
|
2405
|
+
Mediator.installTo( Queue.prototype );
|
2406
|
+
|
2407
|
+
return Queue;
|
2408
|
+
});
|
2409
|
+
/**
|
2410
|
+
* @fileOverview 队列
|
2411
|
+
*/
|
2412
|
+
define('widgets/queue',[
|
2413
|
+
'base',
|
2414
|
+
'uploader',
|
2415
|
+
'queue',
|
2416
|
+
'file',
|
2417
|
+
'lib/file',
|
2418
|
+
'runtime/client',
|
2419
|
+
'widgets/widget'
|
2420
|
+
], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {
|
2421
|
+
|
2422
|
+
var $ = Base.$,
|
2423
|
+
rExt = /\.\w+$/,
|
2424
|
+
Status = WUFile.Status;
|
2425
|
+
|
2426
|
+
return Uploader.register({
|
2427
|
+
'sort-files': 'sortFiles',
|
2428
|
+
'add-file': 'addFiles',
|
2429
|
+
'get-file': 'getFile',
|
2430
|
+
'fetch-file': 'fetchFile',
|
2431
|
+
'get-stats': 'getStats',
|
2432
|
+
'get-files': 'getFiles',
|
2433
|
+
'remove-file': 'removeFile',
|
2434
|
+
'retry': 'retry',
|
2435
|
+
'reset': 'reset',
|
2436
|
+
'accept-file': 'acceptFile'
|
2437
|
+
}, {
|
2438
|
+
|
2439
|
+
init: function( opts ) {
|
2440
|
+
var me = this,
|
2441
|
+
deferred, len, i, item, arr, accept, runtime;
|
2442
|
+
|
2443
|
+
if ( $.isPlainObject( opts.accept ) ) {
|
2444
|
+
opts.accept = [ opts.accept ];
|
2445
|
+
}
|
2446
|
+
|
2447
|
+
// accept中的中生成匹配正则。
|
2448
|
+
if ( opts.accept ) {
|
2449
|
+
arr = [];
|
2450
|
+
|
2451
|
+
for ( i = 0, len = opts.accept.length; i < len; i++ ) {
|
2452
|
+
item = opts.accept[ i ].extensions;
|
2453
|
+
item && arr.push( item );
|
2454
|
+
}
|
2455
|
+
|
2456
|
+
if ( arr.length ) {
|
2457
|
+
accept = '\\.' + arr.join(',')
|
2458
|
+
.replace( /,/g, '$|\\.' )
|
2459
|
+
.replace( /\*/g, '.*' ) + '$';
|
2460
|
+
}
|
2461
|
+
|
2462
|
+
me.accept = new RegExp( accept, 'i' );
|
2463
|
+
}
|
2464
|
+
|
2465
|
+
me.queue = new Queue();
|
2466
|
+
me.stats = me.queue.stats;
|
2467
|
+
|
2468
|
+
// 如果当前不是html5运行时,那就算了。
|
2469
|
+
// 不执行后续操作
|
2470
|
+
if ( this.request('predict-runtime-type') !== 'html5' ) {
|
2471
|
+
return;
|
2472
|
+
}
|
2473
|
+
|
2474
|
+
// 创建一个 html5 运行时的 placeholder
|
2475
|
+
// 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。
|
2476
|
+
deferred = Base.Deferred();
|
2477
|
+
runtime = new RuntimeClient('Placeholder');
|
2478
|
+
runtime.connectRuntime({
|
2479
|
+
runtimeOrder: 'html5'
|
2480
|
+
}, function() {
|
2481
|
+
me._ruid = runtime.getRuid();
|
2482
|
+
deferred.resolve();
|
2483
|
+
});
|
2484
|
+
return deferred.promise();
|
2485
|
+
},
|
2486
|
+
|
2487
|
+
|
2488
|
+
// 为了支持外部直接添加一个原生File对象。
|
2489
|
+
_wrapFile: function( file ) {
|
2490
|
+
if ( !(file instanceof WUFile) ) {
|
2491
|
+
|
2492
|
+
if ( !(file instanceof File) ) {
|
2493
|
+
if ( !this._ruid ) {
|
2494
|
+
throw new Error('Can\'t add external files.');
|
2495
|
+
}
|
2496
|
+
file = new File( this._ruid, file );
|
2497
|
+
}
|
2498
|
+
|
2499
|
+
file = new WUFile( file );
|
2500
|
+
}
|
2501
|
+
|
2502
|
+
return file;
|
2503
|
+
},
|
2504
|
+
|
2505
|
+
// 判断文件是否可以被加入队列
|
2506
|
+
acceptFile: function( file ) {
|
2507
|
+
var invalid = !file || file.size < 6 || this.accept &&
|
2508
|
+
|
2509
|
+
// 如果名字中有后缀,才做后缀白名单处理。
|
2510
|
+
rExt.exec( file.name ) && !this.accept.test( file.name );
|
2511
|
+
|
2512
|
+
return !invalid;
|
2513
|
+
},
|
2514
|
+
|
2515
|
+
|
2516
|
+
/**
|
2517
|
+
* @event beforeFileQueued
|
2518
|
+
* @param {File} file File对象
|
2519
|
+
* @description 当文件被加入队列之前触发,此事件的handler返回值为`false`,则此文件不会被添加进入队列。
|
2520
|
+
* @for Uploader
|
2521
|
+
*/
|
2522
|
+
|
2523
|
+
/**
|
2524
|
+
* @event fileQueued
|
2525
|
+
* @param {File} file File对象
|
2526
|
+
* @description 当文件被加入队列以后触发。
|
2527
|
+
* @for Uploader
|
2528
|
+
*/
|
2529
|
+
|
2530
|
+
_addFile: function( file ) {
|
2531
|
+
var me = this;
|
2532
|
+
|
2533
|
+
file = me._wrapFile( file );
|
2534
|
+
|
2535
|
+
// 不过类型判断允许不允许,先派送 `beforeFileQueued`
|
2536
|
+
if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {
|
2537
|
+
return;
|
2538
|
+
}
|
2539
|
+
|
2540
|
+
// 类型不匹配,则派送错误事件,并返回。
|
2541
|
+
if ( !me.acceptFile( file ) ) {
|
2542
|
+
me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );
|
2543
|
+
return;
|
2544
|
+
}
|
2545
|
+
|
2546
|
+
me.queue.append( file );
|
2547
|
+
me.owner.trigger( 'fileQueued', file );
|
2548
|
+
return file;
|
2549
|
+
},
|
2550
|
+
|
2551
|
+
getFile: function( fileId ) {
|
2552
|
+
return this.queue.getFile( fileId );
|
2553
|
+
},
|
2554
|
+
|
2555
|
+
/**
|
2556
|
+
* @event filesQueued
|
2557
|
+
* @param {File} files 数组,内容为原始File(lib/File)对象。
|
2558
|
+
* @description 当一批文件添加进队列以后触发。
|
2559
|
+
* @for Uploader
|
2560
|
+
*/
|
2561
|
+
|
2562
|
+
/**
|
2563
|
+
* @method addFiles
|
2564
|
+
* @grammar addFiles( file ) => undefined
|
2565
|
+
* @grammar addFiles( [file1, file2 ...] ) => undefined
|
2566
|
+
* @param {Array of File or File} [files] Files 对象 数组
|
2567
|
+
* @description 添加文件到队列
|
2568
|
+
* @for Uploader
|
2569
|
+
*/
|
2570
|
+
addFiles: function( files ) {
|
2571
|
+
var me = this;
|
2572
|
+
|
2573
|
+
if ( !files.length ) {
|
2574
|
+
files = [ files ];
|
2575
|
+
}
|
2576
|
+
|
2577
|
+
files = $.map( files, function( file ) {
|
2578
|
+
return me._addFile( file );
|
2579
|
+
});
|
2580
|
+
|
2581
|
+
me.owner.trigger( 'filesQueued', files );
|
2582
|
+
|
2583
|
+
if ( me.options.auto ) {
|
2584
|
+
me.request('start-upload');
|
2585
|
+
}
|
2586
|
+
},
|
2587
|
+
|
2588
|
+
getStats: function() {
|
2589
|
+
return this.stats;
|
2590
|
+
},
|
2591
|
+
|
2592
|
+
/**
|
2593
|
+
* @event fileDequeued
|
2594
|
+
* @param {File} file File对象
|
2595
|
+
* @description 当文件被移除队列后触发。
|
2596
|
+
* @for Uploader
|
2597
|
+
*/
|
2598
|
+
|
2599
|
+
/**
|
2600
|
+
* @method removeFile
|
2601
|
+
* @grammar removeFile( file ) => undefined
|
2602
|
+
* @grammar removeFile( id ) => undefined
|
2603
|
+
* @param {File|id} file File对象或这File对象的id
|
2604
|
+
* @description 移除某一文件。
|
2605
|
+
* @for Uploader
|
2606
|
+
* @example
|
2607
|
+
*
|
2608
|
+
* $li.on('click', '.remove-this', function() {
|
2609
|
+
* uploader.removeFile( file );
|
2610
|
+
* })
|
2611
|
+
*/
|
2612
|
+
removeFile: function( file ) {
|
2613
|
+
var me = this;
|
2614
|
+
|
2615
|
+
file = file.id ? file : me.queue.getFile( file );
|
2616
|
+
|
2617
|
+
file.setStatus( Status.CANCELLED );
|
2618
|
+
me.owner.trigger( 'fileDequeued', file );
|
2619
|
+
},
|
2620
|
+
|
2621
|
+
/**
|
2622
|
+
* @method getFiles
|
2623
|
+
* @grammar getFiles() => Array
|
2624
|
+
* @grammar getFiles( status1, status2, status... ) => Array
|
2625
|
+
* @description 返回指定状态的文件集合,不传参数将返回所有状态的文件。
|
2626
|
+
* @for Uploader
|
2627
|
+
* @example
|
2628
|
+
* console.log( uploader.getFiles() ); // => all files
|
2629
|
+
* console.log( uploader.getFiles('error') ) // => all error files.
|
2630
|
+
*/
|
2631
|
+
getFiles: function() {
|
2632
|
+
return this.queue.getFiles.apply( this.queue, arguments );
|
2633
|
+
},
|
2634
|
+
|
2635
|
+
fetchFile: function() {
|
2636
|
+
return this.queue.fetch.apply( this.queue, arguments );
|
2637
|
+
},
|
2638
|
+
|
2639
|
+
/**
|
2640
|
+
* @method retry
|
2641
|
+
* @grammar retry() => undefined
|
2642
|
+
* @grammar retry( file ) => undefined
|
2643
|
+
* @description 重试上传,重试指定文件,或者从出错的文件开始重新上传。
|
2644
|
+
* @for Uploader
|
2645
|
+
* @example
|
2646
|
+
* function retry() {
|
2647
|
+
* uploader.retry();
|
2648
|
+
* }
|
2649
|
+
*/
|
2650
|
+
retry: function( file, noForceStart ) {
|
2651
|
+
var me = this,
|
2652
|
+
files, i, len;
|
2653
|
+
|
2654
|
+
if ( file ) {
|
2655
|
+
file = file.id ? file : me.queue.getFile( file );
|
2656
|
+
file.setStatus( Status.QUEUED );
|
2657
|
+
noForceStart || me.request('start-upload');
|
2658
|
+
return;
|
2659
|
+
}
|
2660
|
+
|
2661
|
+
files = me.queue.getFiles( Status.ERROR );
|
2662
|
+
i = 0;
|
2663
|
+
len = files.length;
|
2664
|
+
|
2665
|
+
for ( ; i < len; i++ ) {
|
2666
|
+
file = files[ i ];
|
2667
|
+
file.setStatus( Status.QUEUED );
|
2668
|
+
}
|
2669
|
+
|
2670
|
+
me.request('start-upload');
|
2671
|
+
},
|
2672
|
+
|
2673
|
+
/**
|
2674
|
+
* @method sort
|
2675
|
+
* @grammar sort( fn ) => undefined
|
2676
|
+
* @description 排序队列中的文件,在上传之前调整可以控制上传顺序。
|
2677
|
+
* @for Uploader
|
2678
|
+
*/
|
2679
|
+
sortFiles: function() {
|
2680
|
+
return this.queue.sort.apply( this.queue, arguments );
|
2681
|
+
},
|
2682
|
+
|
2683
|
+
/**
|
2684
|
+
* @method reset
|
2685
|
+
* @grammar reset() => undefined
|
2686
|
+
* @description 重置uploader。目前只重置了队列。
|
2687
|
+
* @for Uploader
|
2688
|
+
* @example
|
2689
|
+
* uploader.reset();
|
2690
|
+
*/
|
2691
|
+
reset: function() {
|
2692
|
+
this.queue = new Queue();
|
2693
|
+
this.stats = this.queue.stats;
|
2694
|
+
}
|
2695
|
+
});
|
2696
|
+
|
2697
|
+
});
|
2698
|
+
/**
|
2699
|
+
* @fileOverview 添加获取Runtime相关信息的方法。
|
2700
|
+
*/
|
2701
|
+
define('widgets/runtime',[
|
2702
|
+
'uploader',
|
2703
|
+
'runtime/runtime',
|
2704
|
+
'widgets/widget'
|
2705
|
+
], function( Uploader, Runtime ) {
|
2706
|
+
|
2707
|
+
Uploader.support = function() {
|
2708
|
+
return Runtime.hasRuntime.apply( Runtime, arguments );
|
2709
|
+
};
|
2710
|
+
|
2711
|
+
return Uploader.register({
|
2712
|
+
'predict-runtime-type': 'predictRuntmeType'
|
2713
|
+
}, {
|
2714
|
+
|
2715
|
+
init: function() {
|
2716
|
+
if ( !this.predictRuntmeType() ) {
|
2717
|
+
throw Error('Runtime Error');
|
2718
|
+
}
|
2719
|
+
},
|
2720
|
+
|
2721
|
+
/**
|
2722
|
+
* 预测Uploader将采用哪个`Runtime`
|
2723
|
+
* @grammar predictRuntmeType() => String
|
2724
|
+
* @method predictRuntmeType
|
2725
|
+
* @for Uploader
|
2726
|
+
*/
|
2727
|
+
predictRuntmeType: function() {
|
2728
|
+
var orders = this.options.runtimeOrder || Runtime.orders,
|
2729
|
+
type = this.type,
|
2730
|
+
i, len;
|
2731
|
+
|
2732
|
+
if ( !type ) {
|
2733
|
+
orders = orders.split( /\s*,\s*/g );
|
2734
|
+
|
2735
|
+
for ( i = 0, len = orders.length; i < len; i++ ) {
|
2736
|
+
if ( Runtime.hasRuntime( orders[ i ] ) ) {
|
2737
|
+
this.type = type = orders[ i ];
|
2738
|
+
break;
|
2739
|
+
}
|
2740
|
+
}
|
2741
|
+
}
|
2742
|
+
|
2743
|
+
return type;
|
2744
|
+
}
|
2745
|
+
});
|
2746
|
+
});
|
2747
|
+
/**
|
2748
|
+
* @fileOverview Transport
|
2749
|
+
*/
|
2750
|
+
define('lib/transport',[
|
2751
|
+
'base',
|
2752
|
+
'runtime/client',
|
2753
|
+
'mediator'
|
2754
|
+
], function( Base, RuntimeClient, Mediator ) {
|
2755
|
+
|
2756
|
+
var $ = Base.$;
|
2757
|
+
|
2758
|
+
function Transport( opts ) {
|
2759
|
+
var me = this;
|
2760
|
+
|
2761
|
+
opts = me.options = $.extend( true, {}, Transport.options, opts || {} );
|
2762
|
+
RuntimeClient.call( this, 'Transport' );
|
2763
|
+
|
2764
|
+
this._blob = null;
|
2765
|
+
this._formData = opts.formData || {};
|
2766
|
+
this._headers = opts.headers || {};
|
2767
|
+
|
2768
|
+
this.on( 'progress', this._timeout );
|
2769
|
+
this.on( 'load error', function() {
|
2770
|
+
me.trigger( 'progress', 1 );
|
2771
|
+
clearTimeout( me._timer );
|
2772
|
+
});
|
2773
|
+
}
|
2774
|
+
|
2775
|
+
Transport.options = {
|
2776
|
+
server: '',
|
2777
|
+
method: 'POST',
|
2778
|
+
|
2779
|
+
// 跨域时,是否允许携带cookie, 只有html5 runtime才有效
|
2780
|
+
withCredentials: false,
|
2781
|
+
fileVal: 'file',
|
2782
|
+
timeout: 2 * 60 * 1000, // 2分钟
|
2783
|
+
formData: {},
|
2784
|
+
headers: {},
|
2785
|
+
sendAsBinary: false
|
2786
|
+
};
|
2787
|
+
|
2788
|
+
$.extend( Transport.prototype, {
|
2789
|
+
|
2790
|
+
// 添加Blob, 只能添加一次,最后一次有效。
|
2791
|
+
appendBlob: function( key, blob, filename ) {
|
2792
|
+
var me = this,
|
2793
|
+
opts = me.options;
|
2794
|
+
|
2795
|
+
if ( me.getRuid() ) {
|
2796
|
+
me.disconnectRuntime();
|
2797
|
+
}
|
2798
|
+
|
2799
|
+
// 连接到blob归属的同一个runtime.
|
2800
|
+
me.connectRuntime( blob.ruid, function() {
|
2801
|
+
me.exec('init');
|
2802
|
+
});
|
2803
|
+
|
2804
|
+
me._blob = blob;
|
2805
|
+
opts.fileVal = key || opts.fileVal;
|
2806
|
+
opts.filename = filename || opts.filename;
|
2807
|
+
},
|
2808
|
+
|
2809
|
+
// 添加其他字段
|
2810
|
+
append: function( key, value ) {
|
2811
|
+
if ( typeof key === 'object' ) {
|
2812
|
+
$.extend( this._formData, key );
|
2813
|
+
} else {
|
2814
|
+
this._formData[ key ] = value;
|
2815
|
+
}
|
2816
|
+
},
|
2817
|
+
|
2818
|
+
setRequestHeader: function( key, value ) {
|
2819
|
+
if ( typeof key === 'object' ) {
|
2820
|
+
$.extend( this._headers, key );
|
2821
|
+
} else {
|
2822
|
+
this._headers[ key ] = value;
|
2823
|
+
}
|
2824
|
+
},
|
2825
|
+
|
2826
|
+
send: function( method ) {
|
2827
|
+
this.exec( 'send', method );
|
2828
|
+
this._timeout();
|
2829
|
+
},
|
2830
|
+
|
2831
|
+
abort: function() {
|
2832
|
+
clearTimeout( this._timer );
|
2833
|
+
return this.exec('abort');
|
2834
|
+
},
|
2835
|
+
|
2836
|
+
destroy: function() {
|
2837
|
+
this.trigger('destroy');
|
2838
|
+
this.off();
|
2839
|
+
this.exec('destroy');
|
2840
|
+
this.disconnectRuntime();
|
2841
|
+
},
|
2842
|
+
|
2843
|
+
getResponse: function() {
|
2844
|
+
return this.exec('getResponse');
|
2845
|
+
},
|
2846
|
+
|
2847
|
+
getResponseAsJson: function() {
|
2848
|
+
return this.exec('getResponseAsJson');
|
2849
|
+
},
|
2850
|
+
|
2851
|
+
getStatus: function() {
|
2852
|
+
return this.exec('getStatus');
|
2853
|
+
},
|
2854
|
+
|
2855
|
+
_timeout: function() {
|
2856
|
+
var me = this,
|
2857
|
+
duration = me.options.timeout;
|
2858
|
+
|
2859
|
+
if ( !duration ) {
|
2860
|
+
return;
|
2861
|
+
}
|
2862
|
+
|
2863
|
+
clearTimeout( me._timer );
|
2864
|
+
me._timer = setTimeout(function() {
|
2865
|
+
me.abort();
|
2866
|
+
me.trigger( 'error', 'timeout' );
|
2867
|
+
}, duration );
|
2868
|
+
}
|
2869
|
+
|
2870
|
+
});
|
2871
|
+
|
2872
|
+
// 让Transport具备事件功能。
|
2873
|
+
Mediator.installTo( Transport.prototype );
|
2874
|
+
|
2875
|
+
return Transport;
|
2876
|
+
});
|
2877
|
+
/**
|
2878
|
+
* @fileOverview 负责文件上传相关。
|
2879
|
+
*/
|
2880
|
+
define('widgets/upload',[
|
2881
|
+
'base',
|
2882
|
+
'uploader',
|
2883
|
+
'file',
|
2884
|
+
'lib/transport',
|
2885
|
+
'widgets/widget'
|
2886
|
+
], function( Base, Uploader, WUFile, Transport ) {
|
2887
|
+
|
2888
|
+
var $ = Base.$,
|
2889
|
+
isPromise = Base.isPromise,
|
2890
|
+
Status = WUFile.Status;
|
2891
|
+
|
2892
|
+
// 添加默认配置项
|
2893
|
+
$.extend( Uploader.options, {
|
2894
|
+
|
2895
|
+
|
2896
|
+
/**
|
2897
|
+
* @property {Boolean} [prepareNextFile=false]
|
2898
|
+
* @namespace options
|
2899
|
+
* @for Uploader
|
2900
|
+
* @description 是否允许在文件传输时提前把下一个文件准备好。
|
2901
|
+
* 对于一个文件的准备工作比较耗时,比如图片压缩,md5序列化。
|
2902
|
+
* 如果能提前在当前文件传输期处理,可以节省总体耗时。
|
2903
|
+
*/
|
2904
|
+
prepareNextFile: false,
|
2905
|
+
|
2906
|
+
/**
|
2907
|
+
* @property {Boolean} [chunked=false]
|
2908
|
+
* @namespace options
|
2909
|
+
* @for Uploader
|
2910
|
+
* @description 是否要分片处理大文件上传。
|
2911
|
+
*/
|
2912
|
+
chunked: false,
|
2913
|
+
|
2914
|
+
/**
|
2915
|
+
* @property {Boolean} [chunkSize=5242880]
|
2916
|
+
* @namespace options
|
2917
|
+
* @for Uploader
|
2918
|
+
* @description 如果要分片,分多大一片? 默认大小为5M.
|
2919
|
+
*/
|
2920
|
+
chunkSize: 5 * 1024 * 1024,
|
2921
|
+
|
2922
|
+
/**
|
2923
|
+
* @property {Boolean} [chunkRetry=2]
|
2924
|
+
* @namespace options
|
2925
|
+
* @for Uploader
|
2926
|
+
* @description 如果某个分片由于网络问题出错,允许自动重传多少次?
|
2927
|
+
*/
|
2928
|
+
chunkRetry: 2,
|
2929
|
+
|
2930
|
+
/**
|
2931
|
+
* @property {Boolean} [threads=3]
|
2932
|
+
* @namespace options
|
2933
|
+
* @for Uploader
|
2934
|
+
* @description 上传并发数。允许同时最大上传进程数。
|
2935
|
+
*/
|
2936
|
+
threads: 3,
|
2937
|
+
|
2938
|
+
|
2939
|
+
/**
|
2940
|
+
* @property {Object} [formData]
|
2941
|
+
* @namespace options
|
2942
|
+
* @for Uploader
|
2943
|
+
* @description 文件上传请求的参数表,每次发送都会发送此对象中的参数。
|
2944
|
+
*/
|
2945
|
+
formData: null
|
2946
|
+
|
2947
|
+
/**
|
2948
|
+
* @property {Object} [fileVal='file']
|
2949
|
+
* @namespace options
|
2950
|
+
* @for Uploader
|
2951
|
+
* @description 设置文件上传域的name。
|
2952
|
+
*/
|
2953
|
+
|
2954
|
+
/**
|
2955
|
+
* @property {Object} [method='POST']
|
2956
|
+
* @namespace options
|
2957
|
+
* @for Uploader
|
2958
|
+
* @description 文件上传方式,`POST`或者`GET`。
|
2959
|
+
*/
|
2960
|
+
|
2961
|
+
/**
|
2962
|
+
* @property {Object} [sendAsBinary=false]
|
2963
|
+
* @namespace options
|
2964
|
+
* @for Uploader
|
2965
|
+
* @description 是否已二进制的流的方式发送文件,这样整个上传内容`php://input`都为文件内容,
|
2966
|
+
* 其他参数在$_GET数组中。
|
2967
|
+
*/
|
2968
|
+
});
|
2969
|
+
|
2970
|
+
// 负责将文件切片。
|
2971
|
+
function CuteFile( file, chunkSize ) {
|
2972
|
+
var pending = [],
|
2973
|
+
blob = file.source,
|
2974
|
+
total = blob.size,
|
2975
|
+
chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,
|
2976
|
+
start = 0,
|
2977
|
+
index = 0,
|
2978
|
+
len;
|
2979
|
+
|
2980
|
+
while ( index < chunks ) {
|
2981
|
+
len = Math.min( chunkSize, total - start );
|
2982
|
+
|
2983
|
+
pending.push({
|
2984
|
+
file: file,
|
2985
|
+
start: start,
|
2986
|
+
end: chunkSize ? (start + len) : total,
|
2987
|
+
total: total,
|
2988
|
+
chunks: chunks,
|
2989
|
+
chunk: index++
|
2990
|
+
});
|
2991
|
+
start += len;
|
2992
|
+
}
|
2993
|
+
|
2994
|
+
file.blocks = pending.concat();
|
2995
|
+
file.remaning = pending.length;
|
2996
|
+
|
2997
|
+
return {
|
2998
|
+
file: file,
|
2999
|
+
|
3000
|
+
has: function() {
|
3001
|
+
return !!pending.length;
|
3002
|
+
},
|
3003
|
+
|
3004
|
+
fetch: function() {
|
3005
|
+
return pending.shift();
|
3006
|
+
}
|
3007
|
+
};
|
3008
|
+
}
|
3009
|
+
|
3010
|
+
Uploader.register({
|
3011
|
+
'start-upload': 'start',
|
3012
|
+
'stop-upload': 'stop',
|
3013
|
+
'skip-file': 'skipFile',
|
3014
|
+
'is-in-progress': 'isInProgress'
|
3015
|
+
}, {
|
3016
|
+
|
3017
|
+
init: function() {
|
3018
|
+
var owner = this.owner;
|
3019
|
+
|
3020
|
+
this.runing = false;
|
3021
|
+
|
3022
|
+
// 记录当前正在传的数据,跟threads相关
|
3023
|
+
this.pool = [];
|
3024
|
+
|
3025
|
+
// 缓存即将上传的文件。
|
3026
|
+
this.pending = [];
|
3027
|
+
|
3028
|
+
// 跟踪还有多少分片没有完成上传。
|
3029
|
+
this.remaning = 0;
|
3030
|
+
this.__tick = Base.bindFn( this._tick, this );
|
3031
|
+
|
3032
|
+
owner.on( 'uploadComplete', function( file ) {
|
3033
|
+
// 把其他块取消了。
|
3034
|
+
file.blocks && $.each( file.blocks, function( _, v ) {
|
3035
|
+
v.transport && (v.transport.abort(), v.transport.destroy());
|
3036
|
+
delete v.transport;
|
3037
|
+
});
|
3038
|
+
|
3039
|
+
delete file.blocks;
|
3040
|
+
delete file.remaning;
|
3041
|
+
});
|
3042
|
+
},
|
3043
|
+
|
3044
|
+
/**
|
3045
|
+
* @event startUpload
|
3046
|
+
* @description 当开始上传流程时触发。
|
3047
|
+
* @for Uploader
|
3048
|
+
*/
|
3049
|
+
|
3050
|
+
/**
|
3051
|
+
* 开始上传。此方法可以从初始状态调用开始上传流程,也可以从暂停状态调用,继续上传流程。
|
3052
|
+
* @grammar upload() => undefined
|
3053
|
+
* @method upload
|
3054
|
+
* @for Uploader
|
3055
|
+
*/
|
3056
|
+
start: function() {
|
3057
|
+
var me = this;
|
3058
|
+
|
3059
|
+
// 移出invalid的文件
|
3060
|
+
$.each( me.request( 'get-files', Status.INVALID ), function() {
|
3061
|
+
me.request( 'remove-file', this );
|
3062
|
+
});
|
3063
|
+
|
3064
|
+
if ( me.runing ) {
|
3065
|
+
return;
|
3066
|
+
}
|
3067
|
+
|
3068
|
+
me.runing = true;
|
3069
|
+
|
3070
|
+
// 如果有暂停的,则续传
|
3071
|
+
$.each( me.pool, function( _, v ) {
|
3072
|
+
var file = v.file;
|
3073
|
+
|
3074
|
+
if ( file.getStatus() === Status.INTERRUPT ) {
|
3075
|
+
file.setStatus( Status.PROGRESS );
|
3076
|
+
me._trigged = false;
|
3077
|
+
v.transport && v.transport.send();
|
3078
|
+
}
|
3079
|
+
});
|
3080
|
+
|
3081
|
+
me._trigged = false;
|
3082
|
+
me.owner.trigger('startUpload');
|
3083
|
+
Base.nextTick( me.__tick );
|
3084
|
+
},
|
3085
|
+
|
3086
|
+
/**
|
3087
|
+
* @event stopUpload
|
3088
|
+
* @description 当开始上传流程暂停时触发。
|
3089
|
+
* @for Uploader
|
3090
|
+
*/
|
3091
|
+
|
3092
|
+
/**
|
3093
|
+
* 暂停上传。第一个参数为是否中断上传当前正在上传的文件。
|
3094
|
+
* @grammar stop() => undefined
|
3095
|
+
* @grammar stop( true ) => undefined
|
3096
|
+
* @method stop
|
3097
|
+
* @for Uploader
|
3098
|
+
*/
|
3099
|
+
stop: function( interrupt ) {
|
3100
|
+
var me = this;
|
3101
|
+
|
3102
|
+
if ( me.runing === false ) {
|
3103
|
+
return;
|
3104
|
+
}
|
3105
|
+
|
3106
|
+
me.runing = false;
|
3107
|
+
|
3108
|
+
interrupt && $.each( me.pool, function( _, v ) {
|
3109
|
+
v.transport && v.transport.abort();
|
3110
|
+
v.file.setStatus( Status.INTERRUPT );
|
3111
|
+
});
|
3112
|
+
|
3113
|
+
me.owner.trigger('stopUpload');
|
3114
|
+
},
|
3115
|
+
|
3116
|
+
/**
|
3117
|
+
* 判断`Uplaode`r是否正在上传中。
|
3118
|
+
* @grammar isInProgress() => Boolean
|
3119
|
+
* @method isInProgress
|
3120
|
+
* @for Uploader
|
3121
|
+
*/
|
3122
|
+
isInProgress: function() {
|
3123
|
+
return !!this.runing;
|
3124
|
+
},
|
3125
|
+
|
3126
|
+
getStats: function() {
|
3127
|
+
return this.request('get-stats');
|
3128
|
+
},
|
3129
|
+
|
3130
|
+
/**
|
3131
|
+
* 掉过一个文件上传,直接标记指定文件为已上传状态。
|
3132
|
+
* @grammar skipFile( file ) => undefined
|
3133
|
+
* @method skipFile
|
3134
|
+
* @for Uploader
|
3135
|
+
*/
|
3136
|
+
skipFile: function( file, status ) {
|
3137
|
+
file = this.request( 'get-file', file );
|
3138
|
+
|
3139
|
+
file.setStatus( status || Status.COMPLETE );
|
3140
|
+
file.skipped = true;
|
3141
|
+
|
3142
|
+
// 如果正在上传。
|
3143
|
+
file.blocks && $.each( file.blocks, function( _, v ) {
|
3144
|
+
var _tr = v.transport;
|
3145
|
+
|
3146
|
+
if ( _tr ) {
|
3147
|
+
_tr.abort();
|
3148
|
+
_tr.destroy();
|
3149
|
+
delete v.transport;
|
3150
|
+
}
|
3151
|
+
});
|
3152
|
+
|
3153
|
+
this.owner.trigger( 'uploadSkip', file );
|
3154
|
+
},
|
3155
|
+
|
3156
|
+
/**
|
3157
|
+
* @event uploadFinished
|
3158
|
+
* @description 当所有文件上传结束时触发。
|
3159
|
+
* @for Uploader
|
3160
|
+
*/
|
3161
|
+
_tick: function() {
|
3162
|
+
var me = this,
|
3163
|
+
opts = me.options,
|
3164
|
+
fn, val;
|
3165
|
+
|
3166
|
+
// 上一个promise还没有结束,则等待完成后再执行。
|
3167
|
+
if ( me._promise ) {
|
3168
|
+
return me._promise.always( me.__tick );
|
3169
|
+
}
|
3170
|
+
|
3171
|
+
// 还有位置,且还有文件要处理的话。
|
3172
|
+
if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {
|
3173
|
+
me._trigged = false;
|
3174
|
+
|
3175
|
+
fn = function( val ) {
|
3176
|
+
me._promise = null;
|
3177
|
+
|
3178
|
+
// 有可能是reject过来的,所以要检测val的类型。
|
3179
|
+
val && val.file && me._startSend( val );
|
3180
|
+
Base.nextTick( me.__tick );
|
3181
|
+
};
|
3182
|
+
|
3183
|
+
me._promise = isPromise( val ) ? val.always( fn ) : fn( val );
|
3184
|
+
|
3185
|
+
// 没有要上传的了,且没有正在传输的了。
|
3186
|
+
} else if ( !me.remaning && !me.getStats().numOfQueue ) {
|
3187
|
+
me.runing = false;
|
3188
|
+
|
3189
|
+
me._trigged || Base.nextTick(function() {
|
3190
|
+
me.owner.trigger('uploadFinished');
|
3191
|
+
});
|
3192
|
+
me._trigged = true;
|
3193
|
+
}
|
3194
|
+
},
|
3195
|
+
|
3196
|
+
_nextBlock: function() {
|
3197
|
+
var me = this,
|
3198
|
+
act = me._act,
|
3199
|
+
opts = me.options,
|
3200
|
+
next, done;
|
3201
|
+
|
3202
|
+
// 如果当前文件还有没有需要传输的,则直接返回剩下的。
|
3203
|
+
if ( act && act.has() &&
|
3204
|
+
act.file.getStatus() === Status.PROGRESS ) {
|
3205
|
+
|
3206
|
+
// 是否提前准备下一个文件
|
3207
|
+
if ( opts.prepareNextFile && !me.pending.length ) {
|
3208
|
+
me._prepareNextFile();
|
3209
|
+
}
|
3210
|
+
|
3211
|
+
return act.fetch();
|
3212
|
+
|
3213
|
+
// 否则,如果正在运行,则准备下一个文件,并等待完成后返回下个分片。
|
3214
|
+
} else if ( me.runing ) {
|
3215
|
+
|
3216
|
+
// 如果缓存中有,则直接在缓存中取,没有则去queue中取。
|
3217
|
+
if ( !me.pending.length && me.getStats().numOfQueue ) {
|
3218
|
+
me._prepareNextFile();
|
3219
|
+
}
|
3220
|
+
|
3221
|
+
next = me.pending.shift();
|
3222
|
+
done = function( file ) {
|
3223
|
+
if ( !file ) {
|
3224
|
+
return null;
|
3225
|
+
}
|
3226
|
+
|
3227
|
+
act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );
|
3228
|
+
me._act = act;
|
3229
|
+
return act.fetch();
|
3230
|
+
};
|
3231
|
+
|
3232
|
+
// 文件可能还在prepare中,也有可能已经完全准备好了。
|
3233
|
+
return isPromise( next ) ?
|
3234
|
+
next[ next.pipe ? 'pipe' : 'then']( done ) :
|
3235
|
+
done( next );
|
3236
|
+
}
|
3237
|
+
},
|
3238
|
+
|
3239
|
+
|
3240
|
+
/**
|
3241
|
+
* @event uploadStart
|
3242
|
+
* @param {File} file File对象
|
3243
|
+
* @description 某个文件开始上传前触发,一个文件只会触发一次。
|
3244
|
+
* @for Uploader
|
3245
|
+
*/
|
3246
|
+
_prepareNextFile: function() {
|
3247
|
+
var me = this,
|
3248
|
+
file = me.request('fetch-file'),
|
3249
|
+
pending = me.pending,
|
3250
|
+
promise;
|
3251
|
+
|
3252
|
+
if ( file ) {
|
3253
|
+
promise = me.request( 'before-send-file', file, function() {
|
3254
|
+
|
3255
|
+
// 有可能文件被skip掉了。文件被skip掉后,状态坑定不是Queued.
|
3256
|
+
if ( file.getStatus() === Status.QUEUED ) {
|
3257
|
+
me.owner.trigger( 'uploadStart', file );
|
3258
|
+
file.setStatus( Status.PROGRESS );
|
3259
|
+
return file;
|
3260
|
+
}
|
3261
|
+
|
3262
|
+
return me._finishFile( file );
|
3263
|
+
});
|
3264
|
+
|
3265
|
+
// 如果还在pending中,则替换成文件本身。
|
3266
|
+
promise.done(function() {
|
3267
|
+
var idx = $.inArray( promise, pending );
|
3268
|
+
|
3269
|
+
~idx && pending.splice( idx, 1, file );
|
3270
|
+
});
|
3271
|
+
|
3272
|
+
// befeore-send-file的钩子就有错误发生。
|
3273
|
+
promise.fail(function( reason ) {
|
3274
|
+
file.setStatus( Status.ERROR, reason );
|
3275
|
+
me.owner.trigger( 'uploadError', file, reason );
|
3276
|
+
me.owner.trigger( 'uploadComplete', file );
|
3277
|
+
});
|
3278
|
+
|
3279
|
+
pending.push( promise );
|
3280
|
+
}
|
3281
|
+
},
|
3282
|
+
|
3283
|
+
// 让出位置了,可以让其他分片开始上传
|
3284
|
+
_popBlock: function( block ) {
|
3285
|
+
var idx = $.inArray( block, this.pool );
|
3286
|
+
|
3287
|
+
this.pool.splice( idx, 1 );
|
3288
|
+
block.file.remaning--;
|
3289
|
+
this.remaning--;
|
3290
|
+
},
|
3291
|
+
|
3292
|
+
// 开始上传,可以被掉过。如果promise被reject了,则表示跳过此分片。
|
3293
|
+
_startSend: function( block ) {
|
3294
|
+
var me = this,
|
3295
|
+
file = block.file,
|
3296
|
+
promise;
|
3297
|
+
|
3298
|
+
me.pool.push( block );
|
3299
|
+
me.remaning++;
|
3300
|
+
|
3301
|
+
// 如果没有分片,则直接使用原始的。
|
3302
|
+
// 不会丢失content-type信息。
|
3303
|
+
block.blob = block.chunks === 1 ? file.source :
|
3304
|
+
file.source.slice( block.start, block.end );
|
3305
|
+
|
3306
|
+
// hook, 每个分片发送之前可能要做些异步的事情。
|
3307
|
+
promise = me.request( 'before-send', block, function() {
|
3308
|
+
|
3309
|
+
// 有可能文件已经上传出错了,所以不需要再传输了。
|
3310
|
+
if ( file.getStatus() === Status.PROGRESS ) {
|
3311
|
+
me._doSend( block );
|
3312
|
+
} else {
|
3313
|
+
me._popBlock( block );
|
3314
|
+
Base.nextTick( me.__tick );
|
3315
|
+
}
|
3316
|
+
});
|
3317
|
+
|
3318
|
+
// 如果为fail了,则跳过此分片。
|
3319
|
+
promise.fail(function() {
|
3320
|
+
if ( file.remaning === 1 ) {
|
3321
|
+
me._finishFile( file ).always(function() {
|
3322
|
+
block.percentage = 1;
|
3323
|
+
me._popBlock( block );
|
3324
|
+
me.owner.trigger( 'uploadComplete', file );
|
3325
|
+
Base.nextTick( me.__tick );
|
3326
|
+
});
|
3327
|
+
} else {
|
3328
|
+
block.percentage = 1;
|
3329
|
+
me._popBlock( block );
|
3330
|
+
Base.nextTick( me.__tick );
|
3331
|
+
}
|
3332
|
+
});
|
3333
|
+
},
|
3334
|
+
|
3335
|
+
|
3336
|
+
/**
|
3337
|
+
* @event uploadBeforeSend
|
3338
|
+
* @param {Object} object
|
3339
|
+
* @param {Object} data 默认的上传参数,可以扩展此对象来控制上传参数。
|
3340
|
+
* @description 当某个文件的分块在发送前触发,主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次。
|
3341
|
+
* @for Uploader
|
3342
|
+
*/
|
3343
|
+
|
3344
|
+
/**
|
3345
|
+
* @event uploadAccept
|
3346
|
+
* @param {Object} object
|
3347
|
+
* @param {Object} ret 服务端的返回数据,json格式,如果服务端不是json格式,从ret._raw中取数据,自行解析。
|
3348
|
+
* @description 当某个文件上传到服务端响应后,会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。
|
3349
|
+
* @for Uploader
|
3350
|
+
*/
|
3351
|
+
|
3352
|
+
/**
|
3353
|
+
* @event uploadProgress
|
3354
|
+
* @param {File} file File对象
|
3355
|
+
* @param {Number} percentage 上传进度
|
3356
|
+
* @description 上传过程中触发,携带上传进度。
|
3357
|
+
* @for Uploader
|
3358
|
+
*/
|
3359
|
+
|
3360
|
+
|
3361
|
+
/**
|
3362
|
+
* @event uploadError
|
3363
|
+
* @param {File} file File对象
|
3364
|
+
* @param {String} reason 出错的code
|
3365
|
+
* @description 当文件上传出错时触发。
|
3366
|
+
* @for Uploader
|
3367
|
+
*/
|
3368
|
+
|
3369
|
+
/**
|
3370
|
+
* @event uploadSuccess
|
3371
|
+
* @param {File} file File对象
|
3372
|
+
* @param {Object} response 服务端返回的数据
|
3373
|
+
* @description 当文件上传成功时触发。
|
3374
|
+
* @for Uploader
|
3375
|
+
*/
|
3376
|
+
|
3377
|
+
/**
|
3378
|
+
* @event uploadComplete
|
3379
|
+
* @param {File} [file] File对象
|
3380
|
+
* @description 不管成功或者失败,文件上传完成时触发。
|
3381
|
+
* @for Uploader
|
3382
|
+
*/
|
3383
|
+
|
3384
|
+
// 做上传操作。
|
3385
|
+
_doSend: function( block ) {
|
3386
|
+
var me = this,
|
3387
|
+
owner = me.owner,
|
3388
|
+
opts = me.options,
|
3389
|
+
file = block.file,
|
3390
|
+
tr = new Transport( opts ),
|
3391
|
+
data = $.extend({}, opts.formData ),
|
3392
|
+
headers = $.extend({}, opts.headers ),
|
3393
|
+
requestAccept, ret;
|
3394
|
+
|
3395
|
+
block.transport = tr;
|
3396
|
+
|
3397
|
+
tr.on( 'destroy', function() {
|
3398
|
+
delete block.transport;
|
3399
|
+
me._popBlock( block );
|
3400
|
+
Base.nextTick( me.__tick );
|
3401
|
+
});
|
3402
|
+
|
3403
|
+
// 广播上传进度。以文件为单位。
|
3404
|
+
tr.on( 'progress', function( percentage ) {
|
3405
|
+
var totalPercent = 0,
|
3406
|
+
uploaded = 0;
|
3407
|
+
|
3408
|
+
// 可能没有abort掉,progress还是执行进来了。
|
3409
|
+
// if ( !file.blocks ) {
|
3410
|
+
// return;
|
3411
|
+
// }
|
3412
|
+
|
3413
|
+
totalPercent = block.percentage = percentage;
|
3414
|
+
|
3415
|
+
if ( block.chunks > 1 ) { // 计算文件的整体速度。
|
3416
|
+
$.each( file.blocks, function( _, v ) {
|
3417
|
+
uploaded += (v.percentage || 0) * (v.end - v.start);
|
3418
|
+
});
|
3419
|
+
|
3420
|
+
totalPercent = uploaded / file.size;
|
3421
|
+
}
|
3422
|
+
|
3423
|
+
owner.trigger( 'uploadProgress', file, totalPercent || 0 );
|
3424
|
+
});
|
3425
|
+
|
3426
|
+
// 用来询问,是否返回的结果是有错误的。
|
3427
|
+
requestAccept = function( reject ) {
|
3428
|
+
var fn;
|
3429
|
+
|
3430
|
+
ret = tr.getResponseAsJson() || {};
|
3431
|
+
ret._raw = tr.getResponse();
|
3432
|
+
fn = function( value ) {
|
3433
|
+
reject = value;
|
3434
|
+
};
|
3435
|
+
|
3436
|
+
// 服务端响应了,不代表成功了,询问是否响应正确。
|
3437
|
+
if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {
|
3438
|
+
reject = reject || 'server';
|
3439
|
+
}
|
3440
|
+
|
3441
|
+
return reject;
|
3442
|
+
};
|
3443
|
+
|
3444
|
+
// 尝试重试,然后广播文件上传出错。
|
3445
|
+
tr.on( 'error', function( type, flag ) {
|
3446
|
+
block.retried = block.retried || 0;
|
3447
|
+
|
3448
|
+
// 自动重试
|
3449
|
+
if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&
|
3450
|
+
block.retried < opts.chunkRetry ) {
|
3451
|
+
|
3452
|
+
block.retried++;
|
3453
|
+
tr.send();
|
3454
|
+
|
3455
|
+
} else {
|
3456
|
+
|
3457
|
+
// http status 500 ~ 600
|
3458
|
+
if ( !flag && type === 'server' ) {
|
3459
|
+
type = requestAccept( type );
|
3460
|
+
}
|
3461
|
+
|
3462
|
+
file.setStatus( Status.ERROR, type );
|
3463
|
+
owner.trigger( 'uploadError', file, type );
|
3464
|
+
owner.trigger( 'uploadComplete', file );
|
3465
|
+
}
|
3466
|
+
});
|
3467
|
+
|
3468
|
+
// 上传成功
|
3469
|
+
tr.on( 'load', function() {
|
3470
|
+
var reason;
|
3471
|
+
|
3472
|
+
// 如果非预期,转向上传出错。
|
3473
|
+
if ( (reason = requestAccept()) ) {
|
3474
|
+
tr.trigger( 'error', reason, true );
|
3475
|
+
return;
|
3476
|
+
}
|
3477
|
+
|
3478
|
+
// 全部上传完成。
|
3479
|
+
if ( file.remaning === 1 ) {
|
3480
|
+
me._finishFile( file, ret );
|
3481
|
+
} else {
|
3482
|
+
tr.destroy();
|
3483
|
+
}
|
3484
|
+
});
|
3485
|
+
|
3486
|
+
// 配置默认的上传字段。
|
3487
|
+
data = $.extend( data, {
|
3488
|
+
id: file.id,
|
3489
|
+
name: file.name,
|
3490
|
+
type: file.type,
|
3491
|
+
lastModifiedDate: file.lastModifiedDate,
|
3492
|
+
size: file.size
|
3493
|
+
});
|
3494
|
+
|
3495
|
+
block.chunks > 1 && $.extend( data, {
|
3496
|
+
chunks: block.chunks,
|
3497
|
+
chunk: block.chunk
|
3498
|
+
});
|
3499
|
+
|
3500
|
+
// 在发送之间可以添加字段什么的。。。
|
3501
|
+
// 如果默认的字段不够使用,可以通过监听此事件来扩展
|
3502
|
+
owner.trigger( 'uploadBeforeSend', block, data, headers );
|
3503
|
+
|
3504
|
+
// 开始发送。
|
3505
|
+
tr.appendBlob( opts.fileVal, block.blob, file.name );
|
3506
|
+
tr.append( data );
|
3507
|
+
tr.setRequestHeader( headers );
|
3508
|
+
tr.send();
|
3509
|
+
},
|
3510
|
+
|
3511
|
+
// 完成上传。
|
3512
|
+
_finishFile: function( file, ret, hds ) {
|
3513
|
+
var owner = this.owner;
|
3514
|
+
|
3515
|
+
return owner
|
3516
|
+
.request( 'after-send-file', arguments, function() {
|
3517
|
+
file.setStatus( Status.COMPLETE );
|
3518
|
+
owner.trigger( 'uploadSuccess', file, ret, hds );
|
3519
|
+
})
|
3520
|
+
.fail(function( reason ) {
|
3521
|
+
|
3522
|
+
// 如果外部已经标记为invalid什么的,不再改状态。
|
3523
|
+
if ( file.getStatus() === Status.PROGRESS ) {
|
3524
|
+
file.setStatus( Status.ERROR, reason );
|
3525
|
+
}
|
3526
|
+
|
3527
|
+
owner.trigger( 'uploadError', file, reason );
|
3528
|
+
})
|
3529
|
+
.always(function() {
|
3530
|
+
owner.trigger( 'uploadComplete', file );
|
3531
|
+
});
|
3532
|
+
}
|
3533
|
+
|
3534
|
+
});
|
3535
|
+
});
|
3536
|
+
/**
|
3537
|
+
* @fileOverview 各种验证,包括文件总大小是否超出、单文件是否超出和文件是否重复。
|
3538
|
+
*/
|
3539
|
+
|
3540
|
+
define('widgets/validator',[
|
3541
|
+
'base',
|
3542
|
+
'uploader',
|
3543
|
+
'file',
|
3544
|
+
'widgets/widget'
|
3545
|
+
], function( Base, Uploader, WUFile ) {
|
3546
|
+
|
3547
|
+
var $ = Base.$,
|
3548
|
+
validators = {},
|
3549
|
+
api;
|
3550
|
+
|
3551
|
+
/**
|
3552
|
+
* @event error
|
3553
|
+
* @param {String} type 错误类型。
|
3554
|
+
* @description 当validate不通过时,会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误,目前有以下错误会在特定的情况下派送错来。
|
3555
|
+
*
|
3556
|
+
* * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。
|
3557
|
+
* * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。
|
3558
|
+
* @for Uploader
|
3559
|
+
*/
|
3560
|
+
|
3561
|
+
// 暴露给外面的api
|
3562
|
+
api = {
|
3563
|
+
|
3564
|
+
// 添加验证器
|
3565
|
+
addValidator: function( type, cb ) {
|
3566
|
+
validators[ type ] = cb;
|
3567
|
+
},
|
3568
|
+
|
3569
|
+
// 移除验证器
|
3570
|
+
removeValidator: function( type ) {
|
3571
|
+
delete validators[ type ];
|
3572
|
+
}
|
3573
|
+
};
|
3574
|
+
|
3575
|
+
// 在Uploader初始化的时候启动Validators的初始化
|
3576
|
+
Uploader.register({
|
3577
|
+
init: function() {
|
3578
|
+
var me = this;
|
3579
|
+
$.each( validators, function() {
|
3580
|
+
this.call( me.owner );
|
3581
|
+
});
|
3582
|
+
}
|
3583
|
+
});
|
3584
|
+
|
3585
|
+
/**
|
3586
|
+
* @property {int} [fileNumLimit=undefined]
|
3587
|
+
* @namespace options
|
3588
|
+
* @for Uploader
|
3589
|
+
* @description 验证文件总数量, 超出则不允许加入队列。
|
3590
|
+
*/
|
3591
|
+
api.addValidator( 'fileNumLimit', function() {
|
3592
|
+
var uploader = this,
|
3593
|
+
opts = uploader.options,
|
3594
|
+
count = 0,
|
3595
|
+
max = opts.fileNumLimit >> 0,
|
3596
|
+
flag = true;
|
3597
|
+
|
3598
|
+
if ( !max ) {
|
3599
|
+
return;
|
3600
|
+
}
|
3601
|
+
|
3602
|
+
uploader.on( 'beforeFileQueued', function( file ) {
|
3603
|
+
|
3604
|
+
if ( count >= max && flag ) {
|
3605
|
+
flag = false;
|
3606
|
+
this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );
|
3607
|
+
setTimeout(function() {
|
3608
|
+
flag = true;
|
3609
|
+
}, 1 );
|
3610
|
+
}
|
3611
|
+
|
3612
|
+
return count >= max ? false : true;
|
3613
|
+
});
|
3614
|
+
|
3615
|
+
uploader.on( 'fileQueued', function() {
|
3616
|
+
count++;
|
3617
|
+
});
|
3618
|
+
|
3619
|
+
uploader.on( 'fileDequeued', function() {
|
3620
|
+
count--;
|
3621
|
+
});
|
3622
|
+
|
3623
|
+
uploader.on( 'uploadFinished', function() {
|
3624
|
+
count = 0;
|
3625
|
+
});
|
3626
|
+
});
|
3627
|
+
|
3628
|
+
|
3629
|
+
/**
|
3630
|
+
* @property {int} [fileSizeLimit=undefined]
|
3631
|
+
* @namespace options
|
3632
|
+
* @for Uploader
|
3633
|
+
* @description 验证文件总大小是否超出限制, 超出则不允许加入队列。
|
3634
|
+
*/
|
3635
|
+
api.addValidator( 'fileSizeLimit', function() {
|
3636
|
+
var uploader = this,
|
3637
|
+
opts = uploader.options,
|
3638
|
+
count = 0,
|
3639
|
+
max = opts.fileSizeLimit >> 0,
|
3640
|
+
flag = true;
|
3641
|
+
|
3642
|
+
if ( !max ) {
|
3643
|
+
return;
|
3644
|
+
}
|
3645
|
+
|
3646
|
+
uploader.on( 'beforeFileQueued', function( file ) {
|
3647
|
+
var invalid = count + file.size > max;
|
3648
|
+
|
3649
|
+
if ( invalid && flag ) {
|
3650
|
+
flag = false;
|
3651
|
+
this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );
|
3652
|
+
setTimeout(function() {
|
3653
|
+
flag = true;
|
3654
|
+
}, 1 );
|
3655
|
+
}
|
3656
|
+
|
3657
|
+
return invalid ? false : true;
|
3658
|
+
});
|
3659
|
+
|
3660
|
+
uploader.on( 'fileQueued', function( file ) {
|
3661
|
+
count += file.size;
|
3662
|
+
});
|
3663
|
+
|
3664
|
+
uploader.on( 'fileDequeued', function( file ) {
|
3665
|
+
count -= file.size;
|
3666
|
+
});
|
3667
|
+
|
3668
|
+
uploader.on( 'uploadFinished', function() {
|
3669
|
+
count = 0;
|
3670
|
+
});
|
3671
|
+
});
|
3672
|
+
|
3673
|
+
/**
|
3674
|
+
* @property {int} [fileSingleSizeLimit=undefined]
|
3675
|
+
* @namespace options
|
3676
|
+
* @for Uploader
|
3677
|
+
* @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。
|
3678
|
+
*/
|
3679
|
+
api.addValidator( 'fileSingleSizeLimit', function() {
|
3680
|
+
var uploader = this,
|
3681
|
+
opts = uploader.options,
|
3682
|
+
max = opts.fileSingleSizeLimit;
|
3683
|
+
|
3684
|
+
if ( !max ) {
|
3685
|
+
return;
|
3686
|
+
}
|
3687
|
+
|
3688
|
+
uploader.on( 'beforeFileQueued', function( file ) {
|
3689
|
+
|
3690
|
+
if ( file.size > max ) {
|
3691
|
+
file.setStatus( WUFile.Status.INVALID, 'exceed_size' );
|
3692
|
+
this.trigger( 'error', 'F_EXCEED_SIZE', file );
|
3693
|
+
return false;
|
3694
|
+
}
|
3695
|
+
|
3696
|
+
});
|
3697
|
+
|
3698
|
+
});
|
3699
|
+
|
3700
|
+
/**
|
3701
|
+
* @property {int} [duplicate=undefined]
|
3702
|
+
* @namespace options
|
3703
|
+
* @for Uploader
|
3704
|
+
* @description 去重, 根据文件名字、文件大小和最后修改时间来生成hash Key.
|
3705
|
+
*/
|
3706
|
+
api.addValidator( 'duplicate', function() {
|
3707
|
+
var uploader = this,
|
3708
|
+
opts = uploader.options,
|
3709
|
+
mapping = {};
|
3710
|
+
|
3711
|
+
if ( opts.duplicate ) {
|
3712
|
+
return;
|
3713
|
+
}
|
3714
|
+
|
3715
|
+
function hashString( str ) {
|
3716
|
+
var hash = 0,
|
3717
|
+
i = 0,
|
3718
|
+
len = str.length,
|
3719
|
+
_char;
|
3720
|
+
|
3721
|
+
for ( ; i < len; i++ ) {
|
3722
|
+
_char = str.charCodeAt( i );
|
3723
|
+
hash = _char + (hash << 6) + (hash << 16) - hash;
|
3724
|
+
}
|
3725
|
+
|
3726
|
+
return hash;
|
3727
|
+
}
|
3728
|
+
|
3729
|
+
uploader.on( 'beforeFileQueued', function( file ) {
|
3730
|
+
var hash = file.__hash || (file.__hash = hashString( file.name +
|
3731
|
+
file.size + file.lastModifiedDate ));
|
3732
|
+
|
3733
|
+
// 已经重复了
|
3734
|
+
if ( mapping[ hash ] ) {
|
3735
|
+
this.trigger( 'error', 'F_DUPLICATE', file );
|
3736
|
+
return false;
|
3737
|
+
}
|
3738
|
+
});
|
3739
|
+
|
3740
|
+
uploader.on( 'fileQueued', function( file ) {
|
3741
|
+
var hash = file.__hash;
|
3742
|
+
|
3743
|
+
hash && (mapping[ hash ] = true);
|
3744
|
+
});
|
3745
|
+
|
3746
|
+
uploader.on( 'fileDequeued', function( file ) {
|
3747
|
+
var hash = file.__hash;
|
3748
|
+
|
3749
|
+
hash && (delete mapping[ hash ]);
|
3750
|
+
});
|
3751
|
+
});
|
3752
|
+
|
3753
|
+
return api;
|
3754
|
+
});
|
3755
|
+
|
3756
|
+
/**
|
3757
|
+
* @fileOverview Runtime管理器,负责Runtime的选择, 连接
|
3758
|
+
*/
|
3759
|
+
define('runtime/compbase',[],function() {
|
3760
|
+
|
3761
|
+
function CompBase( owner, runtime ) {
|
3762
|
+
|
3763
|
+
this.owner = owner;
|
3764
|
+
this.options = owner.options;
|
3765
|
+
|
3766
|
+
this.getRuntime = function() {
|
3767
|
+
return runtime;
|
3768
|
+
};
|
3769
|
+
|
3770
|
+
this.getRuid = function() {
|
3771
|
+
return runtime.uid;
|
3772
|
+
};
|
3773
|
+
|
3774
|
+
this.trigger = function() {
|
3775
|
+
return owner.trigger.apply( owner, arguments );
|
3776
|
+
};
|
3777
|
+
}
|
3778
|
+
|
3779
|
+
return CompBase;
|
3780
|
+
});
|
3781
|
+
/**
|
3782
|
+
* @fileOverview FlashRuntime
|
3783
|
+
*/
|
3784
|
+
define('runtime/flash/runtime',[
|
3785
|
+
'base',
|
3786
|
+
'runtime/runtime',
|
3787
|
+
'runtime/compbase'
|
3788
|
+
], function( Base, Runtime, CompBase ) {
|
3789
|
+
|
3790
|
+
var $ = Base.$,
|
3791
|
+
type = 'flash',
|
3792
|
+
components = {};
|
3793
|
+
|
3794
|
+
|
3795
|
+
function getFlashVersion() {
|
3796
|
+
var version;
|
3797
|
+
|
3798
|
+
try {
|
3799
|
+
version = navigator.plugins[ 'Shockwave Flash' ];
|
3800
|
+
version = version.description;
|
3801
|
+
} catch ( ex ) {
|
3802
|
+
try {
|
3803
|
+
version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')
|
3804
|
+
.GetVariable('$version');
|
3805
|
+
} catch ( ex2 ) {
|
3806
|
+
version = '0.0';
|
3807
|
+
}
|
3808
|
+
}
|
3809
|
+
version = version.match( /\d+/g );
|
3810
|
+
return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );
|
3811
|
+
}
|
3812
|
+
|
3813
|
+
function FlashRuntime() {
|
3814
|
+
var pool = {},
|
3815
|
+
clients = {},
|
3816
|
+
destory = this.destory,
|
3817
|
+
me = this,
|
3818
|
+
jsreciver = Base.guid('webuploader_');
|
3819
|
+
|
3820
|
+
Runtime.apply( me, arguments );
|
3821
|
+
me.type = type;
|
3822
|
+
|
3823
|
+
|
3824
|
+
// 这个方法的调用者,实际上是RuntimeClient
|
3825
|
+
me.exec = function( comp, fn/*, args...*/ ) {
|
3826
|
+
var client = this,
|
3827
|
+
uid = client.uid,
|
3828
|
+
args = Base.slice( arguments, 2 ),
|
3829
|
+
instance;
|
3830
|
+
|
3831
|
+
clients[ uid ] = client;
|
3832
|
+
|
3833
|
+
if ( components[ comp ] ) {
|
3834
|
+
if ( !pool[ uid ] ) {
|
3835
|
+
pool[ uid ] = new components[ comp ]( client, me );
|
3836
|
+
}
|
3837
|
+
|
3838
|
+
instance = pool[ uid ];
|
3839
|
+
|
3840
|
+
if ( instance[ fn ] ) {
|
3841
|
+
return instance[ fn ].apply( instance, args );
|
3842
|
+
}
|
3843
|
+
}
|
3844
|
+
|
3845
|
+
return me.flashExec.apply( client, arguments );
|
3846
|
+
};
|
3847
|
+
|
3848
|
+
function handler( evt, obj ) {
|
3849
|
+
var type = evt.type || evt,
|
3850
|
+
parts, uid;
|
3851
|
+
|
3852
|
+
parts = type.split('::');
|
3853
|
+
uid = parts[ 0 ];
|
3854
|
+
type = parts[ 1 ];
|
3855
|
+
|
3856
|
+
// console.log.apply( console, arguments );
|
3857
|
+
|
3858
|
+
if ( type === 'Ready' && uid === me.uid ) {
|
3859
|
+
me.trigger('ready');
|
3860
|
+
} else if ( clients[ uid ] ) {
|
3861
|
+
clients[ uid ].trigger( type.toLowerCase(), evt, obj );
|
3862
|
+
}
|
3863
|
+
|
3864
|
+
// Base.log( evt, obj );
|
3865
|
+
}
|
3866
|
+
|
3867
|
+
// flash的接受器。
|
3868
|
+
window[ jsreciver ] = function() {
|
3869
|
+
var args = arguments;
|
3870
|
+
|
3871
|
+
// 为了能捕获得到。
|
3872
|
+
setTimeout(function() {
|
3873
|
+
handler.apply( null, args );
|
3874
|
+
}, 1 );
|
3875
|
+
};
|
3876
|
+
|
3877
|
+
this.jsreciver = jsreciver;
|
3878
|
+
|
3879
|
+
this.destory = function() {
|
3880
|
+
// @todo 删除池子中的所有实例
|
3881
|
+
return destory && destory.apply( this, arguments );
|
3882
|
+
};
|
3883
|
+
|
3884
|
+
this.flashExec = function( comp, fn ) {
|
3885
|
+
var flash = me.getFlash(),
|
3886
|
+
args = Base.slice( arguments, 2 );
|
3887
|
+
|
3888
|
+
return flash.exec( this.uid, comp, fn, args );
|
3889
|
+
};
|
3890
|
+
|
3891
|
+
// @todo
|
3892
|
+
}
|
3893
|
+
|
3894
|
+
Base.inherits( Runtime, {
|
3895
|
+
constructor: FlashRuntime,
|
3896
|
+
|
3897
|
+
init: function() {
|
3898
|
+
var container = this.getContainer(),
|
3899
|
+
opts = this.options,
|
3900
|
+
html;
|
3901
|
+
|
3902
|
+
// if not the minimal height, shims are not initialized
|
3903
|
+
// in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)
|
3904
|
+
container.css({
|
3905
|
+
position: 'absolute',
|
3906
|
+
top: '-8px',
|
3907
|
+
left: '-8px',
|
3908
|
+
width: '9px',
|
3909
|
+
height: '9px',
|
3910
|
+
overflow: 'hidden'
|
3911
|
+
});
|
3912
|
+
|
3913
|
+
// insert flash object
|
3914
|
+
html = '<object id="' + this.uid + '" type="application/' +
|
3915
|
+
'x-shockwave-flash" data="' + opts.swf + '" ';
|
3916
|
+
|
3917
|
+
if ( Base.browser.ie ) {
|
3918
|
+
html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
|
3919
|
+
}
|
3920
|
+
|
3921
|
+
html += 'width="100%" height="100%" style="outline:0">' +
|
3922
|
+
'<param name="movie" value="' + opts.swf + '" />' +
|
3923
|
+
'<param name="flashvars" value="uid=' + this.uid +
|
3924
|
+
'&jsreciver=' + this.jsreciver + '" />' +
|
3925
|
+
'<param name="wmode" value="transparent" />' +
|
3926
|
+
'<param name="allowscriptaccess" value="always" />' +
|
3927
|
+
'</object>';
|
3928
|
+
|
3929
|
+
container.html( html );
|
3930
|
+
},
|
3931
|
+
|
3932
|
+
getFlash: function() {
|
3933
|
+
if ( this._flash ) {
|
3934
|
+
return this._flash;
|
3935
|
+
}
|
3936
|
+
|
3937
|
+
this._flash = $( '#' + this.uid ).get( 0 );
|
3938
|
+
return this._flash;
|
3939
|
+
}
|
3940
|
+
|
3941
|
+
});
|
3942
|
+
|
3943
|
+
FlashRuntime.register = function( name, component ) {
|
3944
|
+
component = components[ name ] = Base.inherits( CompBase, $.extend({
|
3945
|
+
|
3946
|
+
// @todo fix this later
|
3947
|
+
flashExec: function() {
|
3948
|
+
var owner = this.owner,
|
3949
|
+
runtime = this.getRuntime();
|
3950
|
+
|
3951
|
+
return runtime.flashExec.apply( owner, arguments );
|
3952
|
+
}
|
3953
|
+
}, component ) );
|
3954
|
+
|
3955
|
+
return component;
|
3956
|
+
};
|
3957
|
+
|
3958
|
+
if ( getFlashVersion() >= 11.4 ) {
|
3959
|
+
Runtime.addRuntime( type, FlashRuntime );
|
3960
|
+
}
|
3961
|
+
|
3962
|
+
return FlashRuntime;
|
3963
|
+
});
|
3964
|
+
/**
|
3965
|
+
* @fileOverview FilePicker
|
3966
|
+
*/
|
3967
|
+
define('runtime/flash/filepicker',[
|
3968
|
+
'base',
|
3969
|
+
'runtime/flash/runtime'
|
3970
|
+
], function( Base, FlashRuntime ) {
|
3971
|
+
var $ = Base.$;
|
3972
|
+
|
3973
|
+
return FlashRuntime.register( 'FilePicker', {
|
3974
|
+
init: function( opts ) {
|
3975
|
+
var copy = $.extend({}, opts ),
|
3976
|
+
len, i;
|
3977
|
+
|
3978
|
+
// 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.
|
3979
|
+
len = copy.accept && copy.accept.length;
|
3980
|
+
for ( i = 0; i < len; i++ ) {
|
3981
|
+
if ( !copy.accept[ i ].title ) {
|
3982
|
+
copy.accept[ i ].title = 'Files';
|
3983
|
+
}
|
3984
|
+
}
|
3985
|
+
|
3986
|
+
delete copy.button;
|
3987
|
+
delete copy.container;
|
3988
|
+
|
3989
|
+
this.flashExec( 'FilePicker', 'init', copy );
|
3990
|
+
},
|
3991
|
+
|
3992
|
+
destroy: function() {
|
3993
|
+
// todo
|
3994
|
+
}
|
3995
|
+
});
|
3996
|
+
});
|
3997
|
+
/**
|
3998
|
+
* @fileOverview 图片压缩
|
3999
|
+
*/
|
4000
|
+
define('runtime/flash/image',[
|
4001
|
+
'runtime/flash/runtime'
|
4002
|
+
], function( FlashRuntime ) {
|
4003
|
+
|
4004
|
+
return FlashRuntime.register( 'Image', {
|
4005
|
+
// init: function( options ) {
|
4006
|
+
// var owner = this.owner;
|
4007
|
+
|
4008
|
+
// this.flashExec( 'Image', 'init', options );
|
4009
|
+
// owner.on( 'load', function() {
|
4010
|
+
// debugger;
|
4011
|
+
// });
|
4012
|
+
// },
|
4013
|
+
|
4014
|
+
loadFromBlob: function( blob ) {
|
4015
|
+
var owner = this.owner;
|
4016
|
+
|
4017
|
+
owner.info() && this.flashExec( 'Image', 'info', owner.info() );
|
4018
|
+
owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );
|
4019
|
+
|
4020
|
+
this.flashExec( 'Image', 'loadFromBlob', blob.uid );
|
4021
|
+
}
|
4022
|
+
});
|
4023
|
+
});
|
4024
|
+
/**
|
4025
|
+
* @fileOverview Transport flash实现
|
4026
|
+
*/
|
4027
|
+
define('runtime/flash/transport',[
|
4028
|
+
'base',
|
4029
|
+
'runtime/flash/runtime',
|
4030
|
+
'runtime/client'
|
4031
|
+
], function( Base, FlashRuntime, RuntimeClient ) {
|
4032
|
+
var $ = Base.$;
|
4033
|
+
|
4034
|
+
return FlashRuntime.register( 'Transport', {
|
4035
|
+
init: function() {
|
4036
|
+
this._status = 0;
|
4037
|
+
this._response = null;
|
4038
|
+
this._responseJson = null;
|
4039
|
+
},
|
4040
|
+
|
4041
|
+
send: function() {
|
4042
|
+
var owner = this.owner,
|
4043
|
+
opts = this.options,
|
4044
|
+
xhr = this._initAjax(),
|
4045
|
+
blob = owner._blob,
|
4046
|
+
server = opts.server,
|
4047
|
+
binary;
|
4048
|
+
|
4049
|
+
xhr.connectRuntime( blob.ruid );
|
4050
|
+
|
4051
|
+
if ( opts.sendAsBinary ) {
|
4052
|
+
server += (/\?/.test( server ) ? '&' : '?') +
|
4053
|
+
$.param( owner._formData );
|
4054
|
+
|
4055
|
+
binary = blob.uid;
|
4056
|
+
} else {
|
4057
|
+
$.each( owner._formData, function( k, v ) {
|
4058
|
+
xhr.exec( 'append', k, v );
|
4059
|
+
});
|
4060
|
+
|
4061
|
+
xhr.exec( 'appendBlob', opts.fileVal, blob.uid,
|
4062
|
+
opts.filename || owner._formData.name || '' );
|
4063
|
+
}
|
4064
|
+
|
4065
|
+
this._setRequestHeader( xhr, opts.headers );
|
4066
|
+
xhr.exec( 'send', {
|
4067
|
+
method: opts.method,
|
4068
|
+
url: server
|
4069
|
+
}, binary );
|
4070
|
+
},
|
4071
|
+
|
4072
|
+
getStatus: function() {
|
4073
|
+
return this._status;
|
4074
|
+
},
|
4075
|
+
|
4076
|
+
getResponse: function() {
|
4077
|
+
return this._response;
|
4078
|
+
},
|
4079
|
+
|
4080
|
+
getResponseAsJson: function() {
|
4081
|
+
return this._responseJson;
|
4082
|
+
},
|
4083
|
+
|
4084
|
+
abort: function() {
|
4085
|
+
var xhr = this._xhr;
|
4086
|
+
|
4087
|
+
if ( xhr ) {
|
4088
|
+
xhr.exec('abort');
|
4089
|
+
xhr.destroy();
|
4090
|
+
this._xhr = xhr = null;
|
4091
|
+
}
|
4092
|
+
},
|
4093
|
+
|
4094
|
+
destroy: function() {
|
4095
|
+
this.abort();
|
4096
|
+
},
|
4097
|
+
|
4098
|
+
_initAjax: function() {
|
4099
|
+
var me = this,
|
4100
|
+
xhr = new RuntimeClient('XMLHttpRequest');
|
4101
|
+
|
4102
|
+
xhr.on( 'uploadprogress progress', function( e ) {
|
4103
|
+
return me.trigger( 'progress', e.loaded / e.total );
|
4104
|
+
});
|
4105
|
+
|
4106
|
+
xhr.on( 'load', function() {
|
4107
|
+
var status = xhr.exec('getStatus'),
|
4108
|
+
err = '';
|
4109
|
+
|
4110
|
+
xhr.off();
|
4111
|
+
me._xhr = null;
|
4112
|
+
|
4113
|
+
if ( status >= 200 && status < 300 ) {
|
4114
|
+
me._response = xhr.exec('getResponse');
|
4115
|
+
me._responseJson = xhr.exec('getResponseAsJson');
|
4116
|
+
} else if ( status >= 500 && status < 600 ) {
|
4117
|
+
me._response = xhr.exec('getResponse');
|
4118
|
+
me._responseJson = xhr.exec('getResponseAsJson');
|
4119
|
+
err = 'server';
|
4120
|
+
} else {
|
4121
|
+
err = 'http';
|
4122
|
+
}
|
4123
|
+
|
4124
|
+
xhr.destroy();
|
4125
|
+
xhr = null;
|
4126
|
+
|
4127
|
+
return err ? me.trigger( 'error', err ) : me.trigger('load');
|
4128
|
+
});
|
4129
|
+
|
4130
|
+
xhr.on( 'error', function() {
|
4131
|
+
xhr.off();
|
4132
|
+
me._xhr = null;
|
4133
|
+
me.trigger( 'error', 'http' );
|
4134
|
+
});
|
4135
|
+
|
4136
|
+
me._xhr = xhr;
|
4137
|
+
return xhr;
|
4138
|
+
},
|
4139
|
+
|
4140
|
+
_setRequestHeader: function( xhr, headers ) {
|
4141
|
+
$.each( headers, function( key, val ) {
|
4142
|
+
xhr.exec( 'setRequestHeader', key, val );
|
4143
|
+
});
|
4144
|
+
}
|
4145
|
+
});
|
4146
|
+
});
|
4147
|
+
/**
|
4148
|
+
* @fileOverview 只有flash实现的文件版本。
|
4149
|
+
*/
|
4150
|
+
define('preset/flashonly',[
|
4151
|
+
'base',
|
4152
|
+
|
4153
|
+
// widgets
|
4154
|
+
'widgets/filepicker',
|
4155
|
+
'widgets/image',
|
4156
|
+
'widgets/queue',
|
4157
|
+
'widgets/runtime',
|
4158
|
+
'widgets/upload',
|
4159
|
+
'widgets/validator',
|
4160
|
+
|
4161
|
+
// runtimes
|
4162
|
+
|
4163
|
+
// flash
|
4164
|
+
'runtime/flash/filepicker',
|
4165
|
+
'runtime/flash/image',
|
4166
|
+
'runtime/flash/transport'
|
4167
|
+
], function( Base ) {
|
4168
|
+
return Base;
|
4169
|
+
});
|
4170
|
+
define('webuploader',[
|
4171
|
+
'preset/flashonly'
|
4172
|
+
], function( preset ) {
|
4173
|
+
return preset;
|
4174
|
+
});
|
4175
|
+
return require('webuploader');
|
4176
|
+
});
|