demo2.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. (function( $ ){
  2. // 当domReady的时候开始初始化
  3. $(function() {
  4. var $wrap = $('#uploader'),
  5. // 图片容器
  6. $queue = $( '<ul class="filelist"></ul>' )
  7. .appendTo( $wrap.find( '.queueList' ) ),
  8. // 状态栏,包括进度和控制按钮
  9. $statusBar = $wrap.find( '.statusBar' ),
  10. // 文件总体选择信息。
  11. $info = $statusBar.find( '.info' ),
  12. // 上传按钮
  13. $upload = $wrap.find( '.uploadBtn' ),
  14. // 没选择文件之前的内容。
  15. $placeHolder = $wrap.find( '.placeholder' ),
  16. $progress = $statusBar.find( '.progress' ).hide(),
  17. // 添加的文件数量
  18. fileCount = 0,
  19. // 添加的文件总大小
  20. fileSize = 0,
  21. // 优化retina, 在retina下这个值是2
  22. ratio = window.devicePixelRatio || 1,
  23. // 缩略图大小
  24. thumbnailWidth = 110 * ratio,
  25. thumbnailHeight = 110 * ratio,
  26. // 可能有pedding, ready, uploading, confirm, done.
  27. state = 'pedding',
  28. // 所有文件的进度信息,key为file id
  29. percentages = {},
  30. // WebUploader实例
  31. uploader;
  32. // 实例化
  33. uploader = WebUploader.create({
  34. pick: '#filePicker',
  35. dnd: '#dndArea',
  36. paste: '#uploader',
  37. server: '../server/fileupload2.php',
  38. accept: '',
  39. fileNumLimit: 300,
  40. fileSizeLimit: 0,
  41. fileSingleSizeLimit: 512 * 1024 * 1024 // 512 M
  42. });
  43. // 添加“添加文件”的按钮,
  44. uploader.addButton('#filePicker2');
  45. // 当有文件添加进来时执行,负责view的创建
  46. function addFile( file ) {
  47. var $li = $( '<li id="' + file.id + '">' +
  48. '<p class="title">' + file.name + '</p>' +
  49. '<p class="imgWrap"></p>'+
  50. '<p class="progress"><span></span></p>' +
  51. '</li>' ),
  52. $btns = $('<div class="file-panel">' +
  53. '<span class="cancel">删除</span>' +
  54. '<span class="rotateRight">向右旋转</span>' +
  55. '<span class="rotateLeft">向左旋转</span></div>').appendTo( $li ),
  56. $prgress = $li.find('p.progress span'),
  57. $wrap = $li.find( 'p.imgWrap' ),
  58. $info = $('<p class="error"></p>'),
  59. showError = function( code ) {
  60. switch( code ) {
  61. case 'exceed_size':
  62. text = '文件大小超出';
  63. break;
  64. default:
  65. text = '上传失败,请重试';
  66. break;
  67. }
  68. $info.text( text ).appendTo( $li );
  69. };
  70. if ( file.getStatus() === 'invalid' ) {
  71. showError( file.statusText );
  72. } else {
  73. // @todo lazyload
  74. $wrap.text( '预览中' );
  75. uploader.makeThumb( file, function( error, src ) {
  76. if ( error ) {
  77. $wrap.text( '不能预览' );
  78. return;
  79. }
  80. var img = $('<img src="'+src+'">');
  81. $wrap.empty().append( img );
  82. }, thumbnailWidth, thumbnailHeight );
  83. percentages[ file.id ] = [ file.size, 0 ];
  84. file.ratation = 0;
  85. }
  86. file.on('statuschange', function( cur, prev ) {
  87. if ( prev === 'progress' ) {
  88. $prgress.hide().width(0);
  89. } else if ( prev === 'queued' ) {
  90. $li.off( 'mouseenter mouseleave' );
  91. $btns.remove();
  92. }
  93. // 成功
  94. if ( cur === 'error' || cur === 'invalid' ) {
  95. showError( file.statusText );
  96. percentages[ file.id ][ 1 ] = 1;
  97. } else if ( cur === 'queued' ) {
  98. percentages[ file.id ][ 1 ] = 0;
  99. } else if ( cur === 'progress' ) {
  100. $info.remove();
  101. $prgress.css('display', 'block');
  102. }
  103. $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );
  104. });
  105. $li.on( 'mouseenter', function() {
  106. $btns.stop().animate({height: 30});
  107. });
  108. $li.on( 'mouseleave', function() {
  109. $btns.stop().animate({height: 0});
  110. });
  111. $btns.on( 'click', 'span', function() {
  112. var index = $(this).index(),
  113. deg;
  114. switch ( index ) {
  115. case 0:
  116. uploader.removeFile( file );
  117. return;
  118. case 1:
  119. file.ratation += 90;
  120. break;
  121. case 2:
  122. file.ratation -= 90;
  123. break;
  124. }
  125. // -webkit-transform: rotate(90deg);
  126. index && (deg = 'rotate(' + file.ratation + 'deg)', $wrap.css({
  127. '-webkit-transform': deg,
  128. '-mos-transform': deg,
  129. '-o-transform': deg,
  130. 'transform': deg
  131. }));
  132. });
  133. $li.appendTo( $queue );
  134. }
  135. // 负责view的销毁
  136. function removeFile( file ) {
  137. var $li = $('#'+file.id);
  138. delete percentages[ file.id ];
  139. updateTotalProgress();
  140. $li.off().find('.file-panel').off().end().remove();
  141. }
  142. function updateTotalProgress() {
  143. var loaded = 0,
  144. total = 0,
  145. spans = $progress.children(),
  146. percent;
  147. $.each( percentages, function( k, v ) {
  148. total += v[ 0 ];
  149. loaded += v[ 0 ] * v[ 1 ];
  150. } );
  151. percent = total ? loaded / total : 0;
  152. spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );
  153. spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );
  154. updateStatus();
  155. }
  156. function updateStatus() {
  157. var text = '', stats;
  158. if ( state === 'ready' ) {
  159. text = '选中' + fileCount + '张图片,共' +
  160. uploader.formatSize( fileSize ) + '。';
  161. } else if ( state === 'confirm' ) {
  162. stats = uploader.getStats();
  163. if ( stats.uploadFailNum ) {
  164. text = '已成功上传' + stats.successNum+ '张照片至XX相册,'+
  165. stats.uploadFailNum + '张照片上传失败,<a class="retry" href="#">重新上传</a>失败图片或<a class="ignore" href="#">忽略</a>'
  166. }
  167. } else {
  168. stats = uploader.getStats();
  169. text = '共' + fileCount + '张(' +
  170. uploader.formatSize( fileSize ) +
  171. '),已上传' + stats.successNum + '张';
  172. if ( stats.uploadFailNum ) {
  173. text += ',失败' + stats.uploadFailNum + '张';
  174. }
  175. }
  176. $info.html( text );
  177. }
  178. function setState( val ) {
  179. var file, stats;
  180. if ( val === state ) {
  181. return;
  182. }
  183. $upload.removeClass( 'state-' + state );
  184. $upload.addClass( 'state-' + val );
  185. state = val;
  186. switch ( state ) {
  187. case 'pedding':
  188. $placeHolder.show();
  189. $queue.hide();
  190. $statusBar.hide();
  191. break;
  192. case 'ready':
  193. $placeHolder.hide();
  194. $( '#filePicker2' ).show();
  195. $queue.show();
  196. $statusBar.show();
  197. break;
  198. case 'uploading':
  199. $( '#filePicker2' ).hide();
  200. $progress.show();
  201. $upload.text( '暂停上传' );
  202. break;
  203. case 'paused':
  204. $progress.show();
  205. $upload.text( '继续上传' );
  206. break;
  207. case 'confirm':
  208. $progress.hide();
  209. $upload.text( '开始上传' ).addClass( 'disabled' );
  210. stats = uploader.getStats();
  211. if ( stats.successNum && !stats.uploadFailNum ) {
  212. setState( 'finish' );
  213. return;
  214. }
  215. break;
  216. case 'finish':
  217. stats = uploader.getStats();
  218. if ( stats.successNum ) {
  219. alert( '上传成功' );
  220. } else {
  221. // 没有成功的图片,重设
  222. state = 'done';
  223. location.reload();
  224. }
  225. break;
  226. }
  227. updateStatus();
  228. }
  229. uploader.onUploadBeforeSend = function( file, data ) {
  230. data.md5 = file.md5 || '';
  231. };
  232. uploader.onUploadProgress = function( file, percentage ) {
  233. var $li = $('#'+file.id),
  234. $percent = $li.find('.progress span');
  235. $percent.css( 'width', percentage * 100 + '%' );
  236. percentages[ file.id ][ 1 ] = percentage;
  237. updateTotalProgress();
  238. };
  239. uploader.onFileQueued = function( file ) {
  240. var start = Date.now();
  241. fileCount++;
  242. fileSize += file.size;
  243. if ( fileCount === 1 ) {
  244. $placeHolder.hide();
  245. $statusBar.show();
  246. }
  247. Md5File( file, function( value ) {
  248. var $li = $('#'+file.id);
  249. file.md5 = value;
  250. console.log( value );
  251. $li.append( '<p class="log">md5:' + ((Date.now() - start)/1000).toFixed(2) + '秒</p>')
  252. });
  253. addFile( file );
  254. setState( 'ready' );
  255. updateTotalProgress();
  256. };
  257. uploader.onFileDequeued = function( file ) {
  258. fileCount--;
  259. fileSize -= file.size;
  260. if ( !fileCount ) {
  261. setState( 'pedding' );
  262. }
  263. removeFile( file );
  264. updateTotalProgress();
  265. };
  266. uploader.on( 'all', function( type ) {
  267. var stats;
  268. switch( type ) {
  269. case 'uploadFinished':
  270. setState( 'confirm' );
  271. break;
  272. case 'startUpload':
  273. setState( 'uploading' );
  274. break;
  275. case 'stopUpload':
  276. setState( 'paused' );
  277. break;
  278. }
  279. });
  280. uploader.onError = function( code ) {
  281. alert( 'Eroor: ' + code );
  282. };
  283. uploader.onUploadChunkcontinue = function( file, ret ) {
  284. if ( ret.exist ) {
  285. var $li = $( '#'+file.id );
  286. $li.append( '<p class="log">跳过' + uploader.formatSize( file.size - file.loaded ) + '</p>' );
  287. return false;
  288. }
  289. };
  290. $upload.on('click', function() {
  291. if ( $(this).hasClass( 'disabled' ) ) {
  292. return false;
  293. }
  294. if ( state === 'ready' ) {
  295. uploader.upload();
  296. } else if ( state === 'paused' ) {
  297. uploader.upload();
  298. } else if ( state === 'uploading' ) {
  299. uploader.stop();
  300. }
  301. });
  302. $info.on( 'click', '.retry', function() {
  303. uploader.retry();
  304. } );
  305. $info.on( 'click', '.ignore', function() {
  306. alert( 'todo' );
  307. } );
  308. $upload.addClass( 'state-' + state );
  309. updateTotalProgress();
  310. var Md5File = (function(){
  311. return function( file, cb ) {
  312. var worker = new Worker( 'hashFile.js' );
  313. worker.onmessage = function( e ) {
  314. cb( e.data, file );
  315. worker.terminate();
  316. };
  317. worker.postMessage( file.source );
  318. }
  319. })();
  320. });
  321. })( jQuery );