upload_ui.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*global plupload */
  2. /*global qiniu */
  3. function FileProgress(file, targetID) {
  4. this.fileProgressID = file.id;
  5. this.file = file;
  6. this.opacity = 100;
  7. this.height = 0;
  8. this.fileProgressWrapper = $('#' + this.fileProgressID);
  9. if (!this.fileProgressWrapper.length) {
  10. // <div class="progress">
  11. // <div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
  12. // <span class="sr-only">20% Complete</span>
  13. // </div>
  14. // </div>
  15. this.fileProgressWrapper = $('<tr></tr>');
  16. var Wrappeer = this.fileProgressWrapper;
  17. Wrappeer.attr('id', this.fileProgressID).addClass('progressContainer');
  18. var progressText = $("<td/>");
  19. progressText.addClass('progressName').text(file.name);
  20. var fileSize = plupload.formatSize(file.size).toUpperCase();
  21. var progressSize = $("<td/>");
  22. progressSize.addClass("progressFileSize").text(fileSize);
  23. var progressBarTd = $("<td/>");
  24. var progressBarBox = $("<div/>");
  25. progressBarBox.addClass('info');
  26. var progressBarWrapper = $("<div/>");
  27. progressBarWrapper.addClass("progress progress-striped");
  28. var progressBar = $("<div/>");
  29. progressBar.addClass("progress-bar progress-bar-info")
  30. .attr('role', 'progressbar')
  31. .attr('aria-valuemax', 100)
  32. .attr('aria-valuenow', 0)
  33. .attr('aria-valuein', 0)
  34. .width('0%');
  35. var progressBarPercent = $('<span class=sr-only />');
  36. progressBarPercent.text(fileSize);
  37. var progressCancel = $('<a href=# />');
  38. progressCancel.hide().addClass('progressCancel').text('');
  39. progressBar.append(progressBarPercent);
  40. progressBarWrapper.append(progressBar);
  41. progressBarBox.append(progressBarWrapper);
  42. progressBarBox.append(progressCancel);
  43. var progressBarStatus = $('<div class="status text-center"/>');
  44. progressBarBox.append(progressBarStatus);
  45. progressBarTd.append(progressBarBox);
  46. Wrappeer.append(progressText);
  47. Wrappeer.append(progressSize);
  48. Wrappeer.append(progressBarTd);
  49. $('#' + targetID).append(Wrappeer);
  50. } else {
  51. this.reset();
  52. }
  53. this.height = this.fileProgressWrapper.offset().top;
  54. this.setTimer(null);
  55. }
  56. FileProgress.prototype.setTimer = function(timer) {
  57. this.fileProgressWrapper.FP_TIMER = timer;
  58. };
  59. FileProgress.prototype.getTimer = function(timer) {
  60. return this.fileProgressWrapper.FP_TIMER || null;
  61. };
  62. FileProgress.prototype.reset = function() {
  63. this.fileProgressWrapper.attr('class', "progressContainer");
  64. this.fileProgressWrapper.find('td .progress .progress-bar-info').attr('aria-valuenow', 0).width('0%').find('span').text('');
  65. this.appear();
  66. };
  67. FileProgress.prototype.setChunkProgess = function(chunk_size) {
  68. var chunk_amount = Math.ceil(this.file.size / chunk_size);
  69. if (chunk_amount === 1) {
  70. return false;
  71. }
  72. var viewProgess = $('<button class="btn btn-default">查看分块上传进度</button>');
  73. var progressBarChunkTr = $('<tr class="chunk-status-tr"><td colspan=3></td></tr>');
  74. var progressBarChunk = $('<div/>');
  75. for (var i = 1; i <= chunk_amount; i++) {
  76. var col = $('<div class="col-md-2"/>');
  77. var progressBarWrapper = $('<div class="progress progress-striped"></div');
  78. var progressBar = $("<div/>");
  79. progressBar.addClass("progress-bar progress-bar-info text-left")
  80. .attr('role', 'progressbar')
  81. .attr('aria-valuemax', 100)
  82. .attr('aria-valuenow', 0)
  83. .attr('aria-valuein', 0)
  84. .width('0%')
  85. .attr('id', this.file.id + '_' + i)
  86. .text('');
  87. var progressBarStatus = $('<span/>');
  88. progressBarStatus.addClass('chunk-status').text();
  89. progressBarWrapper.append(progressBar);
  90. progressBarWrapper.append(progressBarStatus);
  91. col.append(progressBarWrapper);
  92. progressBarChunk.append(col);
  93. }
  94. this.fileProgressWrapper.find('td>div').append(viewProgess);
  95. progressBarChunkTr.hide().find('td').append(progressBarChunk);
  96. progressBarChunkTr.insertAfter(this.fileProgressWrapper);
  97. };
  98. FileProgress.prototype.setProgress = function(percentage, speed, chunk_size) {
  99. this.fileProgressWrapper.attr('class', "progressContainer green");
  100. var file = this.file;
  101. var uploaded = file.loaded;
  102. var size = plupload.formatSize(uploaded).toUpperCase();
  103. var formatSpeed = plupload.formatSize(speed).toUpperCase();
  104. var progressbar = this.fileProgressWrapper.find('td .progress').find('.progress-bar-info');
  105. this.fileProgressWrapper.find('.status').text("已上传: " + size + " 上传速度: " + formatSpeed + "/s");
  106. percentage = parseInt(percentage, 10);
  107. if (file.status !== plupload.DONE && percentage === 100) {
  108. percentage = 99;
  109. }
  110. progressbar.attr('aria-valuenow', percentage).css('width', percentage + '%');
  111. if (chunk_size) {
  112. var chunk_amount = Math.ceil(file.size / chunk_size);
  113. if (chunk_amount === 1) {
  114. return false;
  115. }
  116. var current_uploading_chunk = Math.ceil(uploaded / chunk_size);
  117. var pre_chunk, text;
  118. for (var index = 0; index < current_uploading_chunk; index++) {
  119. pre_chunk = $('#' + file.id + "_" + index);
  120. pre_chunk.width('100%').removeClass().addClass('alert-success').attr('aria-valuenow', 100);
  121. text = "块" + index + "上传进度100%";
  122. pre_chunk.next().html(text);
  123. }
  124. var currentProgessBar = $('#' + file.id + "_" + current_uploading_chunk);
  125. var current_chunk_percent;
  126. if (current_uploading_chunk < chunk_amount) {
  127. if (uploaded % chunk_size) {
  128. current_chunk_percent = ((uploaded % chunk_size) / chunk_size * 100).toFixed(2);
  129. } else {
  130. current_chunk_percent = 100;
  131. currentProgessBar.removeClass().addClass('alert-success');
  132. }
  133. } else {
  134. var last_chunk_size = file.size - chunk_size * (chunk_amount - 1);
  135. var left_file_size = file.size - uploaded;
  136. if (left_file_size % last_chunk_size) {
  137. current_chunk_percent = ((uploaded % chunk_size) / last_chunk_size * 100).toFixed(2);
  138. } else {
  139. current_chunk_percent = 100;
  140. currentProgessBar.removeClass().addClass('alert-success');
  141. }
  142. }
  143. currentProgessBar.width(current_chunk_percent + '%');
  144. currentProgessBar.attr('aria-valuenow', current_chunk_percent);
  145. text = "块" + current_uploading_chunk + "上传进度" + current_chunk_percent + '%';
  146. currentProgessBar.next().html(text);
  147. }
  148. this.appear();
  149. };
  150. FileProgress.prototype.setComplete = function(up, info) {
  151. var td = this.fileProgressWrapper.find('td:eq(2) .progress');
  152. var res = $.parseJSON(info);
  153. var domain = up.getOption('domain');
  154. var url = domain + encodeURI(res.key);
  155. var link = domain + res.key;
  156. var str = "<div><strong>Link:</strong><a href=" + url + " target='_blank' > " + link + "</a></div>" +
  157. "<div class=hash><strong>Hash:</strong>" + res.hash + "</div>";
  158. td.html(str).removeClass().next().next('.status').hide();
  159. var progressNameTd = this.fileProgressWrapper.find('.progressName');
  160. var imageView = '?imageView2/1/w/100/h/100';
  161. var isImage = function(url) {
  162. var res, suffix = "";
  163. var imageSuffixes = ["png", "jpg", "jpeg", "gif", "bmp"];
  164. var suffixMatch = /\.([a-zA-Z0-9]+)(\?|\@|$)/;
  165. if (!url || !suffixMatch.test(url)) {
  166. return false;
  167. }
  168. res = suffixMatch.exec(url);
  169. suffix = res[1].toLowerCase();
  170. for (var i = 0, l = imageSuffixes.length; i < l; i++) {
  171. if (suffix === imageSuffixes[i]) {
  172. return true;
  173. }
  174. }
  175. return false;
  176. };
  177. var isImg = isImage(url);
  178. var Wrapper = $('<div class="Wrapper"/>');
  179. var imgWrapper = $('<div class="imgWrapper col-md-3"/>');
  180. var linkWrapper = $('<a class="linkWrapper" target="_blank"/>');
  181. var showImg = $('<img src="loading.gif"/>');
  182. progressNameTd.append(Wrapper);
  183. if (!isImg) {
  184. showImg.attr('src', 'default.png');
  185. Wrapper.addClass('default');
  186. imgWrapper.append(showImg);
  187. Wrapper.append(imgWrapper);
  188. } else {
  189. linkWrapper.append(showImg);
  190. imgWrapper.append(linkWrapper);
  191. Wrapper.append(imgWrapper);
  192. var img = new Image();
  193. $(img).attr('src', url + imageView);
  194. var height_space = 340;
  195. $(img).on('load', function() {
  196. showImg.attr('src', url + imageView);
  197. linkWrapper.attr('href', url).attr('title', '查看原图');
  198. function initImg(url, key, height) {
  199. $('#myModal-img').modal();
  200. var modalBody = $('#myModal-img').find('.modal-body');
  201. if (height <= 300) {
  202. $('#myModal-img').find('.text-warning').show();
  203. }
  204. var newImg = new Image();
  205. modalBody.find('img').attr('src', 'loading.gif');
  206. newImg.onload = function() {
  207. modalBody.find('img').attr('src', url).data('key', key).data('h', height);
  208. modalBody.find('.modal-body-wrapper').find('a').attr('href', url);
  209. };
  210. newImg.src = url;
  211. }
  212. var infoWrapper = $('<div class="infoWrapper col-md-6"></div>');
  213. var fopLink = $('<a class="fopLink"/>');
  214. fopLink.attr('data-key', res.key).text('查看处理效果');
  215. infoWrapper.append(fopLink);
  216. fopLink.on('click', function() {
  217. var key = $(this).data('key');
  218. var height = parseInt($(this).parents('.Wrapper').find('.origin-height').text(), 10);
  219. if (height > $(window).height() - height_space) {
  220. height = parseInt($(window).height() - height_space, 10);
  221. } else {
  222. height = parseInt(height, 10) || 300;
  223. //set a default height 300 for ie9-
  224. }
  225. var fopArr = [];
  226. fopArr.push({
  227. fop: 'imageView2',
  228. mode: 3,
  229. h: height,
  230. q: 100,
  231. format: 'png'
  232. });
  233. fopArr.push({
  234. fop: 'watermark',
  235. mode: 1,
  236. image: 'http://www.b1.qiniudn.com/images/logo-2.png',
  237. dissolve: 100,
  238. gravity: 'SouthEast',
  239. dx: 100,
  240. dy: 100
  241. });
  242. var url = Qiniu.pipeline(fopArr, key);
  243. $('#myModal-img').on('hide.bs.modal', function() {
  244. $('#myModal-img').find('.btn-default').removeClass('disabled');
  245. $('#myModal-img').find('.text-warning').hide();
  246. }).on('show.bs.modal', function() {
  247. $('#myModal-img').find('.imageView').find('a:eq(0)').addClass('disabled');
  248. $('#myModal-img').find('.watermark').find('a:eq(3)').addClass('disabled');
  249. $('#myModal-img').find('.text-warning').hide();
  250. });
  251. initImg(url, key, height);
  252. return false;
  253. });
  254. var ie = Qiniu.detectIEVersion();
  255. if (!(ie && ie <= 9)) {
  256. var exif = Qiniu.exif(res.key);
  257. if (exif) {
  258. var exifLink = $('<a href="" target="_blank">查看exif</a>');
  259. exifLink.attr('href', url + '?exif');
  260. infoWrapper.append(exifLink);
  261. }
  262. var imageInfo = Qiniu.imageInfo(res.key);
  263. var infoArea = $('<div/>');
  264. var infoInner = '<div>格式:<span class="origin-format">' + imageInfo.format + '</span></div>' +
  265. '<div>宽度:<span class="orgin-width">' + imageInfo.width + 'px</span></div>' +
  266. '<div>高度:<span class="origin-height">' + imageInfo.height + 'px</span></div>';
  267. infoArea.html(infoInner);
  268. infoWrapper.append(infoArea);
  269. }
  270. Wrapper.append(infoWrapper);
  271. }).on('error', function() {
  272. showImg.attr('src', 'default.png');
  273. Wrapper.addClass('default');
  274. });
  275. }
  276. };
  277. FileProgress.prototype.setError = function() {
  278. this.fileProgressWrapper.find('td:eq(2)').attr('class', 'text-warning');
  279. this.fileProgressWrapper.find('td:eq(2) .progress').css('width', 0).hide();
  280. this.fileProgressWrapper.find('button').hide();
  281. this.fileProgressWrapper.next('.chunk-status-tr').hide();
  282. };
  283. FileProgress.prototype.setCancelled = function(manual) {
  284. var progressContainer = 'progressContainer';
  285. if (!manual) {
  286. progressContainer += ' red';
  287. }
  288. this.fileProgressWrapper.attr('class', progressContainer);
  289. this.fileProgressWrapper.find('td .progress .progress-bar-info').css('width', 0);
  290. };
  291. FileProgress.prototype.setStatus = function(status, isUploading) {
  292. if (!isUploading) {
  293. this.fileProgressWrapper.find('.status').text(status).attr('class', 'status text-left');
  294. }
  295. };
  296. FileProgress.prototype.appear = function() {
  297. if (this.getTimer() !== null) {
  298. clearTimeout(this.getTimer());
  299. this.setTimer(null);
  300. }
  301. if (this.fileProgressWrapper[0].filters) {
  302. try {
  303. this.fileProgressWrapper[0].filters.item("DXImageTransform.Microsoft.Alpha").opacity = 100;
  304. } catch (e) {
  305. // If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
  306. this.fileProgressWrapper.css('filter', "progid:DXImageTransform.Microsoft.Alpha(opacity=100)");
  307. }
  308. } else {
  309. this.fileProgressWrapper.css('opacity', 1);
  310. }
  311. this.fileProgressWrapper.css('height', '');
  312. this.height = this.fileProgressWrapper.offset().top;
  313. this.opacity = 100;
  314. this.fileProgressWrapper.show();
  315. };