init.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. jQuery(function() {
  2. var $ = jQuery;
  3. $.fn.webupload_fileinput = function (config) {
  4. $('body').append(renderModal());
  5. var _modal = $('#' + config['modal_id']),
  6. chooseObject; // 点击选择图片的按钮
  7. _modal.on("shown.bs.modal", init);
  8. function init () {
  9. var $wrap = $('#uploader');
  10. // 图片容器
  11. if($("ul.filelist").length>0)
  12. {
  13. $queue = $("ul.filelist");
  14. }
  15. else
  16. {
  17. $queue = $('<ul class="filelist"></ul>').appendTo( $wrap.find('.queueList') );
  18. }
  19. // 状态栏,包括进度和控制按钮
  20. $statusBar = $wrap.find('.statusBar'),
  21. // 文件总体选择信息。
  22. $info = $statusBar.find('.info'),
  23. // 上传按钮
  24. $upload = $wrap.find('.uploadBtn'),
  25. // 没选择文件之前的内容。
  26. $placeHolder = $wrap.find('.placeholder'),
  27. // 总体进度条
  28. $progress = $statusBar.find('.progress').hide(),
  29. // 添加的文件数量
  30. fileCount = 0,
  31. // 添加的文件总大小
  32. fileSize = 0,
  33. // 优化retina, 在retina下这个值是2
  34. ratio = window.devicePixelRatio || 1,
  35. // 缩略图大小
  36. thumbnailWidth = 110 * ratio,
  37. thumbnailHeight = 110 * ratio,
  38. // 可能有pedding, ready, uploading, confirm, done.
  39. state = 'pedding',
  40. // 所有文件的进度信息,key为file id
  41. percentages = {},
  42. supportTransition = (function(){
  43. var s = document.createElement('p').style,
  44. r = 'transition' in s ||
  45. 'WebkitTransition' in s ||
  46. 'MozTransition' in s ||
  47. 'msTransition' in s ||
  48. 'OTransition' in s;
  49. s = null;
  50. return r;
  51. })(),
  52. uploadedFiles = [], // 成功上传的图片信息
  53. k = 0,
  54. $r = config.uploadType==1?$('<li class="fileinput-button js-add-image" id="filePicker2" style="display:none;"> <a href="javascript:;" class="fileinput-button-icon">+</a></li>').appendTo($wrap.find('.filelist')):$('<li class="fileinput-button js-add-image add-multi-file" id="filePicker2" style="display:none;"> <a href="javascript:;" class="fileinput-button-icon">+</a></li>').appendTo($wrap.find('.filelist')),
  55. // WebUploader实例
  56. uploader;
  57. if(config.uploadType!=1)$wrap.addClass('uploader2');
  58. if ( !WebUploader.Uploader.support() ) {
  59. alert( 'Web Uploader 不支持您的浏览器!如果你使用的是IE浏览器,请尝试升级 flash 播放器');
  60. throw new Error( 'WebUploader does not support the browser you are using.' );
  61. }
  62. if (config.compress == undefined) {
  63. config.compress = {};
  64. }
  65. // 实例化
  66. uploader = WebUploader.create({
  67. pick: {
  68. id: '#filePicker',
  69. label: config.uploadType==1?'点击选择图片':'点击选择文件',
  70. multiple: config.pick.multiple
  71. },
  72. dnd: '#uploader .queueList',
  73. paste: document.body,
  74. accept: config.accept,
  75. swf: './webuploader/Uploader.swf',
  76. server: config.server,
  77. formData: config.formData,
  78. disableGlobalDnd: config.disableGlobalDnd,
  79. chunked: config.chunked,
  80. fileNumLimit: config.pick.multiple ? config.fileNumLimit : 1,
  81. fileSizeLimit: config.fileSizeLimit,
  82. fileSingleSizeLimit: config.fileSingleSizeLimit,
  83. compress: config.compress
  84. /*compress: {
  85. width: config.compress.width,
  86. height: config.compress.height,
  87. quality: config.compress.quality,
  88. allowMagnify: config.compress.allowMagnify,
  89. crop: config.compress.crop,
  90. preserveHeaders: config.compress.preserveHeaders,
  91. noCompressIfLarger: config.compress.noCompressIfLarger,
  92. compressSize: config.compress.compressSize
  93. }*/
  94. });
  95. // 添加“添加文件”的按钮,
  96. uploader.addButton({
  97. id: '#filePicker2',
  98. label: '+',
  99. multiple: config.pick.multiple
  100. });
  101. // 当有文件添加进来时执行,负责view的创建
  102. function addFile( file ) {
  103. if(config.uploadType==1)
  104. {
  105. var $li = $( '<li id="' + file.id + '">' +
  106. '<p class="title">' + file.name + '</p>' +
  107. '<p class="imgWrap"></p>'+
  108. '</li>' ),
  109. $btns = $('<div class="file-panel">' +
  110. '<span class="cancel">删除</span>' +
  111. '<span class="rotateRight">向右旋转</span>' +
  112. '<span class="rotateLeft">向左旋转</span></div>').appendTo( $li ),
  113. $prgress = $li.find('p.progress span'),
  114. $wrap = $li.find( 'p.imgWrap' ),
  115. $info = $('<p class="error"></p>'),
  116. showError = function( code ) {
  117. switch( code ) {
  118. case 'exceed_size':
  119. text = '文件大小超出';
  120. break;
  121. case 'interrupt':
  122. text = '上传暂停';
  123. break;
  124. default:
  125. text = '上传失败,请重试';
  126. break;
  127. }
  128. $info.text( text ).appendTo( $li );
  129. };
  130. }
  131. else
  132. {
  133. var $li = $( '<li id="' + file.id + '" class="uploadbox-fileunit">' +
  134. '<p class="title file-icon-'+file.ext+'">' + file.name + '</p></li>' ),
  135. $btns = $('<div class="file-panel">' +
  136. '<span class="cancel">删除</span></div>').appendTo( $li ),
  137. $prgress = $li.find('p.progress span'),
  138. $info = $('<p class="error"></p>'),
  139. showError = function( code ) {
  140. switch( code ) {
  141. case 'exceed_size':
  142. text = '文件大小超出';
  143. break;
  144. case 'interrupt':
  145. text = '上传暂停';
  146. break;
  147. default:
  148. text = '上传失败,请重试';
  149. break;
  150. }
  151. $info.text( text ).appendTo( $li );
  152. };
  153. }
  154. if ( file.getStatus() === 'invalid' ) {
  155. showError( file.statusText );
  156. } else {
  157. if(config.uploadType==1)//只有图片生成预览
  158. {
  159. // @todo lazyload
  160. $wrap.text( '预览中' );
  161. uploader.makeThumb( file, function( error, src ) {
  162. if ( error ) {
  163. $wrap.text( '不能预览' );
  164. return;
  165. }
  166. var img = $('<img src="'+src+'">');
  167. $wrap.empty().append( img );
  168. }, thumbnailWidth, thumbnailHeight );
  169. }
  170. percentages[ file.id ] = [ file.size, 0 ];
  171. file.rotation = 0;
  172. }
  173. //文件状态变化
  174. file.on('statuschange', function( cur, prev ) {
  175. if ( prev === 'progress' ) {
  176. $prgress.hide().width(0);
  177. } else if ( prev === 'queued' ) {
  178. $li.off( 'mouseenter mouseleave' );
  179. $btns.remove();
  180. }
  181. // 成功
  182. if ( cur === 'error' || cur === 'invalid' ) {
  183. showError( file.statusText );
  184. percentages[ file.id ][ 1 ] = 1;
  185. } else if ( cur === 'interrupt' ) {
  186. showError( 'interrupt' );
  187. } else if ( cur === 'queued' ) {
  188. percentages[ file.id ][ 1 ] = 0;
  189. } else if ( cur === 'progress' ) {
  190. $info.remove();
  191. $prgress.css('display', 'block');
  192. } else if ( cur === 'complete' ) {
  193. $li.append( '<span class="success"></span>' );
  194. }
  195. $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );
  196. });
  197. $li.on( 'mouseenter', function() {
  198. $btns.stop().animate({height: 30});
  199. });
  200. $li.on( 'mouseleave', function() {
  201. $btns.stop().animate({height: 0});
  202. });
  203. $btns.on( 'click', 'span', function() {
  204. var index = $(this).index(),
  205. deg;
  206. switch ( index ) {
  207. case 0:
  208. uploader.removeFile( file );
  209. return;
  210. case 1:
  211. file.rotation += 90;
  212. break;
  213. case 2:
  214. file.rotation -= 90;
  215. break;
  216. }
  217. if ( supportTransition ) {
  218. deg = 'rotate(' + file.rotation + 'deg)';
  219. $wrap.css({
  220. '-webkit-transform': deg,
  221. '-mos-transform': deg,
  222. '-o-transform': deg,
  223. 'transform': deg
  224. });
  225. } else {
  226. $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');
  227. }
  228. });
  229. config.pick.multiple && $r.find(".fileinput-button").show(), $li.insertBefore($('#filePicker2'));
  230. // $li.appendTo( $queue );
  231. }
  232. // 负责view的销毁
  233. function removeFile( file ) {
  234. var $li = $('#'+file.id);
  235. delete percentages[ file.id ];
  236. updateTotalProgress();
  237. $li.off().find('.file-panel').off().end().remove();
  238. }
  239. function resetUploader() {
  240. uploadedFiles = [];
  241. k = 0;
  242. }
  243. function updateTotalProgress() {
  244. var loaded = 0,
  245. total = 0,
  246. spans = $progress.children(),
  247. percent;
  248. $.each( percentages, function( k, v ) {
  249. total += v[ 0 ];
  250. loaded += v[ 0 ] * v[ 1 ];
  251. } );
  252. percent = total ? loaded / total : 0;
  253. spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );
  254. spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );
  255. updateStatus();
  256. }
  257. function updateStatus() {
  258. var title = config.uploadType==1?['张','图片','张图片']:['个','文件','个文件'];
  259. var text = '', stats;
  260. if ( state === 'ready' ) {
  261. text = '选中' + fileCount + title[2] +',共' +
  262. WebUploader.formatSize( fileSize ) + '。';
  263. } else if ( state === 'confirm' ) {
  264. stats = uploader.getStats();
  265. if ( stats.uploadFailNum ) {
  266. text = '已成功上传' + stats.successNum+ title[2] +','+
  267. stats.uploadFailNum + title[2] +'上传失败,<a class="retry" href="#">重新上传</a>失败'+title[1]+'或<a class="ignore" href="#">忽略</a>'
  268. }
  269. } else {
  270. stats = uploader.getStats();
  271. text = '共' + fileCount + title[0] +'(' +
  272. WebUploader.formatSize( fileSize ) +
  273. '),已上传' + stats.successNum + title[0];
  274. if ( stats.uploadFailNum ) {
  275. text += ',失败' + stats.uploadFailNum + title[0];
  276. }
  277. }
  278. $info.html( text );
  279. }
  280. function setState( val ) {
  281. var file, stats;
  282. if ( val === state ) {
  283. return;
  284. }
  285. $upload.removeClass( 'state-' + state );
  286. $upload.addClass( 'state-' + val );
  287. state = val;
  288. switch ( state ) {
  289. case 'pedding':
  290. $placeHolder.removeClass( 'element-invisible' );
  291. $queue.parent().removeClass('filled');
  292. $queue.hide();
  293. $statusBar.addClass( 'element-invisible' );
  294. uploader.refresh();
  295. $r.hide();
  296. break;
  297. case 'ready':
  298. $placeHolder.addClass( 'element-invisible' );
  299. $( '#filePicker2' ).removeClass( 'element-invisible');
  300. $queue.parent().addClass('filled');
  301. $queue.show();
  302. $statusBar.removeClass('element-invisible');
  303. uploader.refresh();
  304. config.pick.multiple && $r.show();
  305. break;
  306. case 'uploading':
  307. $( '#filePicker2' ).addClass( 'element-invisible' );
  308. $progress.show();
  309. $upload.text( '暂停上传' );
  310. break;
  311. case 'paused':
  312. $progress.show();
  313. $upload.text( '继续上传' );
  314. break;
  315. case 'confirm':
  316. $progress.hide();
  317. $upload.text( '开始上传' ).addClass( 'disabled' );
  318. stats = uploader.getStats();
  319. if ( stats.successNum && !stats.uploadFailNum ) {
  320. setState( 'finish' );
  321. return;
  322. }
  323. break;
  324. case 'finish':
  325. stats = uploader.getStats();
  326. if ( stats.successNum ) {
  327. if (uploadedFiles.length > 0) {
  328. if (!config.pick.multiple) {
  329. uploadedFiles = uploadedFiles[0];
  330. if (uploadedFiles.code == 0) {
  331. if(config.uploadType==1)
  332. {
  333. var btn = chooseObject,
  334. ipt = btn.parent().prev().find("input").eq(0),
  335. val = ipt.val(),
  336. img = ipt.parent().parent().next().children();
  337. if(img.length > 0){
  338. img.get(0).src = uploadedFiles.url;
  339. }
  340. ipt.val(uploadedFiles.attachment);
  341. }
  342. else
  343. {
  344. var btn = chooseObject,
  345. ipt = btn.parent().prev().find("input").eq(0),
  346. val = ipt.val();
  347. ipt.val(uploadedFiles.attachment);
  348. var htmlStr = '<div class="uploader-file-item"><div class="uploader-unit-file-name">'+basename(uploadedFiles.name)+'</div><em class="close delMultiFile" title="删除">x</em></div>';
  349. btn.parent().parent().next().html('').append(htmlStr);
  350. }
  351. } else {
  352. alert(uploadedFiles.msg);
  353. }
  354. } else {
  355. var name = chooseObject.parent().prev().attr('name');
  356. var multierr = false;
  357. $.each(uploadedFiles, function(idx, url) {
  358. if (url.code == 0) {
  359. if(config.uploadType==1)
  360. {
  361. chooseObject.parent().parent().next().append('<div class="multi-item"><img src="'+url.url+'" class="img-responsive img-thumbnail cus-img"><input type="hidden" name="'+name+'[]" value="'+url.attachment+'"><em class="close delMultiImage" title="删除这张图片">×</em></div>');
  362. }
  363. else
  364. {
  365. var htmlStr = '<div class="uploader-file-item"><div class="uploader-unit-file-name">'+basename(url.name)+'</div><input type="hidden" name="'+name+'[]" value="'+url.attachment+'"><em class="close delMultiFile" title="删除">x</em></div>';
  366. chooseObject.parent().parent().next().append(htmlStr);
  367. }
  368. } else {
  369. if (!multierr) {
  370. multierr = true;
  371. alert(url.msg);
  372. } else {
  373. console.log(url.msg);
  374. }
  375. }
  376. });
  377. }
  378. _modal.modal('hide');
  379. resetUploader();
  380. }
  381. } else {
  382. // 没有成功的图片,重设
  383. state = 'done';
  384. location.reload();
  385. }
  386. break;
  387. }
  388. updateStatus();
  389. }
  390. uploader.onUploadProgress = function( file, percentage ) {
  391. var $li = $('#'+file.id),
  392. $percent = $li.find('.progress span');
  393. $percent.css( 'width', percentage * 100 + '%' );
  394. percentages[ file.id ][ 1 ] = percentage;
  395. updateTotalProgress();
  396. };
  397. uploader.onFileQueued = function( file ) {
  398. fileCount++;
  399. fileSize += file.size;
  400. if ( fileCount === 1 ) {
  401. $placeHolder.addClass( 'element-invisible' );
  402. $statusBar.show();
  403. }
  404. addFile( file );
  405. setState( 'ready' );
  406. updateTotalProgress();
  407. };
  408. uploader.onFileDequeued = function( file ) {
  409. fileCount--;
  410. fileSize -= file.size;
  411. if ( !fileCount ) {
  412. setState( 'pedding' );
  413. }
  414. removeFile( file );
  415. updateTotalProgress();
  416. };
  417. uploader.on( 'all', function( type ) {
  418. var stats;
  419. switch( type ) {
  420. case 'uploadFinished':
  421. setState( 'confirm' );
  422. break;
  423. case 'startUpload':
  424. setState( 'uploading' );
  425. break;
  426. case 'stopUpload':
  427. setState( 'paused' );
  428. break;
  429. }
  430. });
  431. uploader.onError = function( code ) {
  432. var msg = code;
  433. switch (code) {
  434. case 'Q_EXCEED_NUM_LIMIT':
  435. msg = '添加的文件数量超出 fileNumLimit 的设置';
  436. break;
  437. case 'Q_EXCEED_SIZE_LIMIT':
  438. msg = '添加的文件总大小超出了 fileSizeLimit 的设置';
  439. break;
  440. case 'Q_TYPE_DENIED':
  441. msg = '添加的文件类型错误';
  442. break;
  443. case 'P_DUPLICATE':
  444. msg = '添加的文件重复了';
  445. break;
  446. }
  447. alert( 'Error: ' + msg );
  448. };
  449. uploader.onUploadSuccess = function (b, c) {
  450. return (k++, uploadedFiles.push(c))
  451. }
  452. $upload.on('click', function() {
  453. if ( $(this).hasClass( 'disabled' ) ) {
  454. return false;
  455. }
  456. if ( state === 'ready' ) {
  457. uploader.upload();
  458. } else if ( state === 'paused' ) {
  459. uploader.upload();
  460. } else if ( state === 'uploading' ) {
  461. uploader.stop();
  462. }
  463. });
  464. $info.on( 'click', '.retry', function() {
  465. uploader.retry();
  466. } );
  467. $info.on( 'click', '.ignore', function() {
  468. alert( 'todo' );
  469. } );
  470. $upload.addClass( 'state-' + state );
  471. updateTotalProgress();
  472. $('#filePicker2').mouseenter(function(){
  473. uploader.refresh();
  474. });;
  475. }
  476. function buildModalBody () {
  477. var title = config['uploadType']==1?['图片','张']:['文件','个'];
  478. return '<div role="tabpanel" class="tab-pane upload active" id="upload">' +
  479. '<div id="uploader" class="uploader">' +
  480. '<div class="queueList">' +
  481. '<div id="dndArea" class="placeholder">' +
  482. '<div id="filePicker"></div>' +
  483. '<p id="">或将'+title[0]+'拖到这里</p>' +
  484. ' </div>' +
  485. '</div>' +
  486. '<div class="statusBar">' +
  487. '<div class="infowrap">' +
  488. '<div class="progress" style="display: none;">' +
  489. '<span class="text">0%</span>' +
  490. '<span class="percentage" style="width: 0%;"></span>' +
  491. '</div>' +
  492. '<div class="info">共0'+title[1]+'(0B),已上传0'+title[1]+'</div>' +
  493. '<div class="accept"></div>' +
  494. '</div>' +
  495. '<div class="btns">' +
  496. '<div class="uploadBtn btn btn-primary state-pedding" style="margin-top: 2px;">确定使用</div>' +
  497. '<div class="modal-button-upload" style="float: right; margin-left: 5px;">' +
  498. '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>' +
  499. '</div>' +
  500. '</div>' +
  501. '</div>' +
  502. '</div>' +
  503. '</div>';
  504. }
  505. function renderModal () {
  506. var title = config['uploadType']==1?'上传图片':'上传文件';
  507. var modal_id = config['modal_id'];
  508. if ($('#' + modal_id).length == 0) {
  509. return '<div id="' + config['modal_id'] + '" class="modal fade '+($('#mymodal').length>0?'uploadModal':'')+'" role="dialog" tabindex="-1" style="z-index:999999">' +
  510. '<div class="modal-dialog modal-lg cus-size">' +
  511. '<div class="modal-content">' +
  512. '<div class="modal-header">' +
  513. '<h5 class="modal-title">'+title+'</h5>' +
  514. '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>' +
  515. '</div>' +
  516. '<div class="modal-body">' +
  517. '</div>' +
  518. '</div>' +
  519. '</div>' +
  520. '</div>';
  521. } else {
  522. return false;
  523. }
  524. }
  525. function basename(str) {
  526. var idx = str.lastIndexOf('/')
  527. idx = idx > -1 ? idx : str.lastIndexOf('\\')
  528. if (idx < 0) {
  529. return str
  530. }
  531. return str.substring(idx + 1);
  532. }
  533. // =====================================================================================
  534. $('.' + config['modal_id']).on('click', function () {
  535. chooseObject = $(this);
  536. _modal.modal('show');
  537. _modal.find('.modal-body').html('');
  538. _modal.find('.modal-body').html(buildModalBody());
  539. });
  540. $(document).on('click', '.delImage', function () {
  541. var _this = $(this);
  542. console.log(config);
  543. _this.prev().attr("src", config.defaultImage);
  544. _this.parent().prev().find("input").val("");
  545. });
  546. $(document).on('click', '.delImage6', function () {
  547. var _this = $(this);
  548. _this.prev().attr("src", "");
  549. //console.log(config);
  550. //console.log(_this.parent().parent().parent().prev().find("input").val());
  551. _this.parent().parent().parent().prev().find("input").val("");
  552. _this.parent().hide();
  553. });
  554. $(document).on('click', '.delImage3', function () {
  555. var _this = $(this);
  556. _this.prev().attr("src", "");
  557. //console.log(config);
  558. //console.log(_this.parent().parent().parent().prev().find("input").val());
  559. _this.parent().parent().parent().prev().find("input").val("");
  560. _this.parent().hide();
  561. });
  562. $(document).on('click', '.delFile', function () {
  563. var _this = $(this);
  564. _this.parent().parent().prev().find("input").val("");
  565. _this.parent().remove();
  566. });
  567. $(document).on('click', '.delMultiImage', function () {
  568. $(this).parent().remove();
  569. });
  570. $(document).on('click', '.delMultiFile', function () {
  571. $(this).parent().remove();
  572. });
  573. // 解决多modal下滚动以及filePicker失效问题
  574. $(document).on('hidden.bs.modal', '.modal', function () {
  575. if($('.modal:visible').length) {
  576. $(document.body).addClass('modal-open');
  577. }
  578. $('.modal-c').find('.modal-body').html('');
  579. });
  580. };
  581. });