1/** 2 * @name Uploader.js 3 * @author Jiang 4 * @create 2012-12-20 5 * @version 0.1 6 * @description The Annouse funtion for HTML5/FLASH/FORM upload method. The 7 * function will autoly to choose the property method to ajust to client 8 * Browswer. This js function mainly borrow from youku.com's uploader.min.js 9 * and try to re-create it for fullfiting my requirement. 10 * @example 11 * 1. new Stream(); 12 * 2. var cfg = { 13 * extFilters : [".txt", ".gz"], 14 * fileFieldName : "FileData" 15 * }; 16 * new Stream(cfg); 17 */ 18(function(){ 19 var Provider, nIdCount = 0, aOtherBrowsers = ["Maxthon", "SE 2.X", "QQBrowser"], 20 nZero = 0, sOneSpace = " ", sLBrace = "{", sRBrace = "}", 21 ga = /(~-(\d+)-~)/g, rLBrace = /\{LBRACE\}/g, rRBrace = /\{RBRACE\}/g, 22 ea = { 23 "&" : "&", 24 "<" : "<", 25 ">" : ">", 26 '"' : """, 27 "'" : "'", 28 "/" : "/", 29 "`" : "`" 30 }, pa = Array.isArray && /\{\s*\[(?:native code|function)\]\s*\}/i.test(Array.isArray) 31 ? Array.isArray 32 : function(a) {return "array" === fToString(a)}, 33 sStreamMessagerId = "i_stream_message_container", 34 sCellFileTemplate = '<b class="stream-uploading-ico"></b>' + 35 '<div class="stream-file-name"><strong></strong></div>' + 36 '<div class="stream-process">' + 37 ' <a class="stream-cancel" href="javascript:void(0)">\u5220\u9664</a>' + 38 ' <span class="stream-process-bar"><span style="width: 0%;"></span></span>' + 39 ' <span class="stream-percent">0%</span>' + 40 '</div>' + 41 '<div class="stream-cell-infos">' + 42 ' <span class="stream-cell-info">\u901f\u5ea6\uff1a<em class="stream-speed"></em></span>' + 43 ' <span class="stream-cell-info">\u5df2\u4e0a\u4f20\uff1a<em class="stream-uploaded"></em></span>' + 44 ' <span class="stream-cell-info">\u5269\u4f59\u65f6\u95f4\uff1a<em class="stream-remain-time"></em></span>' + 45 '</div>', 46 sTotalContainer = '<div id="#totalContainerId#" class="stream-total-tips">' + 47 ' \u4e0a\u4f20\u603b\u8fdb\u5ea6\uff1a<span class="stream-process-bar"><span style="width: 0%;"></span></span>' + 48 ' <span class="stream-percent">0%</span>\uff0c\u5df2\u4e0a\u4f20<strong class="_stream-total-uploaded"> </strong>' + 49 ' \uff0c\u603b\u6587\u4ef6\u5927\u5c0f<strong class="_stream-total-size"> </strong>' + 50 '</div>', 51 sFilesContainer = '<div class="stream-files-scroll" style="height: #filesQueueHeight#px;"><ul id="#filesContainerId#"></ul></div>'; 52 53 function fGenerateId(prefix) { 54 var b = (new Date).getTime() + "_01v_" + ++nIdCount; 55 return prefix ? prefix + "_" + b : b; 56 } 57 function fGetRandom() { 58 return (new Date).getTime().toString().substring(8); 59 } 60 function fExtend(a, b){ 61 var c = 2 < arguments.length ? [arguments[2]] : null; 62 return function(){ 63 var d = "string" === typeof a ? b[a] : a,e=c ? [arguments[0]].concat(c) : arguments; 64 return d.apply(b||d, e); 65 }; 66 } 67 68 function fAddEventListener(a, b, c) { 69 a.addEventListener ? a.addEventListener(b, c, !1) : a.attachEvent ? a 70 .attachEvent("on" + b, c) : a["on" + b] = c; 71 } 72 73 function fRemoveEventListener(a, b, c) { 74 a.removeEventListener ? a.removeEventListener(b, c, !1) : a.detachEvent 75 ? a.detachEvent("on" + b, c) 76 : a["on" + b] = null; 77 } 78 79 function fToString(a) { 80 var b = { 81 "undefined" : "undefined", 82 number : "number", 83 "boolean" : "boolean", 84 string : "string", 85 "[object Function]" : "function", 86 "[object RegExp]" : "regexp", 87 "[object Array]" : "array", 88 "[object Date]" : "date", 89 "[object Error]" : "error" 90 }; 91 return b[typeof a] || b[Object.prototype.toString.call(a)] || (a ? "object" : "null"); 92 } 93 94 function fAddVars(json, url, c) { 95 var _array = [], _sep = "&", f = function(json, c) { 96 var e = url ? /\[\]$/.test(url) ? url : url + "[" + c + "]" : c; 97 "undefined" != e && "undefined" != c 98 && _array.push("object" === typeof json 99 ? fAddVars(json, e, !0) 100 : "[object Function]" === Object.prototype.toString.call(json) 101 ? encodeURIComponent(e) + "=" + encodeURIComponent(json()) 102 : encodeURIComponent(e) + "=" + encodeURIComponent(json)) 103 }; 104 if (!c && url) 105 _sep = /\?/.test(url) ? /\?$/.test(url) ? "" : "&" : "?", 106 _array.push(url), 107 _array.push(fAddVars(json)); 108 else if ("[object Array]" === Object.prototype.toString.call(json) 109 && "undefined" != typeof json) 110 for (var g = 0, c = json.length; g < c; ++g) 111 f(json[g], g); 112 else if ("undefined" != typeof json && null !== json && "object" === typeof json) 113 for (g in json) 114 f(json[g], g); 115 else 116 _array.push(encodeURIComponent(url) + "=" + encodeURIComponent(json)); 117 return _array.join(_sep).replace(/^&/, "").replace(/%20/g, "+") 118 } 119 120 function fMergeJson(base, extend) { 121 var result = {}; 122 for (var attr in base) 123 result[attr] = base[attr]; 124 for (var attr in extend) 125 result[attr] = extend[attr]; 126 return result; 127 } 128 129 function fAddClass(element, klass) { 130 fHasClass(element, klass) || (element.className += " " + klass); 131 } 132 133 function fHasClass(element, klass) { 134 return RegExp("(^| )" + klass + "( |$)").test(element.className); 135 } 136 137 function fRemoveClass(element, klass) { 138 element && (element.className = element.className.replace(RegExp("(^| )" + klass + "( |$)"), " ").replace(/^\s+|\s+$/g, "")); 139 } 140 141 function fContains(container, klass) { 142 if (!container) 143 return []; 144 if (container.querySelectorAll) 145 return container.querySelectorAll("." + klass); 146 for (var c = [], eles = container.getElementsByTagName("*"), e = eles.length, f = 0; f < e; f++) 147 fHasClass(eles[f], klass) && c.push(eles[f]); 148 return c; 149 } 150 151 function fCreateContentEle(content) { 152 var b = document.createElement("div"); 153 b.innerHTML = content; 154 content = b.childNodes; 155 return content[0].parentNode.removeChild(content[0]); 156 } 157 158 function fShowMessage(msg, warning) { 159 var o = document.getElementById(sStreamMessagerId);
160 o && (o.innerHTML += "<br>" + (!!warning ? ("<span style='color:red;'>" + msg + "</span>"): msg)) && (o.scrollTop = o.scrollHeight); 161 } 162 163 function fMessage(msg, VarVals, c, d) { 164 for (var nLIndex, nRIndex, sepIndex, argName, secondVar, s = [], _argName, length = msg.length;;) { 165 nLIndex = msg.lastIndexOf(sLBrace, length); 166 if (0 > nLIndex) 167 break; 168 nRIndex = msg.indexOf(sRBrace, nLIndex); 169 if (nLIndex + 1 >= nRIndex) 170 break; 171 argName = _argName = msg.substring(nLIndex + 1, nRIndex); 172 secondVar = null; 173 sepIndex = argName.indexOf(sOneSpace); 174 -1 < sepIndex && (secondVar = argName.substring(sepIndex + 1), argName = argName.substring(0, sepIndex)); 175 sepIndex = VarVals[argName]; 176 c && (sepIndex = c(argName, sepIndex, secondVar)); 177 "undefined" === typeof sepIndex && (sepIndex = "~-" + s.length + "-~", s.push(_argName)); 178 msg = msg.substring(0, nLIndex) + sepIndex + msg.substring(nRIndex + 1); 179 d || (length = nLIndex - 1); 180 } 181 return msg.replace(ga, function(msg, VarVals, c) { 182 return sLBrace + s[parseInt(c, 10)] + sRBrace 183 }).replace(rLBrace, sLBrace).replace(rRBrace, sRBrace); 184 } 185 186 function fIsObjOrFun(a, b) { 187 var c = typeof a; 188 return a && ("object" === c || !b && ("function" === c || "function" === fToString(a))) || !1; 189 } 190 function fIsNumber(val) { 191 return "number" === typeof val && isFinite(val); 192 } 193 function fIsArray(val) { 194 return "array" === fToString(val); 195 } 196 function fGetStyle(el,name) { 197 if (window.getComputedStyle) 198 return window.getComputedStyle(el, null)[name]; 199 else 200 return el.currentStyle[name]; 201 } 202 function fGetWidth(el) { 203 var val = el.offsetWidth, which = ['Left', 'Right']; 204 // display is none 205 if(val === 0) return 0; 206 207 for(var i = 0, a; a = which[i++];) { 208 val -= parseFloat(fGetStyle(el, "border" + a + "Width") ) || 0; 209 val -= parseFloat(fGetStyle(el, "padding" + a) ) || 0; 210 } 211 return val + 'px'; 212 } 213 function fGetHeight(el) { 214 var val = el.offsetHeight, which = ['Top', 'Bottom']; 215 // display is none 216 if(val === 0) return 0; 217 218 for(var i = 0, a; a = which[i++];) { 219 val -= parseFloat(fGetStyle(el, "border" + a + "Width") ) || 0; 220 val -= parseFloat(fGetStyle(el, "padding" + a) ) || 0; 221 } 222 return val + 'px'; 223 } 224 225 /** 226 * This function is for registering the function(s) on its prototype. 227 * @hostPrototype which is its host prototype. 228 * @funs functions, such as{aa:function(){}, bb:function(){}} 229 * @forseReg boolean: when the @hostPrototype don't have the function, then register it. 230 * true: do it, ignore the @hostPrototype whether has it. 231 * false: when not have it so that register it. 232 */ 233 function fRegFuns(hostPrototype, funs, forseReg, d) { 234 var e, f, g; 235 if (!hostPrototype || !funs) 236 return hostPrototype || {}; 237 if (d) 238 for (e = 0, g = d.length; e < g; ++e) 239 f = d[e], Object.prototype.hasOwnProperty.call(funs, f) && (forseReg || !(f in hostPrototype)) && (hostPrototype[f] = funs[f]); 240 else { 241 for (f in funs) 242 Object.prototype.hasOwnProperty.call(funs, f) && (forseReg || !(f in hostPrototype)) && (hostPrototype[f] = funs[f]); 243 ({valueOf : 0}).propertyIsEnumerable("valueOf") || fRegFuns(hostPrototype, funs, forseReg, "hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toString,toLocaleString,valueOf".split(",")); 244 } 245 return hostPrototype; 246 } 247 248 function fRegEvents() { 249 fRegFuns(this.constructor.prototype, { 250 publish : function(a) { 251 this._evts[a] || (this._evts[a] = null); 252 }, 253 on : function(a, b, c) { 254 var d = this._evts; 255 d[a] = {}; 256 d[a].type = a; 257 this.name && (d[a].type = this.name + ":" + a); 258 d[a].fn = function() { 259 b.apply(c, arguments); 260 }; 261 }, 262 after : function(a, b, c) { 263 this.on(a, b, c); 264 }, 265 fire : function(a) { 266 var b = this._evts[a]; 267 if (b) { 268 var c = {target : this, type : b.type}, 269 d = Array.prototype.slice.call(arguments, 1); 270 if (fIsObjOrFun(d[0])) 271 for (var e in c) 272 d[0][e] ? d[0]["_" + e] = c[e] : d[0][e] = c[e]; 273 else 274 d[0] = c; 275 "function" === fToString(b.fn) && b.fn.apply(this, d); 276 } 277 }, 278 detach : function(a) { 279 delete this._evts[a]; 280 } 281 }, !1); 282 this._evts = {}; 283 } 284 285 286 function Parent(args) { 287 fRegEvents.call(this); 288 this._isApplySuperClass || fRegFuns(this.constructor.prototype, Parent.prototype, !1); 289 if (args) { 290 for (var field in args) 291 this.set(field, args[field]); 292 } 293 "function" === typeof this.initializer && this.initializer.apply(this, arguments); 294 } 295 Parent.prototype = { 296 _isApplySuperClass : !0, 297 initializer : function() { 298 }, 299 get : function(key) { 300 return this.config[key]; 301 }, 302 set : function(key, val) { 303 var c; 304 key && "undefined" !== typeof val && key in this.config && (this.config[key] = val, c = key + "Change", this._evt && c in this._evt.events && this.fire(c)); 305 } 306 }; 307 308 function SWFReference(a, b, c) { 309 fRegEvents.call(this); 310 var d = this._id = fGenerateId("uploader-swf"), c = c || {}, e = ((c.version || sFlashVersion) + "").split("."), 311 e = SWFReference.isFlashVersionAtLeast(parseInt(e[0], 10), parseInt(e[1], 10), parseInt(e[2], 10)), 312 f = SWFReference.isFlashVersionAtLeast(8, 0, 0) && !e && c.useExpressInstall, 313 g = f ? sFlashDownload : b, 314 b = "<object ", h = "&SWFId=" + d + "&callback=" + sFlashEventHandler + "&allowedDomain=" + document.location.hostname; 315 SWFReference._instances[d] = this; 316 if (a && (e || f) && g) { 317 b += 'id="' + d + '" '; 318 b = Browser.ie ? b + ('classid="' + sIEFlashClassId + '" ') : b 319 + ('type="' + sShockwaveFlash + '" data="' + g + '" '); 320 b += 'width="100%" height="100%">'; 321 Browser.ie && (b += '<param name="movie" value="' + g + '"/>'); 322 for (var j in c.fixedAttributes) 323 oa.hasOwnProperty(j) 324 && (b += '<param name="' + j + '" value="' + c.fixedAttributes[j] + '"/>'); 325 for (var s in c.flashVars) 326 j = c.flashVars[s], "string" === typeof j 327 && (h += "&" + s + "=" + encodeURIComponent(j)); 328 h && (b += '<param name="flashVars" value="' + h + '"/>'); 329 a.innerHTML = b + "</object>"; 330 this.swf = document.getElementById(d); 331 } else 332 this.publish("wrongflashversion", {fireOnce : !0}), this.fire("wrongflashversion", {type : "wrongflashversion"}); 333 } 334 335 SWFReference.getFlashVersion = function() { 336 return "" + Browser.flashMajor + "." + ("" + Browser.flashMinor) + "." + ("" + Browser.flashRev); 337 }; 338 SWFReference.isFlashVersionAtLeast = function(a, b, c) {return true; 339 /*var d = parseInt(Browser.flashMajor, 10), e = parseInt(Browser.flashMinor, 10), f = parseInt( 340 Browser.flashRev, 10), a = parseInt(a || 0, 10), b = parseInt(b || 0, 341 10), c = parseInt(c || 0, 10); 342 return a === d ? b === e ? c <= f : b < e : a < d;*/ 343 }; 344 SWFReference._instances = SWFReference._instances || {}; 345 SWFReference.eventHandler = function(a, b) {SWFReference._instances[a]._eventHandler(b);}; 346 SWFReference.prototype = { 347 initializer : function() {}, 348 _eventHandler : function(a) { 349 "swfReady" === a.type ? (this.publish("swfReady", {fireOnce : !0}), this.fire("swfReady", a)) 350 : "log" !== a.type && this.fire(a.type, a); 351 }, 352 callSWF : function(a, b) { 353 b || (b = []); 354 return this.swf[a] ? this.swf[a].apply(this.swf, b) : null; 355 }, 356 toString : function() {return "SWF " + this._id;} 357 }; 358 SWFReference.prototype.constructor = SWFReference; 359 360 function SWFProvider(a) { 361 this.swfContainerId = fGenerateId("uploader"); 362 this.queue = this.swfReference = null; 363 this.buttonState = "up"; 364 this.config = { 365 enabled : !0, 366 multipleFiles : !0, 367 buttonClassNames : { 368 hover : "uploader-button-hover", 369 active : "uploader-button-active", 370 disabled : "uploader-button-disabled", 371 focus : "uploader-button-selected" 372 },
373 containerClassNames : {hover : "uphotBg"}, 374 fileFilters : a.fileFilters, 375 fileFieldName : "FileData", 376 simLimit : 1, 377 retryCount : 3, 378 postVarsPerFile : {}, 379 swfURL : "/swf/FlashUploader.swf", 380 uploadURL : "/fd" 381 }; 382 Parent.apply(this, arguments); 383 } 384 SWFProvider.prototype = { 385 constructor : SWFProvider, 386 name : "uploader", 387 buttonState : "up", 388 swfContainerId : null, 389 swfReference : null, 390 queue : null, 391 initializer : function() { 392 this.publish("fileselect"); 393 this.publish("uploadstart"); 394 this.publish("fileuploadstart"); 395 this.publish("uploadprogress"); 396 this.publish("totaluploadprogress"); 397 this.publish("uploadcomplete"); 398 this.publish("alluploadscomplete"); 399 this.publish("uploaderror"); 400 this.publish("mouseenter"); 401 this.publish("mouseleave"); 402 this.publish("mousedown"); 403 this.publish("mouseup"); 404 this.publish("click"); 405 }, 406 render : function(a) { 407 a && (this.renderUI(a), this.bindUI()); 408 }, 409 renderUI : function(a) { 410 this.contentBox = a; 411 this.contentBox.style.position = "relative"; 412 var b = fCreateContentEle("<div id='" + this.swfContainerId + "' style='position:absolute;top:0px; left: 0px; margin: 0; padding: 0; border: 0; width:100%; height:100%'></div>"); 413 b.style.width = (a.offsetWidth ? a.offsetWidth : a.scrollWidth) + "px"; 414 b.style.height = (a.offsetHeight ? a.offsetHeight : a.scrollHeight) + "px"; 415 this.contentBox.appendChild(b); 416 this.swfReference = new SWFReference(b, this.get("swfURL"), { 417 version : "10.0.45", 418 fixedAttributes : { 419 wmode : "transparent", 420 allowScriptAccess : "always", 421 allowNetworking : "all", 422 scale : "noscale" 423 } 424 }); 425 }, 426 bindUI : function() { 427 this.setMultipleFiles(); 428 this.setFileFilters(); 429 this.triggerEnabled(); 430 this.swfReference.on("swfReady", function() { 431 this.setMultipleFiles(); 432 this.setFileFilters(); 433 this.triggerEnabled(); 434 this.after("multipleFilesChange", this.setMultipleFiles, this); 435 this.after("fileFiltersChange", this.setFileFilters, this); 436 this.after("enabledChange", this.triggerEnabled, this); 437 }, this); 438 this.swfReference.on("fileselect", this.updateFileList, this); 439 this.swfReference.on("mouseenter", function() {this.setContainerClass("hover", !0);}, this); 440 this.swfReference.on("mouseleave", function() {this.setContainerClass("hover", !1);}, this); 441 }, 442 destroy : function() { 443 this.swfReference.detach("fileselect", this.updateFileList, this); 444 this.swfReference.detach("mouseenter", function() {this.setContainerClass("hover", !0);}, this); 445 this.swfReference.detach("mouseleave", function() {this.setContainerClass("hover", !1);}, this); 446 if (this.contentBox) { 447 while (this.contentBox.firstChild) { 448 var oldNode = this.contentBox.removeChild(this.contentBox.firstChild); 449 oldNode = null; 450 } 451 } 452 this.swfReference = null; 453 }, 454 setContainerClass : function(a, b) { 455 b ? fAddClass(this.contentBox, this.get("containerClassNames")[a]) : fRemoveClass( 456 this.contentBox, this.get("containerClassNames")[a]); 457 }, 458 setFileFilters : function() { 459 this.swfReference && 0 < this.get("fileFilters").length 460 && this.swfReference.callSWF("setFileFilters", [[{description: "\u81ea\u5b9a\u4e49\u6587\u4ef6", extensions: "*" + this.get("fileFilters").join(";*"), macType: "*" + this.get("fileFilters").join(";*")}]]); 461 }, 462 setMultipleFiles : function() { 463 this.swfReference && this.swfReference.callSWF("setAllowMultipleFiles", [this.get("multipleFiles")]); 464 }, 465 triggerEnabled : function() { 466 this.get("enabled") 467 ? (this.swfReference.callSWF("enable"), this.swfReference.swf.setAttribute("aria-disabled", "false")) 468 : (this.swfReference.callSWF("disable"), this.swfReference.swf.setAttribute("aria-disabled", "true")) 469 }, 470 updateFileList : function(a) { 471 this.swfReference.swf.focus(); 472 for (var a = a.fileList, b = [], c = this.swfReference, d = 0; d < a.length; d++) { 473 var e = {}; 474 e.id = a[d].fileId; 475 e.name = a[d].fileReference.name; 476 e.size = a[d].fileReference.size; 477 e.type = a[d].fileReference.type; 478 e.dateCreated = a[d].fileReference.creationDate; 479 e.dateModified = a[d].fileReference.modificationDate; 480 e.uploader = c; 481 b.push(new SWFUploader(e)); 482 } 483 0 < b.length && this.fire("fileselect", {fileList : b}); 484 }, 485 uploadEventHandler : function(a) { 486 switch (a.type) { 487 case "executor:uploadstart" : 488 this.fire("fileuploadstart", a); 489 break; 490 case "executor:uploadprogress" : 491 this.fire("uploadprogress", a); 492 break; 493 case "uploaderqueue:totaluploadprogress" : 494 this.fire("totaluploadprogress", a); 495 break; 496 case "executor:uploadcomplete" : 497 this.fire("uploadcomplete", a); 498 break; 499 case "uploaderqueue:alluploadscomplete" : 500 this.queue = null; 501 this.fire("alluploadscomplete", a); 502 break; 503 case "executor:uploaderror" :
504 case "uploaderqueue:uploaderror" : 505 this.fire("uploaderror", a); 506 break; 507 case "executor:uploadcancel" : 508 case "uploaderqueue:uploadcancel" : 509 this.fire("uploadcancel", a); 510 } 511 }, 512 upload : function(uploader, url, postVars) { 513 var url = url || this.get("uploadURL"), postVars = fMergeJson(postVars, this.get("postVarsPerFile")), id = uploader.id, 514 postVars = postVars.hasOwnProperty(id) ? postVars[id] : postVars; 515 uploader instanceof SWFUploader 516 && (uploader.on("uploadstart", this.uploadEventHandler, this), 517 uploader.on("uploadprogress", this.uploadEventHandler, this), 518 uploader.on("uploadcomplete", this.uploadEventHandler, this), 519 uploader.on("uploaderror", this.uploadEventHandler, this), 520 uploader.on("uploadcancel", this.uploadEventHandler, this), 521 uploader.startUpload(url, postVars, this.get("fileFieldName"))); 522 } 523 }; 524 525 function SWFUploader(a) { 526 this.bytesSpeed = this.bytesPrevLoaded = 0; 527 this.bytesSpeeds = []; 528 this.preTime = this.remainTime = 0; 529 this.config = { 530 id : "", 531 name : "", 532 size : "", 533 type : "", 534 dateCreated : "", 535 dateModified : "", 536 uploader : "" 537 }; 538 Parent.apply(this, arguments); 539 } 540 SWFUploader.prototype = { 541 constructor : SWFUploader, 542 name : "executor", 543 initializer : function() { 544 this.id = fGenerateId("file"); 545 }, 546 swfEventHandler : function(a) { 547 if (a.id === this.get("id")) 548 switch (a.type) { 549 case "uploadstart" : 550 this.fire("uploadstart", {uploader : this.get("uploader")}); 551 break; 552 case "uploadprogress" : 553 var b = (new Date).getTime(), c = (b - this.preTime) / 1E3, d = 0; 554 if (1 <= c || 0 == this.bytesPrevLoaded) { 555 this.bytesSpeed = Math.round((a.bytesLoaded - this.bytesPrevLoaded) / c); 556 this.bytesPrevLoaded = a.bytesLoaded; 557 this.preTime = b; 558 5 < this.bytesSpeeds.length && this.bytesSpeeds.shift(); 559 this.bytesSpeeds.push(this.bytesSpeed); 560 for (b = 0; b < this.bytesSpeeds.length; b++) 561 d += this.bytesSpeeds[b]; 562 this.bytesSpeed = Math.round(d / this.bytesSpeeds.length); 563 this.remainTime = Math.ceil((a.bytesTotal - a.bytesLoaded) / this.bytesSpeed); 564 } 565 this.fire("uploadprogress", { 566 originEvent : a, 567 bytesLoaded : a.bytesLoaded, 568 bytesSpeed : this.bytesSpeed, 569 bytesTotal : a.bytesTotal, 570 remainTime : this.remainTime, 571 percentLoaded : Math.min(100, Math.round(1E4 * a.bytesLoaded / a.bytesTotal) / 100) 572 }); 573 break; 574 case "uploadcomplete" : 575 this.fire("uploadfinished", {originEvent : a}); 576 break; 577 case "uploadcompletedata" : 578 this.fire("uploadcomplete", { 579 originEvent : a, 580 data : a.data 581 }); 582 break; 583 case "uploadcancel" : 584 this.fire("uploadcancel", {originEvent : a}); 585 break; 586 case "uploaderror" : 587 this.fire("uploaderror", { 588 originEvent : a, 589 status : a.status, 590 statusText : a.message, 591 source : a.source 592 }); 593 } 594 }, 595 startUpload : function(url, postVars, fileFieldName) { 596 if (this.get("uploader")) { 597 var uploader = this.get("uploader"), fileFieldName = fileFieldName || "FileData", id = this.get("id"), postVars = postVars || null; 598 uploader.on("uploadstart", this.swfEventHandler, this); 599 uploader.on("uploadprogress", this.swfEventHandler, this); 600 uploader.on("uploadcomplete", this.swfEventHandler, this); 601 uploader.on("uploadcompletedata", this.swfEventHandler, this); 602 uploader.on("uploaderror", this.swfEventHandler, this); 603 this.remainTime = this.bytesSpeed = this.bytesPrevLoaded = 0; 604 this.bytesSpeeds = []; 605 if (!this.preTime) 606 this.preTime = (new Date).getTime(); 607 uploader.callSWF("upload", [id, url, postVars, fileFieldName]); 608 } 609 }, 610 cancelUpload : function() { 611 this.get("uploader") 612 && (this.get("uploader").callSWF("cancel", [this.get("id")]), this.fire("uploadcancel")); 613 } 614 }; 615 616 function StreamProvider(a) { 617 this.buttonBinding = this.queue = this.fileInputField = null; 618 this.config = { 619 enabled : !0, 620 multipleFiles : !0, 621 dragAndDropArea : "", 622 dragAndDropTips : "", 623 fileFilters : a.fileFilters, 624 fileFieldName : a.fileFieldName || "FileData", 625 simLimit : 1, 626 retryCount : 3, 627 postVarsPerFile : {}, 628 uploadURL : "/upload" 629 }; 630 Parent.apply(this, arguments); 631 } 632 StreamProvider.prototype = { 633 constructor : StreamProvider, 634 name : "stream_provider", 635 initializer: function(){ 636 this.publish("fileselect"); 637 this.publish("uploadstart"); 638 this.publish("fileuploadstart"); 639 this.publish("uploadprogress"); 640 this.publish("totaluploadprogress"); 641 this.publish("uploadcomplete"); 642 this.publish("alluploadscomplete"); 643 this.publish("uploaderror"); 644 this.publish("dragenter"); 645 this.publish("dragover"); 646 this.publish("dragleave"); 647 this.publish("drop"); 648 }, 649 render : function(a) { 650 a && (this.renderUI(a), this.bindUI()); 651 }, 652 renderUI : function(a) { 653 this.contentBox = a; 654 this.fileInputField = fCreateContentEle("<input type='file' style='visibility:hidden;width:0px;height:0px;opacity:0;position:absolute;
654left:-1000px;'>"); 655 this.get("dragAndDropArea") && !this.get("dragAndDropArea").nodeType && this.set("dragAndDropArea", document.getElementById(this.get("dragAndDropArea"))); 656 bDraggable && this.get("dragAndDropArea") && (fAddClass(this.get("dragAndDropArea"), 'stream-browse-drag-files-area'), this.get("dragAndDropArea").appendChild(fCreateContentEle(this.get("dragAndDropTips")))); 657 }, 658 bindUI : function() { 659 this.bindSelectButton(); 660 this.setMultipleFiles(); 661 this.setFileFilters(); 662 this.bindDropArea(); 663 this.triggerEnabled(); 664 this.after("multipleFilesChange", this.setMultipleFiles, this); 665 this.after("fileFiltersChange", this.setFileFilters, this); 666 this.after("enabledChange", this.triggerEnabled, this); 667 this.after("dragAndDropAreaChange", this.bindDropArea, this); 668 fAddEventListener(this.fileInputField, "change", fExtend(this.updateFileList, this)); 669 }, 670 bindDropArea : function() { 671 var a = this.get("dragAndDropArea"); 672 this.dropBinding = fExtend(this.dragEventHandler, this); 673 null !== a && (fAddEventListener(a, "drop", this.dropBinding), 674 fAddEventListener(a, "dragenter", this.dropBinding), 675 fAddEventListener(a, "dragover", this.dropBinding), 676 fAddEventListener(a, "dragleave", this.dropBinding)); 677 }, 678 destroy : function() { 679 this.buttonBinding = fExtend(this.openFileSelectDialog, this); 680 fRemoveEventListener(this.contentBox, "click", this.buttonBinding); 681 fRemoveEventListener(this.fileInputField, "change", fExtend(this.updateFileList, this)); 682 this.detach("multipleFilesChange", this.setMultipleFiles, this); 683 this.detach("fileFiltersChange", this.setFileFilters, this); 684 this.detach("enabledChange", this.triggerEnabled, this); 685 this.detach("dragAndDropAreaChange", this.bindDropArea, this); 686 687 var a = this.get("dragAndDropArea"); 688 null !== a && this.dropBinding != null && (fRemoveEventListener(a, "drop", this.dropBinding), 689 fRemoveEventListener(a, "dragenter", this.dropBinding), 690 fRemoveEventListener(a, "dragover", this.dropBinding), 691 fRemoveEventListener(a, "dragleave", this.dropBinding)); 692 this.fileInputField = null; 693 this.buttonBinding = null; 694 this.dropBinding = null; 695 }, 696 dragEventHandler : function(evt) { 697 evt = evt || window.event; 698 evt.preventDefault ? evt.preventDefault() : evt.returnValue = !1; 699 evt.stopPropagation ? evt.stopPropagation() : evt.cancelBubble = !0; 700 switch (evt.type) { 701 case "dragenter" : 702 this.fire("dragenter"); 703 break; 704 case "dragover" : 705 this.fire("dragover"); 706 break; 707 case "dragleave" : 708 this.fire("dragleave"); 709 break; 710 case "drop" : 711 var self = this, callback = function(files) { 712 for (var list = [], c = 0; c < files.length; c++) 713 list.push(new StreamUploader(files[c])); 714 0 < list.length && self.fire("fileselect", {fileList : list}); 715 }; 716 if (bFolder) { 717 var items = evt.dataTransfer.items; 718 if (items.length && items[items.length - 1]) { 719 var entry = items[items.length - 1].webkitGetAsEntry() || items[items.length - 1].getAsEntry(); 720 var entries = []; 721 for (var i = 0; i < items.length; i++) { 722 entries.push(items[i].webkitGetAsEntry() || items[i].getAsEntry()); 723 } 724 entry && this._handleFileTreeEntries(entries, callback); 725 } 726 } else { 727 var files = evt.dataTransfer.files; 728 if (evt.MOZ_SOURCE_MOUSE) { 729 for (var list = [], c = 0; c < files.length; c++) 730 files[c].size > 0 && list.push(files[c]); 731 files = list; 732 } 733 callback(files, this); 734 } 735 this.fire("drop"); 736 } 737 }, 738 _handleFileTreeEntries: function(entries, callback) { 739 for (var i = 0; i < entries.length; i++) { 740 this._handleFileTreeEntry(entries[i], callback); 741 } 742 }, 743 _handleFileTreeEntry: function(entry, callback) { 744 callback.pending || (callback.pending = 0); 745 callback.pending++; 746 callback.files || (callback.files = []); 747 var that = this, reader, path = entry.fullPath.replace(/^\//, "").replace(/(.+?)\/?$/, "$1"), entries = [], succeed = function(entries) { 748 that._handleFileTreeEntries(entries, callback); 749 (--callback.pending === 0) && callback(callback.files, self); 750 }, error = function(e) { 751 alert("Read file Error: " + e); 752 console && console.log(e); 753 }, read = function() { 754 reader.readEntries(function(results) { 755 if (results.length) { 756 entries = entries.concat(results); 757 read(); 758 } else { 759 succeed(entries);
760 if (entries && entries.length === 0 && path != null && path != '' && path != '/') 761 fShowMessage("\u5FFD\u7565\u7A7A\u6587\u4EF6\u5939\uFF1A`" + path + "`", true); 762 } 763 }, error); 764 }; 765 if (entry.isFile) { 766 entry.file(function(f) { 767 f.RelativePath = path; /** self define argument */ 768 callback.files.push(f); 769 (--callback.pending === 0) && callback(callback.files, self); 770 }); 771 } else if (entry.isDirectory) { 772 reader = entry.createReader(); 773 read(); 774 } 775 }, 776 rebindFileField : function() { 777 this.fileInputField = fCreateContentEle("<input type='file' style='visibility:hidden;width:0px;height:0px;opacity:0;position:absolute;left:-1000px;'>"); 778 this.get("dragAndDropArea") && !this.get("dragAndDropArea").nodeType && this.set("dragAndDropArea", document.getElementById(this.get("dragAndDropArea"))); 779 bDraggable && (fAddClass(this.get("dragAndDropArea"), 'stream-browse-drag-files-area')); 780 this.setMultipleFiles(); 781 this.setFileFilters(); 782 fAddEventListener(this.fileInputField, "change", fExtend(this.updateFileList, this)); 783 }, 784 bindSelectButton : function() { 785 this.buttonBinding = fExtend(this.openFileSelectDialog, this); 786 fAddEventListener(this.contentBox, "click", this.buttonBinding); 787 }, 788 setMultipleFiles : function() { 789 !0 === this.get("multipleFiles") 790 && this.fileInputField.setAttribute("multiple", "multiple") 791 }, 792 setFileFilters : function() { 793 var a = this.get("fileFilters"); 794 0 < a.length ? this.fileInputField.setAttribute("accept", a 795 .join(",")) : this.fileInputField.setAttribute( 796 "accept", "") 797 }, 798 triggerEnabled : function() { 799 var a = this.get("dragAndDropArea"); 800 fRemoveClass(a, 'stream-disabled'); 801 if (this.get("enabled") && null === this.buttonBinding) 802 this.bindSelectButton(), this.bindDropArea(), fRemoveClass(a, 'stream-disabled'); 803 else if (!this.get("enabled") && this.buttonBinding) { 804 fRemoveEventListener(this.contentBox, "click", this.buttonBinding), 805 this.buttonBinding = null; 806 807 null !== a && this.dropBinding != null && (fRemoveEventListener(a, "drop", this.dropBinding), 808 fRemoveEventListener(a, "dragenter", this.dropBinding), 809 fRemoveEventListener(a, "dragover", this.dropBinding), 810 fRemoveEventListener(a, "dragleave", this.dropBinding), 811 fAddClass(a, 'stream-disabled')); 812 } 813 }, 814 updateFileList : function(a) { 815 for (var a = a.target.files, b = [], c = 0; c < a.length; c++) { 816 if (a[c].name == ".") continue; 817 b.push(new StreamUploader(a[c])); 818 } 819 0 < b.length && this.fire("fileselect", {fileList : b}); 820 this.rebindFileField(); 821 }, 822 openFileSelectDialog : function(a) { 823 this.fileInputField && this.fileInputField.click && a.target != this.fileInputField && this.fileInputField.click(); 824 }, 825 uploadEventHandler : function(a) { 826 switch (a.type) { 827 case "executor:uploadstart" : 828 this.fire("fileuploadstart", a); 829 break; 830 case "executor:uploadprogress" : 831 this.fire("uploadprogress", a); 832 break; 833 case "uploaderqueue:totaluploadprogress" : 834 this.fire("totaluploadprogress", a); 835 break; 836 case "executor:uploadcomplete" : 837 this.fire("uploadcomplete", a); 838 break; 839 case "uploaderqueue:alluploadscomplete" : 840 this.queue = null; 841 this.fire("alluploadscomplete", a); 842 break; 843 case "executor:uploaderror" : 844 case "uploaderqueue:uploaderror" : 845 this.fire("uploaderror", a); 846 break; 847 case "executor:uploadcancel" : 848 case "uploaderqueue:uploadcancel" : 849 this.fire("uploadcancel", a); 850 } 851 }, 852 upload : function(uploader, url, postVars) { 853 var url = url || this.get("uploadURL"), postVars = fMergeJson(postVars, this.get("postVarsPerFile")), 854 d = uploader.id, postVars = postVars.hasOwnProperty(d) ? postVars[d] : postVars; 855 uploader instanceof StreamUploader 856 && (uploader.on("uploadstart", this.uploadEventHandler, this), 857 uploader.on("uploadprogress", this.uploadEventHandler, this), 858 uploader.on("uploadcomplete", this.uploadEventHandler, this), 859 uploader.on("uploaderror", this.uploadEventHandler, this), 860 uploader.on("uploadcancel", this.uploadEventHandler, this), 861 uploader.startUpload(url, postVars, this.get("fileFieldName"))); 862 } 863 }; 864 865 var StreamUploader = function(){ 866 this.remainTime = this.bytesSpeed = this.bytesStart = this.bytesPrevLoaded = 0; 867 this.bytesSpeeds = []; 868 this.retryTimes = this.preTime = 0; 869 this.config = { 870 id : "", 871 name : "", 872 size : "", 873 type : "", 874 dateCreated : "", 875 dateModified : "", 876 uploader : "", 877 uploadURL : "", 878 serverAddress : "", 879 portionSize : 10485760, 880 parameters : {}, 881 fileFieldName : "FileData", 882 uploadMethod : "formUpload" 883 }; 884 Parent.apply(this, arguments); 885 }; 886 StreamUploader.isValidFile = function(a) {return "undefined" != typeof File && a instanceof File;}; 887 StreamUploader.canUpload = function() {return "undefined" != typeof FormData;}; 888 StreamUploader.prototype = { 889 constructor : StreamUploader, 890 name: "executor", 891 initializer: function(file){ 892 this.XHR = null; 893 this.retryTimes = 10;
894 this.retriedTimes = 0; 895 this.file = null; 896 this.fileId = null; 897 this.filePiece = 10485760;/** 10M. */ 898 this.fileSizeValue = 0; 899 this.fileStartPosValue = null; 900 901 this.durationTime = 2000; 902 this.xhrHandler = null; 903 904 var b = StreamUploader.isValidFile(file) ? file : StreamUploader.isValidFile(file.file) ? file.file : !1; 905 this.get("id") || this.set("id", fGenerateId("file")); 906 if (b && StreamUploader.canUpload()) { 907 if (!this.file) 908 this.file = b; 909 this.set("name", b.RelativePath || b.webkitRelativePath || b.name || b.fileName); 910 if (this.get("size") != (b.size || b.fileSize)) 911 this.set("size", b.size || b.fileSize); 912 this.get("type") || this.set("type", b.type); 913 b.lastModifiedDate && !this.get("dateModified") && this.set("dateModified", b.lastModifiedDate); 914 } 915 }, 916 resetXhr: function(){ 917 if(this.XHR){ 918 try{ 919 this.XHR.upload.removeEventListener("progress", this.xhrHandler), 920 this.XHR.upload.removeEventListener("error", this.xhrHandler), 921 this.XHR.upload.removeEventListener("abort", this.xhrHandler), 922 this.XHR.removeEventListener("loadend", this.xhrHandler), 923 this.XHR.removeEventListener("error", this.xhrHandler), 924 this.XHR.removeEventListener("abort", this.xhrHandler), 925 this.XHR.removeEventListener("readystatechange", this.xhrHandler); 926 }catch(e){throw e;} 927 this.XHR = null; 928 } 929 }, 930 formUpload : function() { 931 this.resetXhr(); 932 this.XHR = new XMLHttpRequest; 933 this.uploadEventHandler = fExtend(this.uploadEventHandler, this); 934 var fd = new FormData, fileFileName = this.get("fileFieldName"), 935 url = this.get("uploadURL"), _xhr = this.XHR, _upload = _xhr.upload; 936 this.set("uploadMethod", "formUpload"); 937 this.bytesStart = 0; 938 this.preTime = (new Date).getTime(); 939 for (var I in this.get('parameters')) I && fd.append(I, this.get('parameters')[I]); 940 // need set file after normal form items. 941 fd.append(fileFileName, this.file); 942 _xhr.addEventListener("loadstart", this.uploadEventHandler, !1); 943 _upload.addEventListener("progress", this.uploadEventHandler, !1); 944 _xhr.addEventListener("load", this.uploadEventHandler, !1); 945 _xhr.addEventListener("error", this.uploadEventHandler, !1); 946 _upload.addEventListener("error", this.uploadEventHandler, !1); 947 _upload.addEventListener("abort", this.uploadEventHandler, !1); 948 _xhr.addEventListener("abort", this.uploadEventHandler, !1); 949 _xhr.addEventListener("loadend", this.uploadEventHandler, !1); 950 _xhr.addEventListener("readystatechange", this.uploadEventHandler, !1); 951 _xhr.open("POST", url, !0); 952 _xhr.send(fd); 953 this.fire("uploadstart", {xhr : _xhr}); 954 }, 955 streamUpload: function(pos){ 956 /** whether continue uploading. */ 957 var _url = this.get("uploadURL"); 958 this.resetXhr(); 959 this.resume = false; 960 this.bytesStart = pos; 961 this.XHR = new XMLHttpRequest; 962 this.xhrHandler = fExtend(this.uploadEventHandler, this); 963 //register callback function 964 var _xhr = this.XHR, upload = _xhr.upload; 965 _xhr.addEventListener("loadstart", this.xhrHandler, !1); 966 upload.addEventListener("progress", this.xhrHandler, !1); 967 _xhr.addEventListener("load", this.xhrHandler, !1); 968 _xhr.addEventListener("error", this.xhrHandler, !1); 969 upload.addEventListener("error", this.xhrHandler, !1); 970 upload.addEventListener("abort", this.xhrHandler, !1); 971 _xhr.addEventListener("abort", this.xhrHandler, !1); 972 _xhr.addEventListener("loadend", this.xhrHandler, !1); 973 _xhr.addEventListener("readystatechange", this.xhrHandler, !1); 974 var blob = this.sliceFile(this.file, pos, pos + this.filePiece); 975 var range = "bytes "+ pos + "-"+ (pos + blob.size) + "/" + this.get("size"); 976 this.preTime = (new Date).getTime(); 977 _xhr.open("POST", _url, !0); 978 _xhr.setRequestHeader("Content-Range", range); 979 _xhr.send(blob); 980 0 === pos && this.fire("uploadstart", {xhr : _xhr}); 981 }, 982 resumeUpload: function() { 983 /** when Browse has `File`, but has not `File.slice` */ 984 if (!bFileSlice) { 985 this.formUpload(); 986 return; 987 } 988 989 this.resetXhr(); 990 this.XHR = new XMLHttpRequest; 991 this.resume = true; 992 993 var _url = this.get("uploadURL") + "&" + fGetRandom(); 994 this.xhrHandler = fExtend(this.uploadEventHandler, this); 995 this.XHR.addEventListener("loadstart", this.xhrHandler, !1); 996 this.XHR.addEventListener("load", this.xhrHandler, !1); 997 this.XHR.addEventListener("abort", this.xhrHandler, !1); 998 this.XHR.addEventListener("error", this.xhrHandler, !1); 999 this.XHR.addEventListener("loadend", this.xhrHandler, !1); 1000 this.XHR.addEventListener("readystatechange", this.xhrHandler, !1); 1001 this.preTime = (new Date).getTime(); 1002 this.XHR.open("GET", _url, !0); 1003 this.XHR.send(null); 1004 }, 1005 retry: function(){
1006 this.retriedTimes++; 1007 var g = this; 1008 2 > this.retriedTimes ? this.resumeUpload() 1009 : (this.timeoutHandler && clearTimeout(this.timeoutHandler), this.timeoutHandler = setTimeout(function() {g.resumeUpload()}, 1E4)); 1010 }, 1011 uploadEventHandler: function(event){ 1012 var xhr = this.XHR, method = this.get("uploadMethod"); 1013 switch(event.type){ 1014 case "load": 1015 var uploaded = 0; 1016 var respJson = null; 1017 var bError = !1; 1018 try { 1019 if (xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 308)) { 1020 uploaded = (respJson = eval("(" + xhr.responseText + ")")) ? respJson.start : -1; 1021 } else if (xhr.status < 500 && xhr.status >= 400) { 1022 bError = !0; 1023 } else if (xhr.status < 200) {return;} 1024 /** the response can't process the request, so throws out the error. */ 1025 bError = bError || respJson.success == false; 1026 } catch(e) { 1027 bError = "formUpload" === method || this.retriedTimes > this.retryTimes; 1028 if (!bError) { 1029 this.retry(); 1030 return; 1031 } 1032 } 1033 if (bError) { 1034 this.fire("uploaderror", { 1035 originEvent : event, 1036 status : xhr.status, 1037 statusText : xhr.responseText, 1038 source : respJson && respJson.message 1039 }); 1040 return; 1041 } 1042 //check whether upload complete yet 1043 if(uploaded < this.get("size") -1) { 1044 this.retriedTimes = 0; 1045 /** StreamUploader request is over and mark the date. */ 1046 this.streamUpload(uploaded); 1047 } else { 1048 this.fire("uploadcomplete", {originEvent : event, data : event.target.responseText}); 1049 } 1050 break; 1051 case "error": 1052 this.retriedTimes < this.retryTimes ? this.retry() 1053 : this.fire("uploaderror", { 1054 originEvent : event, 1055 status : xhr.status, 1056 statusText : xhr.statusText, 1057 source : "io" 1058 }); 1059 break; 1060 case "abort": 1061 this.fire("uploadcancel", {originEvent : event}); 1062 break; 1063 case "progress": 1064 var total = this.get("size"), loaded = this.bytesStart + event.loaded, 1065 now = (new Date).getTime(), cost = (now - this.preTime) / 1E3, totalSpeeds = 0; 1066 if (0.68 <= cost || 0 === this.bytesSpeeds.length) { 1067 this.bytesPrevLoaded = Math.max(this.bytesStart, this.bytesPrevLoaded); 1068 this.bytesSpeed = Math.round((loaded - this.bytesPrevLoaded) / cost); 1069 this.bytesPrevLoaded = loaded; 1070 this.preTime = now; 1071 5 < this.bytesSpeeds.length && this.bytesSpeeds.shift(); 1072 5 > this.bytesSpeeds.length && (this.bytesSpeed = this.bytesSpeed / 2); 1073 this.bytesSpeeds.push(this.bytesSpeed); 1074 for (var i = 0; i < this.bytesSpeeds.length; i++) 1075 totalSpeeds += this.bytesSpeeds[i]; 1076 this.bytesSpeed = Math.round(totalSpeeds / this.bytesSpeeds.length); 1077 this.remainTime = Math.ceil((total - loaded) / this.bytesSpeed); 1078 } 1079 this.fire("uploadprogress", { 1080 originEvent : event, 1081 bytesLoaded : loaded, 1082 bytesTotal : total, 1083 bytesSpeed : this.bytesSpeed, 1084 remainTime : this.remainTime, 1085 percentLoaded : Math.min(100, Math.floor(1E4 * loaded / total) / 100) 1086 }); 1087 break; 1088 case "readystatechange": 1089 this.fire("readystatechange", {readyState : event.target.readyState, originEvent : event}); 1090 } 1091 }, 1092 startUpload: function(url, postVars, fileFieldName){ 1093 this.fileStartPosValue = null; 1094 this.retriedTimes = 0; 1095 1096 postVars.name = this.get("name"); 1097 postVars.size = this.get("size"); 1098 var method = this.get("uploadMethod"); 1099 this.set("uploadURL", 'formUpload' === method ? url : fAddVars(postVars, url)); 1100 this.set("parameters", postVars); 1101 this.set("fileFieldName", fileFieldName); 1102 this.remainTime = this.bytesSpeed = this.bytesPrevLoaded = 0; 1103 this.bytesSpeeds = []; 1104 this.resetXhr(); 1105 switch (method) { 1106 case "formUpload" : 1107 this.formUpload(); 1108 break; 1109 case "streamUpload" : 1110 this.streamUpload(); 1111 break; 1112 case "resumeUpload" : 1113 this.resumeUpload() 1114 } 1115 }, 1116 sliceFile: function(f, startPos, endPos){ 1117 startPos = startPos || 0; 1118 endPos = endPos || 0; 1119 return f.slice ? f.slice(startPos, endPos) : f.webkitSlice ? f.webkitSlice(startPos, endPos) : f.mozSlice ? f.mozSlice(startPos, endPos) : f; 1120 }, 1121 cancelUpload : function() { 1122 this.XHR && (this.XHR.abort(), this.resetXhr()); 1123 } 1124 }; 1125 1126 function Main(cfg){ 1127 cfg = cfg || {}; 1128 this.bStreaming = bStreaming; 1129 this.bDraggable = bDraggable; 1130 this.uploadInfo = {}; 1131 this.config = { 1132 enabled : !0, 1133 customered : !!cfg.customered, 1134 formed : !!cfg.formed, 1135 multipleFiles : !!cfg.multipleFiles, 1136 autoRemoveCompleted : !!cfg.autoRemoveCompleted, 1137 autoUploading : cfg.autoUploading == null ? true : !!cfg.autoUploading, 1138 dragAndDropArea: cfg.dragAndDropArea, 1139 dragAndDropTips: cfg.dragAndDropTips || "<span>ææä»¶(æä»¶å¤¹)ææ½å°è¿é</span>", 1140 fileFieldName : cfg.fileFieldName || "FileData", 1141 browser : cfg.browser, 1142 browseFileId : cfg.browseFileId || "i_select_files", 1143 browseFileBtn : cfg.browseFileBtn || "<div>è¯·éæ©æä»¶</div>", 1144 filesQueueId : cfg.filesQueueId || "i_stream_files_queue", 1145 filesQueueHeight : cfg.filesQueueHeight || 450, 1146 messagerId : cfg.messagerId || "i_stream_message_container", 1147 onSelect : cfg.onSelect, 1148 onRepeatedFile : cfg.onRepeatedFile, 1149 onAddTask: cfg.onAddTask, 1150 onMaxSizeExceed : cfg.onMaxSizeExceed, 1151 onFileCountExceed : cfg.onFileCountExceed, 1152 onExtNameMismatch : cfg.onExtNameMismatch, 1153 onCancel : cfg.onCancel, 1154 onStop : cfg.onStop, 1155 onCancelAll : cfg.onCancelAll, 1156 onComplete : cfg.onComplete, 1157 onQueueComplete: cfg.onQueueComplete, 1158 onUploadProgress: cfg.onUploadProgress, 1159 onUploadError: cfg.onUploadError, 1160 onDestroy: cfg.onDestroy, 1161 maxSize : cfg.maxSize || 2147483648, 1162 simLimit : cfg.simLimit || 10000, 1163 fileFilters: fIsArray(cfg.extFilters) ? cfg.extFilters : [], 1164 retryCount : cfg.retryCount || 5, 1165 postVarsPerFile : cfg.postVarsPerFile || {}, 1166 swfURL : cfg.swfURL || "/swf/FlashUploader.swf", 1167 tokenURL : cfg.tokenURL || "/tk", 1168 frmUploadURL : cfg.frmUploadURL || Browser.firefox ? "/fd;" + document.cookie : "/fd", 1169 uploadURL : cfg.uploadURL || "/upload" 1170 }; 1171 Parent.apply(this, arguments); 1172 } 1173 Main.applyTo = function(a, b) { 1174 if (!a || "SWF.eventHandler" != a) 1175 return null; 1176 try { 1177 return SWFReference.eventHandler.apply(SWFReference, b); 1178 } catch (c) { 1179 return null; 1180 } 1181 }; 1182 Main.prototype = { 1183 constructor : Main, 1184 name : "uploader", 1185 initializer : function() { 1186 sStreamMessagerId = this.config.messagerId; 1187 this.startPanel = this.config.browser || document.getElementById(this.config.browseFileId); 1188 /** the default UI */ 1189 if (!this.config.customered) { 1190 fAddClass(this.startPanel, "stream-browse-files"); 1191 this.startPanel.appendChild(fCreateContentEle(this.config.browseFileBtn)); 1192 var filesQueuePanel = document.getElementById(this.config.filesQueueId); 1193 fAddClass(filesQueuePanel, "stream-main-upload-box"); 1194 var filesContainerId = fGenerateId("files-container"), 1195 totalContainerId = fGenerateId("total-container"); 1196 var filesQueue = fCreateContentEle(sFilesContainer.replace("#filesContainerId#", filesContainerId).replace("#filesQueueHeight#", this.config.filesQueueHeight)), 1197 totalQueue = fCreateContentEle(sTotalContainer.replace("#totalContainerId#", totalContainerId)); 1198 filesQueuePanel.appendChild(filesQueue); 1199 filesQueuePanel.appendChild(totalQueue); 1200 1201 this.containerPanel = document.getElementById(filesContainerId); 1202 this.totalContainerPanel = document.getElementById(totalContainerId); 1203 this.template = sCellFileTemplate; 1204 } 1205 1206 this.fileProvider = new Provider(this.config); 1207 this.fileProvider.render(this.startPanel); 1208 this.fileProvider.on("uploadprogress", this.uploadProgress, this); 1209 this.fileProvider.on("uploadcomplete", this.uploadComplete, this); 1210 this.fileProvider.on("uploaderror", this.uploadError, this); 1211 this.fileProvider.on("fileselect", this.fileSelect, this); 1212 fAddEventListener(window, "beforeunload", fExtend(this.unloadHandler, this)); 1213 this.waiting = []; 1214 this.uploading = !1; 1215 this.totalFileSize = 0; 1216 this.totalUploadedSize = 0; 1217 this.showBrowseBlock(); 1218 }, 1219 addStreamTask : function(a) { 1220 var file_id = a.get("id"), cell_file = fCreateContentEle("<li id='" + file_id + "' class='stream-cell-file'></li>"); 1221 cell_file.innerHTML = this.template; 1222 this.uploadInfo[file_id] = { 1223 uploadToken : "", 1224 uploadComplete : !1, 1225 file : a, 1226 disabled : !1, 1227 actived : !1, 1228 progressNode : this.getNode("stream-process", cell_file), 1229 cellInfosNode : this.getNode("stream-cell-infos", cell_file) 1230 }; 1231 this.totalFileSize += this.uploadInfo[file_id].file.get("size"); 1232 if (!this.config.customered) { 1233 this.getNode("stream-file-name", cell_file).getElementsByTagName("strong")[0].innerHTML = a.get("name"); 1234 this.containerPanel.appendChild(cell_file); 1235 this.renderUI(file_id); 1236 this.bindUI(file_id); 1237 } 1238 /** do not hidden the upload button */ 1239 /*bStreaming ? this.startPanel.style.display = "none" : (this.startPanel.style.height = "1px", this.startPanel.style.width = "1px");*/ 1240 this.waiting.push(file_id); 1241 this.config.autoUploading && this.upload(file_id); 1242 }, 1243 hideBrowseBlock: function() { 1244 this.browseFileBlockHeight = fGetHeight(this.startPanel); 1245 this.browseFileBlockWidth = fGetWidth(this.startPanel); 1246 !this.browseFileBlockDisplay && (this.browseFileBlockDisplay = this.startPanel.style.display == "" ? "block" : this.startPanel.style.display); 1247 bStreaming ? this.startPanel.style.display = "none" : (this.startPanel.style.height = "1px", this.startPanel.style.width = "1px"); 1248 }, 1249 showBrowseBlock: function() { 1250 !this.browseFileBlockHeight && (this.browseFileBlockHeight = fGetHeight(this.startPanel)); 1251 !this.browseFileBlockWidth && (this.browseFileBlockWidth = fGetWidth(this.startPanel)); 1252 !this.browseFileBlockDisplay && (this.browseFileBlockDisplay = this.startPanel.style.display == "" ? "block" : this.startPanel.style.display); 1253 if (this.browseFileBlockDisplay == "none") {this.browseFileBlockDisplay = "block", this.browseFileBlockWidth = null, this.browseFileBlockHeight = null; return !1;} 1254 bStreaming ? this.startPanel.style.display = this.browseFileBlockDisplay : (this.startPanel.style.height = this.browseFileBlockHeight, this.startPanel.style.width = this.browseFileBlockWidth); 1255 }, 1256 renderUI : function(file_id) { 1257 var progressNode = this.uploadInfo[file_id].progressNode, 1258 cellInfosNode = this.uploadInfo[file_id].cellInfosNode, 1259 size = this.uploadInfo[file_id].file.get("size"), 1260 total = this.formatBytes(size); 1261 this.getNode("stream-process-bar", progressNode).innerHTML = "<span style='width:0%;'></span>"; 1262 this.getNode("stream-percent", progressNode).innerHTML = "0%"; 1263 this.getNode("stream-speed", cellInfosNode).innerHTML = "-"; 1264 this.getNode("stream-remain-time", cellInfosNode).innerHTML = "--:--:--"; 1265 this.getNode("stream-uploaded", cellInfosNode).innerHTML = "0/" + total; 1266 var _total = this.formatBytes(this.totalFileSize); 1267 this.getNode("_stream-total-size", this.totalContainerPanel).innerHTML = _total; 1268 }, 1269 bindUI : function(file_id) { 1270 var b = this.uploadInfo[file_id].progressNode, cancelBtn = this.getNode("stream-cancel", b); 1271 this.cancelBtnHandler = fExtend(this.cancelUploadHandler, this, {type : "click", nodeId : file_id}); 1272 fAddEventListener(cancelBtn, "click", this.cancelBtnHandler); 1273 }, 1274 completeUpload : function(info) { 1275 /** set the current scroll for files container */ 1276 var count = 0, scroll = null, ratio = 1; 1277 for(var i in this.uploadInfo) count++; 1278 ratio = (count - this.waiting.length - 1) / (count <= 0 ? 1 : count); 1279 this.containerPanel && this.containerPanel.parentNode && (scroll = this.containerPanel.parentNode, scroll.
1279scrollTop = scroll.scrollHeight * ratio); 1280 this.get("onComplete") ? this.get("onComplete")(info) : this.onComplete(info); 1281 this.waiting.length == 0 && (this.get("onQueueComplete") ? this.get("onQueueComplete")(info.msg) : this.onQueueComplete(info.msg)); 1282 this.config.autoRemoveCompleted && (info = document.getElementById(info.id), info.parentNode && info.parentNode.removeChild(info)); 1283 this.uploading = !1; 1284 this.upload(); 1285 }, 1286 onSelect : function(list) { 1287 fShowMessage("selected files: " + list.length); 1288 }, 1289 onRepeatedFile : function(file) { 1290 fShowMessage("File:" + file.name + " Size:" + file.size +" has been UPLOADED or ADDED.", true); 1291 return false; 1292 }, 1293 onFileCountExceed : function(selected, limit) { 1294 fShowMessage("File counts:" + selected + ", but limited:" + limit, true); 1295 }, 1296 onMaxSizeExceed : function(file) { 1297 fShowMessage("File:" + file.name + " size is:" + file.size +" Exceed limited:" + file.limitSize, true); 1298 }, 1299 onExtNameMismatch: function(file) { 1300 fShowMessage("Allow ext name: [" + file.filters.toString() + "], not for " + file.name, true); 1301 }, 1302 onAddTask: function(file) { 1303 fShowMessage("Add to task << name: [" + file.name); 1304 }, 1305 onCancel : function(file) { 1306 fShowMessage("Canceled: " + file.name); 1307 }, 1308 onStop : function() { 1309 fShowMessage("Stopped!"); 1310 }, 1311 onCancelAll : function(numbers) { 1312 fShowMessage(numbers + " files Canceled! "); 1313 }, 1314 onComplete : function(file) { 1315 fShowMessage("File:" + file.name + ", Size:" + file.size + " onComplete [OK]"); 1316 }, 1317 onQueueComplete : function(msg) { 1318 fShowMessage("onQueueComplete(msg: "+msg+") ---==> [OK]"); 1319 }, 1320 onUploadError : function(status, msg) { 1321 fShowMessage("Error Occur. Status:" + status + ", Message: " + msg, true); 1322 }, 1323 disable : function() { 1324 this.fileProvider.set("enabled", !1), this.fileProvider.triggerEnabled(), fAddClass(this.startPanel.children[0], "stream-disable-browser"), fAddClass(this.startPanel, "disabled"); 1325 }, 1326 enable : function() { 1327 this.fileProvider.set("enabled", !0), this.fileProvider.triggerEnabled(), fRemoveClass(this.startPanel.children[0], "stream-disable-browser"), fRemoveClass(this.startPanel, "disabled"); 1328 }, 1329 stop : function() { 1330 if (!this.uploading) return false; 1331 this.uploading = !1; 1332 var files = this.uploadInfo, number = 0; 1333 /** cancel the unfinished uploading files */ 1334 for(var fileId in files) { 1335 /** add the `file_id` to `waiting` @ index of 0 */ 1336 if (!files[fileId].uploadComplete) { 1337 this.cancelOne(fileId, true) && this.uploadInfo[fileId] && this.waiting.unshift(fileId); 1338 break; 1339 } 1340 } 1341 this.get("onStop") ? this.get("onStop")() : this.onStop(); 1342 }, 1343 destroy : function() { 1344 this.stop(); 1345 this.fileProvider.destroy(); 1346 this.waiting = []; 1347 /** the default UI */ 1348 if (!this.config.customered) { 1349 fRemoveClass(this.startPanel, "stream-browse-files"); 1350 fRemoveClass(this.startPanel, "stream-browse-drag-files-area"); 1351 var filesQueuePanel = document.getElementById(this.config.filesQueueId); 1352 fRemoveClass(filesQueuePanel, "stream-main-upload-box"); 1353 while (this.startPanel.firstChild) { 1354 var oldNode = this.startPanel.removeChild(this.startPanel.firstChild); 1355 oldNode = null; 1356 } 1357 while (filesQueuePanel.firstChild) { 1358 var oldNode = filesQueuePanel.removeChild(filesQueuePanel.firstChild); 1359 oldNode = null; 1360 } 1361 } 1362 this.get("onDestroy") && this.get("onDestroy")(); 1363 var selfthis = this, selfthis = null; 1364 }, 1365 cancel : function() { 1366 this.uploading = !1; 1367 var files = this.uploadInfo, number = 0; 1368 /** cancel the unfinished uploading files */ 1369 for(var fileId in files) 1370 !files[fileId].uploadComplete && (++number) && this.cancelOne(fileId); 1371 this.get("onCancelAll") ? this.get("onCancelAll")(number) : this.onCancelAll(number); 1372 }, 1373 cancelOne : function(file_id, stopping) { 1374 var provider = this.uploadInfo[file_id].file, actived = this.uploadInfo[file_id].actived; 1375 provider && provider.cancelUpload && provider.cancelUpload(); 1376 if (!!stopping) { 1377 this.uploadInfo[file_id].actived = !1; 1378 return true; 1379 } 1380 1381 var totalSize = this.totalFileSize - this.uploadInfo[file_id].file.config.size, info = { 1382 id: file_id, 1383 name: this.uploadInfo[file_id].file.config.name, 1384 size: this.uploadInfo[file_id].file.config.size, 1385 totalSize: totalSize, 1386 formatTotalSize: this.formatBytes(totalSize), 1387 totalLoaded: this.totalUploadedSize, 1388 formatTotalLoaded: this.formatBytes(this.totalUploadedSize), 1389 totalPercent: totalSize == 0 ? 0 : this.totalUploadedSize * 10000 / totalSize / 100 1390 }; 1391 100 > info.totalPercent && (info.totalPercent = parseFloat(info.totalPercent).toFixed(2)); 1392 1393 this.get("onCancel") ? this.get("onCancel")(info) : this.onCancel(info); 1394 this.uploadInfo[file_id] && delete this.uploadInfo[file_id]; 1395 fRemoveEventListener(document, "click", this.cancelBtnHandler); 1396 !this.config.customered && this.containerPanel.removeChild(document.getElementById(file_id)); 1397 if (actived) { 1398 this.uploading = !1; 1399 this.upload(); 1400 } else { 1401 for(var i in this.waiting) 1402 if (this.waiting[i] === file_id) 1403 this.waiting.splice(i, 1); 1404 } 1405 var size = provider.config.size; 1406 this.totalFileSize -= size; 1407 var _loaded = this.formatBytes(this.totalUploadedSize); 1408 var percent = this.totalUploadedSize * 10000 / this.totalFileSize / 100; 1409 100 > percent && (percent = parseFloat(percent).toFixed(2)); 1410 if (this.totalFileSize === 0) 1411 percent = 100; 1412 1413 if (!this.config.customered) { 1414 var _total = this.formatBytes(this.totalFileSize); 1415 this.getNode("_stream-total-size", this.totalContainerPanel).innerHTML = _total; 1416 this.getNode("_stream-total-uploaded", this.totalContainerPanel).innerHTML = _loaded; 1417 this.getNode("stream-percent", this.totalContainerPanel).innerHTML = percent + "%"; 1418 this.getNode("stream-process-bar", this.totalContainerPanel).innerHTML = '<span style="width: '+percent+'%;"></span>'; 1419 1420 /*** TODO: this code will be removed in the future. 1421 bStreaming ? this.startPanel.style.display = "block" 1422 : (this.startPanel.style.height = "auto", this.startPanel.style.width = "970px");*/ 1423 } 1424 }, 1425 cancelUploadHandler : function(event, b) { 1426 var c = event || window.event, id = b.nodeId, self = this; 1427 this.preventDefault(c); 1428 this.stopPropagation(c); 1429 if (this.uploadInfo[id].disabled) 1430 return !1; 1431 this.uploadInfo[id] && !this.uploadInfo[id].uploadComplete; 1432 this.cancelOne(id); 1433 }, 1434 unloadHandler : function(evt) { 1435 var evt = evt || window.event; 1436 if (this.waiting.length > 0) 1437 return evt.returnValue = "\u60A8\u6B63\u5728\u4E0A\u4F20\u6587\u4EF6\uFF0C\u5173\u95ED\u6B64\u9875\u9762\u5C06\u4F1A\u4E2D\u65AD\u4E0A\u4F20\uFF0C\u5EFA\u8BAE\u60A8\u7B49\u5F85\u4E0A\u4F20\u5B8C\u6210\u540E\u518D\u5173\u95ED\u6B64\u9875\u9762"; 1438 }, 1439 upload : function(index) { 1440 if(this.uploading) return; 1441 index = this.waiting.shift(); 1442 if(index == null) return; 1443 this.uploading = !0; 1444 1445 this.uploadInfo[index].actived = !0; 1446 var file = this.uploadInfo[index].file, self = this; 1447 var frmUploadURL = this.get("frmUploadURL"); 1448 var uploadURL = this.get("uploadURL"); 1449 /** request the server to figure out what's the token for the file: */ 1450 var xhr = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP"); 1451 1452 var vars = { 1453 name: file.get('name'), 1454 type: file.get('type'), 1455 size: file.get('size'), 1456 modified: file.get("dateModified") + "" 1457 }; 1458 vars = fMergeJson(vars, this.get("postVarsPerFile")); 1459 var tokenUrl = fAddVars(vars, this.get("tokenURL")) + "&" + fGetRandom(); 1460 xhr.open("GET", tokenUrl, !0); 1461 /** IE7,8 å ¼å®¹*/ 1462 xhr.onreadystatechange = function() { 1463 if (xhr.readyState != 4 || xhr.status < 200) 1464 return false;
1465 1466 var token, server; 1467 try { 1468 try { 1469 token = eval("(" + xhr.responseText + ")").token; 1470 server = eval("(" + xhr.responseText + ")").server; 1471 } catch(e) {} 1472 if (token) { 1473 if(server != null && server != "") { 1474 frmUploadURL = server + frmUploadURL; 1475 uploadURL = server + uploadURL; 1476 } 1477 bStreaming && bFileSlice && !self.config.formed ? (self.uploadInfo[index].serverAddress = server, 1478 self.uploadFile(file, uploadURL, token, "resumeUpload")) 1479 : self.uploadFile(file, frmUploadURL, token, "formUpload"); 1480 } else { 1481 /** not found any token */ 1482 self.cancelOne(index); 1483 var msg = "\u521B\u5EFA\u4E0A\u4F20\u4EFB\u52A1\u5931\u8D25[tokenURL=" + self.get("tokenURL") + "],\u72B6\u6001\u7801:" + xhr.status; 1484 fShowMessage(msg, true); 1485 } 1486 } catch(e) { 1487 /** streaming, swf, resume methods all failed, no more try */ 1488 } 1489 } 1490 window.XMLHttpRequest && (xhr.onerror = function() { 1491 self.cancelOne(index); 1492 var msg = "\u521B\u5EFA\u4E0A\u4F20\u4EFB\u52A1\u5931\u8D25,\u72B6\u6001\u7801:"
1492+ xhr.status + ",\u8BF7\u68C0\u6D4B\u7F51\u7EDC..."; 1493 fShowMessage(msg, true); 1494 }); 1495 xhr.send(); 1496 }, 1497 uploadFile : function(file, url, token, method) { 1498 var token = { 1499 token : token, 1500 client : method == "formUpload" || this.config.formed ? "formUpload" : "html5" 1501 }; 1502 url = url || ""; 1503 method && file instanceof StreamUploader && file.set("uploadMethod", method); 1504 this.fileProvider.upload(file, url, token); 1505 }, 1506 uploadProgress : function(a) { 1507 var id = a.target.get("id"), percent = Math.min(99.99, a.percentLoaded), 1508 totalPercent = (this.totalUploadedSize + a.bytesLoaded) * 10000 / this.totalFileSize / 100, totalPercent = Math.min(99.99, totalPercent); 1509 100 > totalPercent && (totalPercent = parseFloat(totalPercent).toFixed(2)); 1510 1511 if (!this.uploadInfo[id]) return false; 1512 if (this.config.customered) { 1513 var info = { 1514 id: id, 1515 loaded: a.bytesLoaded, 1516 formatLoaded: this.formatBytes(a.bytesLoaded), 1517 speed: a.bytesSpeed, 1518 formatSpeed: this.formatSpeed(a.bytesSpeed), 1519 size: a.bytesTotal, 1520 formatSize: this.formatBytes(a.bytesTotal), 1521 percent: percent, 1522 timeLeft: a.remainTime, 1523 formatTimeLeft: this.formatTime(a.remainTime), 1524 totalSize: this.totalFileSize, 1525 formatTotalSize: this.formatBytes(this.totalFileSize), 1526 totalLoaded: this.totalUploadedSize + a.bytesLoaded, 1527 formatTotalLoaded: this.formatBytes(this.totalUploadedSize + a.bytesLoaded), 1528 totalPercent: totalPercent 1529 }; 1530 this.get("onUploadProgress") && this.get("onUploadProgress")(info); 1531 return false; 1532 } 1533 1534 var progressNode = this.uploadInfo[id].progressNode, 1535 cellInfosNode = this.uploadInfo[id].cellInfosNode, bytesLoaded = a.bytesLoaded, 1536 c = this.formatSpeed(a.bytesSpeed), loaded = this.formatBytes(bytesLoaded), 1537 total = this.formatBytes(a.bytesTotal), _remainTime = this.formatTime(a.remainTime), 1538 a = Math.min(99.99, a.percentLoaded); 1539 100 > a && (a = parseFloat(a).toFixed(2)); 1540 this.getNode("stream-process-bar", progressNode).innerHTML = "<span style='width:"+a+"%;'></span>"; 1541 this.getNode("stream-percent", progressNode).innerHTML = a + "%"; 1542 this.getNode("stream-speed", cellInfosNode).innerHTML = c; 1543 if (_remainTime) 1544 this.getNode("stream-remain-time", cellInfosNode).innerHTML = _remainTime; 1545 this.getNode("stream-uploaded", cellInfosNode).innerHTML = loaded + "/" + total; 1546 1547 var _loaded = this.formatBytes(this.totalUploadedSize + bytesLoaded); 1548 var percent = (this.totalUploadedSize + bytesLoaded) * 10000 / this.totalFileSize / 100, percent = Math.min(99.99, percent); 1549 100 > percent && (percent = parseFloat(percent).toFixed(2)); 1550 this.getNode("_stream-total-uploaded", this.totalContainerPanel).innerHTML = _loaded; 1551 this.getNode("stream-percent", this.totalContainerPanel).innerHTML = percent + "%"; 1552 this.getNode("stream-process-bar", this.totalContainerPanel).innerHTML = '<span style="width: '+percent+'%;"></span>'; 1553 }, 1554 uploadComplete : function(a) { 1555 this.totalUploadedSize += a.target.get("size"); 1556 var id = a.target.get("id"), percent = Math.min(100, a.percentLoaded), 1557 totalPercent = this.totalUploadedSize * 10000 / this.totalFileSize / 100; 1558 100 > totalPercent && (totalPercent = parseFloat(totalPercent).toFixed(2)); 1559 if (this.totalFileSize === 0) 1560 percent = 100; 1561 1562 if (!this.uploadInfo[id]) return false; 1563 1564 var info = { 1565 id: id, 1566 name: a.target.get("name"), 1567 loaded: a.target.get("size"), 1568 formatLoaded: this.formatBytes(a.target.get("size")), 1569 size: a.target.get("size"), 1570 formatSize: this.formatBytes(a.target.get("size")), 1571 percent: 100, 1572 totalSize: this.totalFileSize, 1573 formatTotalSize: this.formatBytes(this.totalFileSize), 1574 totalLoaded: this.totalUploadedSize, 1575 formatTotalLoaded: this.formatBytes(this.totalUploadedSize), 1576 totalPercent: totalPercent, 1577 msg: a.data 1578 }; 1579 /** uploaded flag and its callback function. */ 1580 this.uploadInfo[id].uploadComplete = !0; 1581 1582 if (!this.config.customered) { 1583 var progressNode = this.uploadInfo[id].progressNode, 1584 cellInfosNode = this.uploadInfo[id].cellInfosNode, 1585 size = a.target.get("size"), a = eval("(" + a.data + ")"), fmtSize = this.formatBytes(size); 1586 this.getNode("stream-process-bar", progressNode).innerHTML = "<span style='width:100%;'></span>"; 1587 this.getNode("stream-percent", progressNode).innerHTML = "100%"; 1588 this.getNode("stream-uploaded", cellInfosNode).innerHTML = fmtSize + "/" + fmtSize; 1589 this.getNode("stream-remain-time", cellInfosNode).innerHTML = "00:00:00"; 1590 this.getNode("stream-cancel", progressNode).innerHTML = ""; 1591 1592 var _loaded = this.formatBytes(this.totalUploadedSize); 1593 var percent = this.totalUploadedSize * 10000 / this.totalFileSize / 100; 1594 100 > percent && (percent = parseFloat(percent).toFixed(2)); 1595 if (this.totalFileSize === 0) 1596 percent = 100; 1597 this.getNode("_stream-total-uploaded", this.totalContainerPanel).innerHTML = _loaded; 1598 this.getNode("stream-percent", this.totalContainerPanel).innerHTML = percent + "%"; 1599 this.getNode("stream-process-bar", this.totalContainerPanel).innerHTML = '<span style="width: '+percent+'%;"></span>'; 1600 } 1601 1602 this.completeUpload(info); 1603 }, 1604 getNode : function(a, b) { 1605 return fContains(b || this.containerPanel, a)[0] || null; 1606 }, 1607 uploadError : function(evt) { 1608 this.get("onUploadError") ? this.get("onUploadError")(evt.status, evt.statusText) : this.onUploadError(evt.status, evt.statusText); 1609 }, 1610 fileSelect : function(a) { 1611 var a = a.fileList, b = 0, c, files = []; 1612 for (c = 0; c < a.length; c++) 1613 files.push(a[c].config); 1614 this.get("onSelect") ? this.get("onSelect")(files) : this.onSelect(files); 1615 for (c in this.uploadInfo) 1616 b++; 1617 if (b == this.get("simLimit") || a.length > this.get("simLimit")) { 1618 this.get("onFileCountExceed") ? this.get("onFileCountExceed")(Math.max(a.length, b), this.get("simLimit")) 1619 : this.onFileCountExceed(Math.max(a.length, b), this.get("simLimit")); 1620 return !1; 1621 } 1622 for (c = 0; c < a.length; c++) 1623 this.validateFile(a[c]) && this.addStreamTask(a[c]); 1624 }, 1625 validateFile : function(uploader) { 1626 var name = uploader.get("name"), size = uploader.get("size"), 1627 ext = -1 !== name.indexOf(".") ? name.replace(/.*[.]/, "").toLowerCase() : "", 1628 filters = this.get("fileFilters"), valid = !1, msg = "", 1629 info = { 1630 id: uploader.get("id"), 1631 name: uploader.get("name"), 1632 size: uploader.get("size"), 1633 formatSize: this.formatBytes(uploader.get("size")), 1634 lastModifiedDate: uploader.get("lastModifiedDate"), 1635 limitSize: this.get("maxSize"), 1636 formatLimitSize: this.formatBytes(this.get("maxSize")), 1637 filters: filters 1638 }; 1639 1640 // check the file been uploaded? 1641 if (this.uploadInfo) { 1642 var unique = uploader.get("name") + "_" + uploader.get("size"); 1643 for (var i in this.uploadInfo) { 1644 var key = this.uploadInfo[i].file.get("name") + "_" + this.uploadInfo[i].file.get("size"); 1645 if (key === unique) { 1646 var ignore = this.get("onRepeatedFile") ? this.get("onRepeatedFile")(info) : this.onRepeatedFile(info); 1647 if (!ignore) return !1; 1648 } 1649 } 1650 } 1651 1652 if(!bStreaming && size > 2147483648){this.uploadError({status:100, statusText:"Flashæå¤§åªè½ä¸ä¼ 2Gçæä»¶!"});return !1;} 1653 if (this.get("maxSize") < size) 1654 this.get("onMaxSizeExceed") ? this.get("onMaxSizeExceed")(info) : this.onMaxSizeExceed(info); 1655 else { 1656 filters.length || (valid = !0); 1657 for (var i = 0; i < filters.length; i++) 1658 filters[i].toLowerCase() == "." + ext && (valid = !0); 1659 if (!valid) 1660 this.get("onExtNameMismatch") ? this.get("onExtNameMismatch")(info) : this.onExtNameMismatch(info); 1661 } 1662 valid && this.config.customered && this.get("onAddTask") && this.get("onAddTask")(info, uploader); 1663 return valid; 1664 }, 1665 formatSpeed : function(a) { 1666 var b = 0; 1667 1024 <= Math.round(a / 1024) 1668 ? (b = Math.round(100 * (a / 1048576)) / 100, b = Math.max(0, b), b = isNaN(b) ? 0 : parseFloat(b).toFixed(2), a = b + "MB/s") 1669 : (b = Math.round(100 * (a / 1024)) / 100, b = Math.max(0, b), b = isNaN(b) ? 0 : parseFloat(b).toFixed(2), a = b + "KB/s"); 1670 return a; 1671 }, 1672 formatBytes : function(size) { 1673 if (size < 100) { 1674 return (size + 'B'); 1675 } else if (size < 102400) { 1676 size = Math.round(100 * (size / 1024)) / 100; 1677 size = isNaN(size) ? 0 : parseFloat(size).toFixed(2); 1678 return (size + 'K'); 1679 } else if (size < 1047527424) { 1680 size = Math.round(100 * (size / 1048576)) / 100; 1681 size = isNaN(size) ? 0 : parseFloat(size).toFixed(2); 1682 return (size + 'M'); 1683 } 1684 1685 size = Math.round(100 * (size / 1073741824)) / 100; 1686 size = isNaN(size) ? 0 : parseFloat(size).toFixed(2); 1687 return (size + 'G'); 1688 }, 1689 formatTime : function(time) { 1690 var total = time || 0, hour = Math.floor(total / 3600), minute = Math.floor((total - 3600 * hour) / 60), 1691 second = Math.floor(total - 3600 * hour - 60 * minute), hour = "" + (!isNaN(hour) && 0 < hour ? (hour < 10 ? ("0" + hour + ":") : (hour + ":")): "00:"), 1692 hour = hour + (!isNaN(minute) && 0 < minute ? (minute < 10 ? ("0" + minute + ":") : minute + ":") : "00:"); 1693 return hour += !isNaN(second) && 0 < second ? (second < 10 ? ("0" + second + "") : second): "00"; 1694 }, 1695 preventDefault : function(a) { 1696 a.preventDefault ? a.preventDefault() : a.returnValue = !1 1697 }, 1698 stopPropagation : function(a) { 1699 a.stopPropagation ? a.stopPropagation() : a.cancelBubble = !0 1700 } 1701 }; 1702 1703 var sIEFlashClassId = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000", 1704 sShockwaveFlash = "application/x-shockwave-flash", sFlashVersion = "10.0.22", 1705 sFlashDownload = "http://fpdownload.macromedia.com/pub/flashplayer/update/current/swf/autoUpdater.swf?" + Math.random(), 1706 sFlashEventHandler = "SWF.eventHandler", 1707 oa = { 1708 align : "", 1709 allowFullScreen : "", 1710 allowNetworking : "", 1711 allowScriptAccess : "", 1712 base : "", 1713 bgcolor : "", 1714 loop : "", 1715 menu : "", 1716 name : "", 1717 play : "", 1718 quality : "", 1719 salign : "", 1720 scale : "", 1721 tabindex : "", 1722 wmode : "" 1723 }; 1724 var Browser = function(a) { 1725 var b = function(a) { 1726 var b = 0; 1727 return parseFloat(a.replace(/\./g, function() { 1728 return 1 == b++ ? "" : "."; 1729 })) 1730 }, c = window, d = c && c.navigator, e = { 1731 ie : 0, 1732 opera : 0, 1733 gecko : 0, 1734 webkit : 0, 1735 safari : 0, 1736 chrome : 0, 1737 firefox : 0, 1738 mobile : null, 1739 air : 0, 1740 phantomjs : 0, 1741 air : 0, 1742 ipad : 0, 1743 iphone : 0, 1744 ipod : 0, 1745 ios : null, 1746 android : 0, 1747 silk : 0, 1748 accel : !1, 1749 webos : 0, 1750 caja : d && d.cajaVersion, 1751 secure : !1, 1752 os : null, 1753 nodejs : 0 1754 }, a = a || d && d.userAgent, d = (c = c && c.location) && c.href, c = 0, f, g, h; 1755 e.userAgent = a; 1756 e.secure = d && 0 === d.toLowerCase().indexOf("https"); 1757 if (a) { 1758 if (/windows|win32/i.test(a)) 1759 e.os = "windows"; 1760 else if (/macintosh|mac_powerpc/i.test(a)) 1761 e.os = "macintosh"; 1762 else if (/android/i.test(a)) 1763 e.os = "android"; 1764 else if (/symbos/i.test(a)) 1765 e.os = "symbos"; 1766 else if (/linux/i.test(a)) 1767 e.os = "linux"; 1768 else if (/rhino/i.test(a)) 1769 e.os = "rhino"; 1770 if (/KHTML/.test(a)) 1771 e.webkit = 1; 1772 if (/IEMobile|XBLWP7/.test(a)) 1773 e.mobile = "windows"; 1774 if (/Fennec/.test(a)) 1775 e.mobile = "gecko";
1776 if ((d = a.match(/AppleWebKit\/([^\s]*)/)) && d[1]) { 1777 e.webkit = b(d[1]); 1778 if ((d = a.match(/Version\/([^\s]*)/)) && d[1]) 1779 e.safari = d[1]; 1780 if (/PhantomJS/.test(a) && (d = a.match(/PhantomJS\/([^\s]*)/)) 1781 && d[1]) 1782 e.phantomjs = b(d[1]); 1783 if (/Mobile\//.test(a) || /iPad|iPod|iPhone/.test(a)) { 1784 if (e.mobile = "Apple", (d = a.match(/OS ([^\s]*)/)) 1785 && d[1] && (d = b(d[1].replace("_", "."))), e.ios = d, e.os = "ios", e.ipad = e.ipod = e.iphone = 0, (d = a 1786 .match(/iPad|iPod|iPhone/)) 1787 && d[0]) 1788 e[d[0].toLowerCase()] = e.ios; 1789 } else { 1790 if (d = a.match(/NokiaN[^\/]*|webOS\/\d\.\d/)) 1791 e.mobile = d[0]; 1792 if (/webOS/.test(a) 1793 && (e.mobile = "WebOS", (d = a 1794 .match(/webOS\/([^\s]*);/)) 1795 && d[1])) 1796 e.webos = b(d[1]); 1797 if (/ Android/.test(a)) { 1798 if (/Mobile/.test(a)) 1799 e.mobile = "Android"; 1800 if ((d = a.match(/Android ([^\s]*);/)) && d[1]) 1801 e.android = b(d[1]); 1802 } 1803 if (/Silk/.test(a)) { 1804 if ((d = a.match(/Silk\/([^\s]*)\)/)) && d[1]) 1805 e.silk = b(d[1]); 1806 if (!e.android) 1807 e.android = 2.34, e.os = "Android"; 1808 if (/Accelerated=true/.test(a)) 1809 e.accel = !0; 1810 } 1811 } 1812 if ((d = a.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/)) && d[1] 1813 && d[2]) { 1814 if (e.chrome = b(d[2]), e.safari = 0, "CrMo" === d[1]) 1815 e.mobile = "chrome"; 1816 } else if (d = a.match(/AdobeAIR\/([^\s]*)/)) 1817 e.air = d[0]; 1818 } 1819 if (!e.webkit) 1820 if (/Opera/.test(a)) { 1821 if ((d = a.match(/Opera[\s\/]([^\s]*)/)) && d[1]) 1822 e.opera = b(d[1]); 1823 if ((d = a.match(/Version\/([^\s]*)/)) && d[1]) 1824 e.opera = b(d[1]); 1825 if (/Opera Mobi/.test(a) && (e.mobile = "opera", (d = a.replace("Opera Mobi", "").match(/Opera ([^\s]*)/)) && d[1])) 1826 e.opera = b(d[1]); 1827 if (d = a.match(/Opera Mini[^;]*/)) 1828 e.mobile = d[0]; 1829 } else if ((d = a.match(/MSIE\s([^;]*)/)) && d[1]) 1830 e.ie = b(d[1]); 1831 else if (d = a.match(/Gecko\/([^\s]*)/)) { 1832 if (e.gecko = 1, (d = a.match(/rv:([^\s\)]*)/)) && d[1]) 1833 e.gecko = b(d[1]); 1834 if ((d = a.match(/(Firefox)\/([^\s]*)/)) && d[1] && d[2]) 1835 e.firefox = d[2]; 1836 } 1837 } 1838 if (e.gecko || e.webkit || e.opera) { 1839 if (b = navigator.mimeTypes["application/x-shockwave-flash"]) 1840 if (b = b.enabledPlugin) 1841 f = b.description.replace(/\s[rd]/g, ".").replace( 1842 /[A-Za-z\s]+/g, "").split("."); 1843 } else if (e.ie) { 1844 try { 1845 g = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"), g.AllowScriptAccess = "always"; 1846 } catch (j) {null !== g && (c = 6);} 1847 if (0 === c) 1848 try { 1849 h = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"), 1850 f = h.GetVariable("$version").replace(/[A-Za-z\s]+/g, "").split(","); 1851 } catch (s) {} 1852 } 1853 if (fIsArray(f)) { 1854 if (fIsNumber(parseInt(f[0], 10))) 1855 e.flashMajor = f[0]; 1856 if (fIsNumber(parseInt(f[1], 10))) 1857 e.flashMinor = f[1]; 1858 if (fIsNumber(parseInt(f[2], 10))) 1859 e.flashRev = f[2]; 1860 } 1861 return e; 1862 }(); 1863 var bFileSlice = !1; 1864 var bStreaming = function() { 1865 var bFile = !1, bHtml5 = !1, bFormData = window.FormData ? !0 : !1, bStreaming = !1; 1866 "undefined" != typeof File && "undefined" != typeof (new XMLHttpRequest).upload && (bFile = !0); 1867 if (bFile && (bFileSlice = "slice" in File.prototype || "mozSlice" in File.prototype || "webkitSlice" in File.prototype)) 1868 bHtml5 = !0; 1869 (function() { 1870 for (var a = 0; a < aOtherBrowsers.length; a++) 1871 -1 !== navigator.userAgent.indexOf(aOtherBrowsers[a]) && (bHtml5 = !1); 1872 })(); 1873 /** some browsers has problems. */ 1874 (bFormData && Browser.os === "windows" && Browser.safari === "5.1.7") && (bFormData = !1); 1875 return bFile && (bFormData || bHtml5); 1876 }(), bDraggable = bStreaming && ('draggable' in document.createElement('span')), bFolder = bDraggable && (window.webkitRequestFileSystem || window.requestFileSystem); 1877 Provider = bStreaming ? StreamProvider : SWFProvider; 1878 window.Stream = window.Uploader = Main; /** window.Uploaderæ¯SWFç»ä»¶çå ³é®å(ä¿ç) */ 1879})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.