284042e39931eaa0e218971f438e69e1865638e9.svn-base 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. /**
  2. * Created by JetBrains PhpStorm.
  3. * User: taoqili
  4. * Date: 12-2-20
  5. * Time: 上午11:19
  6. * To change this template use File | Settings | File Templates.
  7. */
  8. (function(){
  9. var video = {},
  10. uploadVideoList = [],
  11. isModifyUploadVideo = false,
  12. // widuu 添加上传判断参数
  13. uploadType,
  14. uploadUrl,
  15. isDirect,
  16. isChunked = false, // 是否分片上传
  17. qiniuCtx = '', // 块控制信息
  18. nextChunkOffset, // 当前片在整个块中的起始偏移
  19. chunkUploadUrl = '', // 分片上传url
  20. videoBlockSize, // 视频块大小
  21. makeBlockUploadUrl, // 创建块url方法
  22. // end widuu
  23. uploadFile;
  24. window.onload = function(){
  25. $focus($G("videoUrl"));
  26. initTabs();
  27. initVideo();
  28. initUpload();
  29. // widuu 初始化配置
  30. initUploadType();
  31. };
  32. /* 初始化tab标签 */
  33. function initTabs(){
  34. var tabs = $G('tabHeads').children;
  35. for (var i = 0; i < tabs.length; i++) {
  36. domUtils.on(tabs[i], "click", function (e) {
  37. var j, bodyId, target = e.target || e.srcElement;
  38. for (j = 0; j < tabs.length; j++) {
  39. bodyId = tabs[j].getAttribute('data-content-id');
  40. if(tabs[j] == target){
  41. domUtils.addClass(tabs[j], 'focus');
  42. domUtils.addClass($G(bodyId), 'focus');
  43. }else {
  44. domUtils.removeClasses(tabs[j], 'focus');
  45. domUtils.removeClasses($G(bodyId), 'focus');
  46. }
  47. }
  48. });
  49. }
  50. }
  51. /* widuu初始化上传参数 */
  52. function initUploadType(){
  53. uploadType = editor.getOpt('uploadType');
  54. isDirect = editor.getOpt('qiniuUploadType');
  55. if( (uploadType == 'local' || isDirect == 'php') && !isChunked ){
  56. var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '',
  57. actionUrl = editor.getActionUrl(editor.getOpt('videoActionName')),
  58. url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params);
  59. uploadUrl = url;
  60. }else{
  61. // 视频分块大小
  62. videoBlockSize = editor.getOpt('VideoBlockFileSize');
  63. // 视频创建块地址
  64. makeBlockUploadUrl = editor.getOpt("ChunkUploadQiniuUrl") + '/mkblk/' + videoBlockSize;
  65. // 直传地址
  66. uploadUrl = editor.getOpt('uploadQiniuUrl');
  67. // 分片上传
  68. chunkUploadUrl = chunkUploadUrl == '' ? editor.getOpt("ChunkUploadQiniuUrl") : chunkUploadUrl;
  69. }
  70. }
  71. /* widuu 格式化日期方法 */
  72. Date.prototype.Format = function (fmt) {
  73. var o = {
  74. "m+": this.getMonth() + 1,
  75. "d+": this.getDate(),
  76. };
  77. if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  78. for (var k in o)
  79. if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  80. return fmt;
  81. }
  82. /* end widuu */
  83. function initVideo(){
  84. createAlignButton( ["videoFloat", "upload_alignment"] );
  85. addUrlChangeListener($G("videoUrl"));
  86. addOkListener();
  87. //编辑视频时初始化相关信息
  88. (function(){
  89. var img = editor.selection.getRange().getClosedNode(),url;
  90. if(img && img.className){
  91. var hasFakedClass = (img.className == "edui-faked-video"),
  92. hasUploadClass = img.className.indexOf("edui-upload-video")!=-1;
  93. if(hasFakedClass || hasUploadClass) {
  94. $G("videoUrl").value = url = img.getAttribute("_url");
  95. $G("videoWidth").value = img.width;
  96. $G("videoHeight").value = img.height;
  97. var align = domUtils.getComputedStyle(img,"float"),
  98. parentAlign = domUtils.getComputedStyle(img.parentNode,"text-align");
  99. updateAlignButton(parentAlign==="center"?"center":align);
  100. }
  101. if(hasUploadClass) {
  102. isModifyUploadVideo = true;
  103. }
  104. }
  105. createPreviewVideo(url);
  106. })();
  107. }
  108. /**
  109. * 监听确认和取消两个按钮事件,用户执行插入或者清空正在播放的视频实例操作
  110. */
  111. function addOkListener(){
  112. dialog.onok = function(){
  113. $G("preview").innerHTML = "";
  114. var currentTab = findFocus("tabHeads","tabSrc");
  115. switch(currentTab){
  116. case "video":
  117. return insertSingle();
  118. break;
  119. case "videoSearch":
  120. return insertSearch("searchList");
  121. break;
  122. case "upload":
  123. return insertUpload();
  124. break;
  125. }
  126. };
  127. dialog.oncancel = function(){
  128. $G("preview").innerHTML = "";
  129. };
  130. }
  131. /**
  132. * 依据传入的align值更新按钮信息
  133. * @param align
  134. */
  135. function updateAlignButton( align ) {
  136. var aligns = $G( "videoFloat" ).children;
  137. for ( var i = 0, ci; ci = aligns[i++]; ) {
  138. if ( ci.getAttribute( "name" ) == align ) {
  139. if ( ci.className !="focus" ) {
  140. ci.className = "focus";
  141. }
  142. } else {
  143. if ( ci.className =="focus" ) {
  144. ci.className = "";
  145. }
  146. }
  147. }
  148. }
  149. /**
  150. * 将单个视频信息插入编辑器中
  151. */
  152. function insertSingle(){
  153. var width = $G("videoWidth"),
  154. height = $G("videoHeight"),
  155. url=$G('videoUrl').value,
  156. align = findFocus("videoFloat","name");
  157. if(!url) return false;
  158. if ( !checkNum( [width, height] ) ) return false;
  159. editor.execCommand('insertvideo', {
  160. url: convert_url(url),
  161. width: width.value,
  162. height: height.value,
  163. align: align
  164. }, isModifyUploadVideo ? 'upload':null);
  165. }
  166. /**
  167. * 将元素id下的所有代表视频的图片插入编辑器中
  168. * @param id
  169. */
  170. function insertSearch(id){
  171. var imgs = domUtils.getElementsByTagName($G(id),"img"),
  172. videoObjs=[];
  173. for(var i=0,img; img=imgs[i++];){
  174. if(img.getAttribute("selected")){
  175. videoObjs.push({
  176. url:img.getAttribute("ue_video_url"),
  177. width:420,
  178. height:280,
  179. align:"none"
  180. });
  181. }
  182. }
  183. editor.execCommand('insertvideo',videoObjs);
  184. }
  185. /**
  186. * 找到id下具有focus类的节点并返回该节点下的某个属性
  187. * @param id
  188. * @param returnProperty
  189. */
  190. function findFocus( id, returnProperty ) {
  191. var tabs = $G( id ).children,
  192. property;
  193. for ( var i = 0, ci; ci = tabs[i++]; ) {
  194. if ( ci.className=="focus" ) {
  195. property = ci.getAttribute( returnProperty );
  196. break;
  197. }
  198. }
  199. return property;
  200. }
  201. function convert_url(url){
  202. if ( !url ) return '';
  203. url = utils.trim(url)
  204. .replace(/v\.youku\.com\/v_show\/id_([\w\-=]+)\.html/i, 'player.youku.com/player.php/sid/$1/v.swf')
  205. .replace(/(www\.)?youtube\.com\/watch\?v=([\w\-]+)/i, "www.youtube.com/v/$2")
  206. .replace(/youtu.be\/(\w+)$/i, "www.youtube.com/v/$1")
  207. .replace(/v\.ku6\.com\/.+\/([\w\.]+)\.html.*$/i, "player.ku6.com/refer/$1/v.swf")
  208. .replace(/www\.56\.com\/u\d+\/v_([\w\-]+)\.html/i, "player.56.com/v_$1.swf")
  209. .replace(/www.56.com\/w\d+\/play_album\-aid\-\d+_vid\-([^.]+)\.html/i, "player.56.com/v_$1.swf")
  210. .replace(/v\.pps\.tv\/play_([\w]+)\.html.*$/i, "player.pps.tv/player/sid/$1/v.swf")
  211. .replace(/www\.letv\.com\/ptv\/vplay\/([\d]+)\.html.*$/i, "i7.imgs.letv.com/player/swfPlayer.swf?id=$1&autoplay=0")
  212. .replace(/www\.tudou\.com\/programs\/view\/([\w\-]+)\/?/i, "www.tudou.com/v/$1")
  213. .replace(/v\.qq\.com\/cover\/[\w]+\/[\w]+\/([\w]+)\.html/i, "static.video.qq.com/TPout.swf?vid=$1")
  214. .replace(/v\.qq\.com\/.+[\?\&]vid=([^&]+).*$/i, "static.video.qq.com/TPout.swf?vid=$1")
  215. .replace(/my\.tv\.sohu\.com\/[\w]+\/[\d]+\/([\d]+)\.shtml.*$/i, "share.vrs.sohu.com/my/v.swf&id=$1");
  216. return url;
  217. }
  218. /**
  219. * 检测传入的所有input框中输入的长宽是否是正数
  220. * @param nodes input框集合,
  221. */
  222. function checkNum( nodes ) {
  223. for ( var i = 0, ci; ci = nodes[i++]; ) {
  224. var value = ci.value;
  225. if ( !isNumber( value ) && value) {
  226. alert( lang.numError );
  227. ci.value = "";
  228. ci.focus();
  229. return false;
  230. }
  231. }
  232. return true;
  233. }
  234. /**
  235. * 数字判断
  236. * @param value
  237. */
  238. function isNumber( value ) {
  239. return /(0|^[1-9]\d*$)/.test( value );
  240. }
  241. /**
  242. * 创建图片浮动选择按钮
  243. * @param ids
  244. */
  245. function createAlignButton( ids ) {
  246. for ( var i = 0, ci; ci = ids[i++]; ) {
  247. var floatContainer = $G( ci ),
  248. nameMaps = {"none":lang['default'], "left":lang.floatLeft, "right":lang.floatRight, "center":lang.block};
  249. for ( var j in nameMaps ) {
  250. var div = document.createElement( "div" );
  251. div.setAttribute( "name", j );
  252. if ( j == "none" ) div.className="focus";
  253. div.style.cssText = "background:url(images/" + j + "_focus.jpg);";
  254. div.setAttribute( "title", nameMaps[j] );
  255. floatContainer.appendChild( div );
  256. }
  257. switchSelect( ci );
  258. }
  259. }
  260. /**
  261. * 选择切换
  262. * @param selectParentId
  263. */
  264. function switchSelect( selectParentId ) {
  265. var selects = $G( selectParentId ).children;
  266. for ( var i = 0, ci; ci = selects[i++]; ) {
  267. domUtils.on( ci, "click", function () {
  268. for ( var j = 0, cj; cj = selects[j++]; ) {
  269. cj.className = "";
  270. cj.removeAttribute && cj.removeAttribute( "class" );
  271. }
  272. this.className = "focus";
  273. } )
  274. }
  275. }
  276. /**
  277. * 监听url改变事件
  278. * @param url
  279. */
  280. function addUrlChangeListener(url){
  281. if (browser.ie) {
  282. url.onpropertychange = function () {
  283. createPreviewVideo( this.value );
  284. }
  285. } else {
  286. url.addEventListener( "input", function () {
  287. createPreviewVideo( this.value );
  288. }, false );
  289. }
  290. }
  291. /**
  292. * 根据url生成视频预览
  293. * @param url
  294. */
  295. function createPreviewVideo(url){
  296. if ( !url )return;
  297. var conUrl = convert_url(url);
  298. conUrl = utils.unhtmlForUrl(conUrl);
  299. $G("preview").innerHTML = '<div class="previewMsg"><span>'+lang.urlError+'</span></div>'+
  300. '<embed class="previewVideo" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"' +
  301. ' src="' + conUrl + '"' +
  302. ' width="' + 420 + '"' +
  303. ' height="' + 280 + '"' +
  304. ' wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true" >' +
  305. '</embed>';
  306. }
  307. /* 插入上传视频 */
  308. function insertUpload(){
  309. var videoObjs=[],
  310. uploadDir = editor.getOpt('videoUrlPrefix'),
  311. width = parseInt($G('upload_width').value, 10) || 420,
  312. height = parseInt($G('upload_height').value, 10) || 280,
  313. align = findFocus("upload_alignment","name") || 'none';
  314. for(var key in uploadVideoList) {
  315. var file = uploadVideoList[key];
  316. videoObjs.push({
  317. url: uploadDir + file.url,
  318. width:width,
  319. height:height,
  320. align:align
  321. });
  322. }
  323. var count = uploadFile.getQueueCount();
  324. if (count) {
  325. $('.info', '#queueList').html('<span style="color:red;">' + '还有2个未上传文件'.replace(/[\d]/, count) + '</span>');
  326. return false;
  327. } else {
  328. editor.execCommand('insertvideo', videoObjs, 'upload');
  329. }
  330. }
  331. /*初始化上传标签*/
  332. function initUpload(){
  333. uploadFile = new UploadFile('queueList');
  334. }
  335. /* 上传附件 */
  336. function UploadFile(target) {
  337. this.$wrap = target.constructor == String ? $('#' + target) : $(target);
  338. this.init();
  339. }
  340. UploadFile.prototype = {
  341. init: function () {
  342. this.fileList = [];
  343. this.initContainer();
  344. this.initUploader();
  345. },
  346. initContainer: function () {
  347. this.$queue = this.$wrap.find('.filelist');
  348. },
  349. /* 初始化容器 */
  350. initUploader: function () {
  351. var _this = this,
  352. $ = jQuery, // just in case. Make sure it's not an other libaray.
  353. $wrap = _this.$wrap,
  354. // 图片容器
  355. $queue = $wrap.find('.filelist'),
  356. // 状态栏,包括进度和控制按钮
  357. $statusBar = $wrap.find('.statusBar'),
  358. // 文件总体选择信息。
  359. $info = $statusBar.find('.info'),
  360. // 上传按钮
  361. $upload = $wrap.find('.uploadBtn'),
  362. // 上传按钮
  363. $filePickerBtn = $wrap.find('.filePickerBtn'),
  364. // 上传按钮
  365. $filePickerBlock = $wrap.find('.filePickerBlock'),
  366. // 没选择文件之前的内容。
  367. $placeHolder = $wrap.find('.placeholder'),
  368. // 总体进度条
  369. $progress = $statusBar.find('.progress').hide(),
  370. // 添加的文件数量
  371. fileCount = 0,
  372. // 添加的文件总大小
  373. fileSize = 0,
  374. // 优化retina, 在retina下这个值是2
  375. ratio = window.devicePixelRatio || 1,
  376. // 缩略图大小
  377. thumbnailWidth = 113 * ratio,
  378. thumbnailHeight = 113 * ratio,
  379. // 可能有pedding, ready, uploading, confirm, done.
  380. state = '',
  381. // 所有文件的进度信息,key为file id
  382. percentages = {},
  383. supportTransition = (function () {
  384. var s = document.createElement('p').style,
  385. r = 'transition' in s ||
  386. 'WebkitTransition' in s ||
  387. 'MozTransition' in s ||
  388. 'msTransition' in s ||
  389. 'OTransition' in s;
  390. s = null;
  391. return r;
  392. })(),
  393. // WebUploader实例
  394. uploader,
  395. actionUrl = editor.getActionUrl(editor.getOpt('videoActionName')),
  396. fileMaxSize = editor.getOpt('videoMaxSize'),
  397. acceptExtensions = (editor.getOpt('videoAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');;
  398. if (!WebUploader.Uploader.support()) {
  399. $('#filePickerReady').after($('<div>').html(lang.errorNotSupport)).hide();
  400. return;
  401. } else if (!editor.getOpt('videoActionName')) {
  402. $('#filePickerReady').after($('<div>').html(lang.errorLoadConfig)).hide();
  403. return;
  404. }
  405. uploader = _this.uploader = WebUploader.create({
  406. pick: {
  407. id: '#filePickerReady',
  408. label: lang.uploadSelectFile
  409. },
  410. swf: '../../third-party/webuploader/Uploader.swf',
  411. server: actionUrl,
  412. fileVal: editor.getOpt('videoFieldName'),
  413. duplicate: true,
  414. fileSingleSizeLimit: fileMaxSize,
  415. compress: false
  416. });
  417. uploader.addButton({
  418. id: '#filePickerBlock'
  419. });
  420. uploader.addButton({
  421. id: '#filePickerBtn',
  422. label: lang.uploadAddFile
  423. });
  424. setState('pedding');
  425. // 当有文件添加进来时执行,负责view的创建
  426. function addFile(file) {
  427. var $li = $('<li id="' + file.id + '">' +
  428. '<p class="title">' + file.name + '</p>' +
  429. '<p class="imgWrap"></p>' +
  430. '<p class="progress"><span></span></p>' +
  431. '</li>'),
  432. $btns = $('<div class="file-panel">' +
  433. '<span class="cancel">' + lang.uploadDelete + '</span>' +
  434. '<span class="rotateRight">' + lang.uploadTurnRight + '</span>' +
  435. '<span class="rotateLeft">' + lang.uploadTurnLeft + '</span></div>').appendTo($li),
  436. $prgress = $li.find('p.progress span'),
  437. $wrap = $li.find('p.imgWrap'),
  438. $info = $('<p class="error"></p>').hide().appendTo($li),
  439. showError = function (code) {
  440. switch (code) {
  441. case 'exceed_size':
  442. text = lang.errorExceedSize;
  443. break;
  444. case 'interrupt':
  445. text = lang.errorInterrupt;
  446. break;
  447. case 'http':
  448. text = lang.errorHttp;
  449. break;
  450. case 'not_allow_type':
  451. text = lang.errorFileType;
  452. break;
  453. default:
  454. text = lang.errorUploadRetry;
  455. break;
  456. }
  457. $info.text(text).show();
  458. };
  459. if (file.getStatus() === 'invalid') {
  460. showError(file.statusText);
  461. } else {
  462. $wrap.text(lang.uploadPreview);
  463. if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) {
  464. $wrap.empty().addClass('notimage').append('<i class="file-preview file-type-' + file.ext.toLowerCase() + '"></i>' +
  465. '<span class="file-title">' + file.name + '</span>');
  466. } else {
  467. if (browser.ie && browser.version <= 7) {
  468. $wrap.text(lang.uploadNoPreview);
  469. } else {
  470. uploader.makeThumb(file, function (error, src) {
  471. if (error || !src || (/^data:/.test(src) && browser.ie && browser.version <= 7)) {
  472. $wrap.text(lang.uploadNoPreview);
  473. } else {
  474. var $img = $('<img src="' + src + '">');
  475. $wrap.empty().append($img);
  476. $img.on('error', function () {
  477. $wrap.text(lang.uploadNoPreview);
  478. });
  479. }
  480. }, thumbnailWidth, thumbnailHeight);
  481. }
  482. }
  483. percentages[ file.id ] = [ file.size, 0 ];
  484. file.rotation = 0;
  485. /* 检查文件格式 */
  486. if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) {
  487. showError('not_allow_type');
  488. uploader.removeFile(file);
  489. }
  490. }
  491. file.on('statuschange', function (cur, prev) {
  492. if (prev === 'progress') {
  493. $prgress.hide().width(0);
  494. } else if (prev === 'queued') {
  495. $li.off('mouseenter mouseleave');
  496. $btns.remove();
  497. }
  498. // 成功
  499. if (cur === 'error' || cur === 'invalid') {
  500. showError(file.statusText);
  501. percentages[ file.id ][ 1 ] = 1;
  502. } else if (cur === 'interrupt') {
  503. showError('interrupt');
  504. } else if (cur === 'queued') {
  505. percentages[ file.id ][ 1 ] = 0;
  506. } else if (cur === 'progress') {
  507. $info.hide();
  508. $prgress.css('display', 'block');
  509. } else if (cur === 'complete') {
  510. }
  511. $li.removeClass('state-' + prev).addClass('state-' + cur);
  512. });
  513. $li.on('mouseenter', function () {
  514. $btns.stop().animate({height: 30});
  515. });
  516. $li.on('mouseleave', function () {
  517. $btns.stop().animate({height: 0});
  518. });
  519. $btns.on('click', 'span', function () {
  520. var index = $(this).index(),
  521. deg;
  522. switch (index) {
  523. case 0:
  524. uploader.removeFile(file);
  525. return;
  526. case 1:
  527. file.rotation += 90;
  528. break;
  529. case 2:
  530. file.rotation -= 90;
  531. break;
  532. }
  533. if (supportTransition) {
  534. deg = 'rotate(' + file.rotation + 'deg)';
  535. $wrap.css({
  536. '-webkit-transform': deg,
  537. '-mos-transform': deg,
  538. '-o-transform': deg,
  539. 'transform': deg
  540. });
  541. } else {
  542. $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')');
  543. }
  544. });
  545. $li.insertBefore($filePickerBlock);
  546. }
  547. // 负责view的销毁
  548. function removeFile(file) {
  549. var $li = $('#' + file.id);
  550. delete percentages[ file.id ];
  551. updateTotalProgress();
  552. $li.off().find('.file-panel').off().end().remove();
  553. }
  554. function updateTotalProgress() {
  555. var loaded = 0,
  556. total = 0,
  557. spans = $progress.children(),
  558. percent;
  559. $.each(percentages, function (k, v) {
  560. total += v[ 0 ];
  561. loaded += v[ 0 ] * v[ 1 ];
  562. });
  563. percent = total ? loaded / total : 0;
  564. spans.eq(0).text(Math.round(percent * 100) + '%');
  565. spans.eq(1).css('width', Math.round(percent * 100) + '%');
  566. updateStatus();
  567. }
  568. function setState(val, files) {
  569. if (val != state) {
  570. var stats = uploader.getStats();
  571. $upload.removeClass('state-' + state);
  572. $upload.addClass('state-' + val);
  573. switch (val) {
  574. /* 未选择文件 */
  575. case 'pedding':
  576. $queue.addClass('element-invisible');
  577. $statusBar.addClass('element-invisible');
  578. $placeHolder.removeClass('element-invisible');
  579. $progress.hide(); $info.hide();
  580. uploader.refresh();
  581. break;
  582. /* 可以开始上传 */
  583. case 'ready':
  584. $placeHolder.addClass('element-invisible');
  585. $queue.removeClass('element-invisible');
  586. $statusBar.removeClass('element-invisible');
  587. $progress.hide(); $info.show();
  588. $upload.text(lang.uploadStart);
  589. uploader.refresh();
  590. break;
  591. /* 上传中 */
  592. case 'uploading':
  593. $progress.show(); $info.hide();
  594. $upload.text(lang.uploadPause);
  595. break;
  596. /* 暂停上传 */
  597. case 'paused':
  598. $progress.show(); $info.hide();
  599. $upload.text(lang.uploadContinue);
  600. break;
  601. case 'confirm':
  602. $progress.show(); $info.hide();
  603. $upload.text(lang.uploadStart);
  604. stats = uploader.getStats();
  605. if (stats.successNum && !stats.uploadFailNum) {
  606. setState('finish');
  607. return;
  608. }
  609. break;
  610. case 'finish':
  611. $progress.hide(); $info.show();
  612. if (stats.uploadFailNum) {
  613. $upload.text(lang.uploadRetry);
  614. } else {
  615. $upload.text(lang.uploadStart);
  616. }
  617. break;
  618. }
  619. state = val;
  620. updateStatus();
  621. }
  622. if (!_this.getQueueCount()) {
  623. $upload.addClass('disabled')
  624. } else {
  625. $upload.removeClass('disabled')
  626. }
  627. }
  628. function updateStatus() {
  629. var text = '', stats;
  630. if (state === 'ready') {
  631. text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize));
  632. } else if (state === 'confirm') {
  633. stats = uploader.getStats();
  634. if (stats.uploadFailNum) {
  635. text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum);
  636. }
  637. } else {
  638. stats = uploader.getStats();
  639. text = lang.updateStatusFinish.replace('_', fileCount).
  640. replace('_KB', WebUploader.formatSize(fileSize)).
  641. replace('_', stats.successNum);
  642. if (stats.uploadFailNum) {
  643. text += lang.updateStatusError.replace('_', stats.uploadFailNum);
  644. }
  645. }
  646. $info.html(text);
  647. }
  648. uploader.on('fileQueued', function (file) {
  649. fileCount++;
  650. fileSize += file.size;
  651. if (fileCount === 1) {
  652. $placeHolder.addClass('element-invisible');
  653. $statusBar.show();
  654. }
  655. addFile(file);
  656. });
  657. uploader.on('fileDequeued', function (file) {
  658. fileCount--;
  659. fileSize -= file.size;
  660. removeFile(file);
  661. updateTotalProgress();
  662. });
  663. uploader.on('filesQueued', function (file) {
  664. if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) {
  665. setState('ready');
  666. }
  667. updateTotalProgress();
  668. });
  669. uploader.on('all', function (type, files) {
  670. switch (type) {
  671. case 'uploadFinished':
  672. setState('confirm', files);
  673. break;
  674. case 'startUpload':
  675. /* 添加额外的GET参数 */
  676. //var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '',
  677. // url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params);
  678. // widuu
  679. //uploader.option('server', url);
  680. uploader.option('server', uploadUrl);
  681. // end widuu
  682. setState('uploading', files);
  683. break;
  684. case 'uploadStart':
  685. // 文件文件超过多大使用分片上传
  686. videoMaxSize = editor.getOpt('VideoChunkMaxSize');
  687. // 分片上传的片的大小
  688. videoChunkSize = editor.getOpt('VideoChunkFileSize');
  689. // 判断文件是否大于最大限制
  690. if( files.size >= videoMaxSize ){
  691. // 第一次上传的初始化URl
  692. uploader.option('server' , makeBlockUploadUrl);
  693. // 开启分片上传
  694. uploader.option('chunked', true);
  695. // 每次上传的片的大小
  696. uploader.option('chunkSize' , videoChunkSize );
  697. // 网络重置次数
  698. uploader.option('chunkRetry' ,3 );
  699. // 以二进制内容发送
  700. uploader.option('sendAsBinary' ,true );
  701. // 由于限制问题,使用单线程上传
  702. uploader.option('threads' ,1 );
  703. // 分片上传标记
  704. isChunked = true;
  705. }
  706. break;
  707. case 'stopUpload':
  708. setState('paused', files);
  709. break;
  710. }
  711. });
  712. uploader.on('uploadBeforeSend', function (file, data, header) {
  713. //这里可以通过data对象添加POST参数
  714. header['X_Requested_With'] = 'XMLHttpRequest';
  715. // widuu 如果是qiniu上传并且不通过php上传就通过ajax来获取token,分片上传设置header
  716. if( (uploadType == 'qiniu' && isDirect != 'php') || isChunked ){
  717. var $file = $('#' + file.id),
  718. type = editor.getOpt('uploadSaveType'),
  719. path = editor.getOpt('qiniuUploadPath'),
  720. time = editor.getOpt('qiniuDatePath');
  721. //生成一个随机数目,防止批量上传的时候文件名同名出错
  722. var randNumber = (((1+Math.random())*0x10000)|0).toString(16).substring(1);
  723. var now = new Date();
  724. var filename = '';
  725. if( type == 'date' ){
  726. if( time != '' ){
  727. filename = path + new Date().Format(time) + '/'+ Date.parse(now)+randNumber+"."+file.file.ext;
  728. }else{
  729. filename = path + '/'+ Date.parse(now)+randNumber+"."+file.file.ext;
  730. }
  731. if( !isChunked ) data['key'] = filename;
  732. }else{
  733. filename = path + file.file.name;
  734. if( !isChunked ) data['key'] = filename;
  735. }
  736. var token ="";
  737. var url = editor.getActionUrl(editor.getOpt('getTokenActionName')),
  738. isJsonp = utils.isCrossDomainUrl(url);
  739. $.ajax({
  740. dataType : isJsonp ? 'jsonp':'json',
  741. async : false,
  742. method : 'post',
  743. data : {"key":filename},
  744. url : url,
  745. success:function(data) {
  746. if( data.state == 'SUCCESS' ){
  747. token = data.token;
  748. }else{
  749. $file.find('.error').text(data.error).show();
  750. }
  751. }
  752. });
  753. if( !isChunked ){
  754. data['token'] = token;
  755. }else{
  756. header['HOST'] = chunkUploadUrl;
  757. header['Content-Type'] = 'application/octet-stream';
  758. header['Authorization'] = "UpToken "+token;
  759. }
  760. }
  761. // end widuu
  762. });
  763. // widuu 通过接受服务器信息来构造url
  764. uploader.on('uploadAccept',function(obj,ret){
  765. // 片上传host
  766. chunkUploadUrl = ret.host ? ret.host : chunkUploadUrl;
  767. // 下一片的起始位置
  768. nextChunkOffset = ret.offset ? ret.offset : 0;
  769. // 如果块文件上传满了,创建块
  770. if( ret.offset == videoBlockSize ){
  771. // 剩余片大小
  772. $blockSize = obj.total - obj.end;
  773. // 创建块的url
  774. uploadUrl = makeBlockUploadUrl;
  775. // 如果是最后一块,并且最后一块不能与videoBlockSize,设置创建块大小
  776. if( obj.chunks - obj.chunk == 2 ){
  777. uploadUrl = chunkUploadUrl + '/mkblk/' + $blockSize;
  778. }
  779. qiniuCtx = qiniuCtx ? qiniuCtx + ',' + ret.ctx : ret.ctx;
  780. }else{
  781. // 上传片url
  782. uploadUrl = chunkUploadUrl + '/bput/' + ret.ctx + '/' + ret.offset;
  783. // 如果是最后一片,添加ctx
  784. if( obj.chunks - obj.chunk == 1 ){
  785. qiniuCtx += ',' + ret.ctx;
  786. }
  787. }
  788. // 设置上传片或者创建块url
  789. uploader.option('server', uploadUrl);
  790. return true;
  791. });
  792. // end widuu
  793. uploader.on('uploadProgress', function (file, percentage) {
  794. var $li = $('#' + file.id),
  795. $percent = $li.find('.progress span');
  796. $percent.css('width', percentage * 100 + '%');
  797. percentages[ file.id ][ 1 ] = percentage;
  798. updateTotalProgress();
  799. });
  800. uploader.on('uploadSuccess', function (file, ret) {
  801. var $file = $('#' + file.id);
  802. try {
  803. var json;
  804. // 分片上传通过服务器合成来返回数据
  805. if( isChunked ){
  806. var url = editor.getActionUrl(editor.getOpt('makeFileActionName')),
  807. isJsonp = utils.isCrossDomainUrl(url);
  808. $.ajax({
  809. dataType : isJsonp ? 'jsonp':'json',
  810. async : false,
  811. method : 'post',
  812. data : { ctx : qiniuCtx, type : file.type, size : file.size, name:file.name, host:chunkUploadUrl},
  813. url : url,
  814. success:function(data) {
  815. json = data;
  816. }
  817. });
  818. }else{
  819. var responseText = (ret._raw || ret);
  820. json = utils.str2json(responseText);
  821. }
  822. // var responseText = (ret._raw || ret),
  823. // json = utils.str2json(responseText);
  824. if (json.state == 'SUCCESS') {
  825. uploadVideoList.push({
  826. 'url': json.url,
  827. 'type': json.type,
  828. 'original':json.original
  829. });
  830. $file.append('<span class="success"></span>');
  831. } else {
  832. $file.find('.error').text(json.state).show();
  833. }
  834. } catch (e) {
  835. $file.find('.error').text(lang.errorServerUpload).show();
  836. }
  837. });
  838. uploader.on('uploadError', function (file, code) {
  839. });
  840. uploader.on('error', function (code, file) {
  841. if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') {
  842. addFile(file);
  843. }
  844. });
  845. uploader.on('uploadComplete', function (file, ret) {
  846. });
  847. $upload.on('click', function () {
  848. if ($(this).hasClass('disabled')) {
  849. return false;
  850. }
  851. if (state === 'ready') {
  852. uploader.upload();
  853. } else if (state === 'paused') {
  854. uploader.upload();
  855. } else if (state === 'uploading') {
  856. uploader.stop();
  857. }
  858. });
  859. $upload.addClass('state-' + state);
  860. updateTotalProgress();
  861. },
  862. getQueueCount: function () {
  863. var file, i, status, readyFile = 0, files = this.uploader.getFiles();
  864. for (i = 0; file = files[i++]; ) {
  865. status = file.getStatus();
  866. if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++;
  867. }
  868. return readyFile;
  869. },
  870. refresh: function(){
  871. this.uploader.refresh();
  872. }
  873. };
  874. })();