1/** 2Base uploader class. Should not be instantiated. 3 4@class Uploader 5@namespace WS.Uploader 6@constructor 7@param {jQuery Object} buttonElements Elements that open the browse for files window when clicked. 8@param {jQuery Object} [listElement=null] Element that will contain upload preview. If multiple elements are sent, only the first one will be used. Ignored if listingTemplate is null. 9@param {Object} params An object containing upload parameters. 10@param {String} params.url The upload url. 11@param {Boolean} [params.keeporiginal=true] Set whether or not to keep the original file. Ignored when no modifications are applied to the uploaded files. 12@param {Boolean} [params.wantresize=false] Set whether or not to resize the file. Ignored if the file is not an image. 13@param {String} [params.resizeformat=null] Set the format to which the image should be resized. If empty and params.wantresize is set to true, the format will be the same as the original file. 14@param {Integer} [params.resizewidth=null] Set the resize width. If empty and params.wantresize is set to true and params.resizewidth is not set, params.resizeheight must be set. 15@param {Integer} [params.resizeheight=null] Set the resize height. If empty and params.wantresize is set to true and params.resizeheight is not set, params.resizewidth must be set. 16@param {Boolean} [params.wantmipmapping=false] Set whether or not to create smaller copies of the file. Ignored if the file is not an image. 17@param {Object} [options=null] An object containing uploader settings. 18@param {Array} [options.mimes=["*"]] Accepted MIME types. 19@param {Boolean} [options.multiple=false] Set whether or not to accept multiple files selection. 20@param {Boolean} [options.autostart=true] Set whether or not to automatically start uploading when a file is selected. 21@param {Boolean} [options.autoclear=false] Set whether or not to automatically remove completed uploads preview. Ignored if listElement or listingTemplate is null. 22@param {jQuery Object} dropElements Elements that accept files dropped from a directory. 23@param {jQuery Object} listingTemplate Element that will be used as a template for upload preview. 24@param {jQuery Object} globalProgressElements Elements that will be used to show upload progression. 25**/ 26WS.Namespace.Create("WS.Uploader.Uploader", (function () 27{ 28 var URL = window.URL || window.webkitURL; 29 var Support = { 30 File: (window.File !== undefined), 31 FormData: (window.FormData !== undefined), 32 BlobUrl: (URL !== undefined && URL.createObjectURL !== undefined), 33 BlobUrlDispose: (URL !== undefined && URL.revokeObjectURL !== undefined) 34 }; 35 36 var SizeUnits = ["B", "KB", "MB", "GB", "TB", "PB"]; 37 var FormatSize = function (byteCount, forcedUnit, precision) 38 { 39 precision = precision || 0; 40 if (precision < 0) precision = 0; 41 var unitIndex = 0; 42 while ((byteCount > 1024 && unitIndex < SizeUnits.length - 1) || (SizeUnits.indexOf(forcedUnit) != -1 && SizeUnits[unitIndex] != forcedUnit)) 43 { 44 byteCount = byteCount / 1024; 45 unitIndex++; 46 } 47 48 return { value: parseFloat(byteCount.toFixed(precision)), unit: SizeUnits[unitIndex] }; 49 }; 50 51 var OnUploadCancel = function () 52 { 53 if (!this.cancelled) 54 { 55 this.cancelled = true; 56 if (this.xhr) 57 { 58 this.xhr.abort(); 59 } 60 61 else 62 { 63 if (this.hasElement) this.element.cancel.hide(); 64 this.completed = true; 65 if (this.autoclear) this.Dispose(); 66 this.RaiseEvent("cancel", this.file.size, this.loaded); 67 this.RaiseEvent("complete", null); 68 } 69 } 70 }; 71 72 var Upload = function (container, template, file, autoclear) 73 { 74 WS.EventObject.call(this, ["start", "progress", "complete", "cancel"]); 75 76 this.file = file; 77 this.autoclear = autoclear; 78 this.blobUrl = null; 79 this.success = false; 80 this.loadEndSupport = true; 81 this.fileSize = FormatSize(file.size, null, 2); 82 this.loaded = 0; 83 this.xhr = null; 84 this.started = false; 85 this.cancelled = false; 86 this.completed = false; 87 this.disposed = false; 88 89 this.element = null; 90 this.hasElement = (container && template ? true : false); 91 if (this.hasElement) 92 { 93 this.element = {}; 94 this.element.main = template.clone(); 95 this.element.preview = this.element.main.find("[data=preview]"); 96 this.element.name = this.element.main.find("[data=name]"); 97 this.element.size = this.element.main.find("[data=size]"); 98 this.element.unit = this.element.main.find("[data=unit]"); 99 this.element.progress = {}; 100 this.element.progress.main = this.element.main.find("[data=progress]"); 101 this.element.progress.bar = this.element.main.find("[data=progress-bar]"); 102 this.element.progress.percentage = this.element.main.find("[data=progress-percentage]"); 103 this.element.progress.size = this.element.main.find("[data=progress-size]"); 104 this.element.progress.unit = this.element.main.find("[data=progress-unit]"); 105 this.element.cancel = this.element.main.find("[action=cancel]"); 106 this.element.loading = {};
107 this.element.loading.overlay = this.element.main.find("[data=loadingoverlay]"); 108 this.element.loading.indicator = this.element.main.find("[data=loading]"); 109 if (this.element.loading.indicator.length == 0) 110 { 111 if (this.element.loading.overlay.length > 0) 112 { 113 this.element.loading.overlay.append('<div class="wsLoadingFlexContainer"><div class="wsLoadingSpinner" style="font-size: 5;"></div></div>'); 114 this.element.loading.overlay.filter("[size=small]").find(".wsLoadingSpinner").css({ fontSize: "2" }); 115 this.element.loading.overlay.filter("[size=large]").find(".wsLoadingSpinner").css({ fontSize: "9" }); 116 } 117 } 118 119 else 120 { 121 this.element.loading.indicator.append('<div class="wsLoadingFlexContainer"><div class="wsLoadingSpinner" style="font-size: 5;"></div></div>'); 122 this.element.loading.indicator.filter("[size=small]").find(".wsLoadingSpinner").css({ fontSize: "2" }); 123 this.element.loading.indicator.filter("[size=large]").find(".wsLoadingSpinner").css({ fontSize: "9" }); 124 } 125 126 this.element.main.removeAttr("data").removeAttr("action"); 127 this.element.main.find("[data],[action]").removeAttr("data").removeAttr("action"); 128 this.element.loading.overlay.removeAttr("size"); 129 this.element.loading.indicator.removeAttr("size"); 130 131 this.element.name.html(this.file.name); 132 this.element.name.attr("title", this.file.name); 133 this.element.size.html(this.fileSize.value); 134 this.element.unit.html(this.fileSize.unit); 135 this.element.progress.main.hide(); 136 this.element.progress.bar.css("width", "0%"); 137 this.element.progress.percentage.html("0"); 138 this.element.progress.size.html("0"); 139 this.element.progress.unit.html(this.fileSize.unit); 140 this.element.loading.overlay.hide(); 141 if (this.element.cancel.length > 0) this.element.cancel.one("click", WS.Exts.BindMethod(OnUploadCancel, this)); 142 143 container.append(this.element.main); 144 } 145 }; 146 147 WS.Exts.Inherits(Upload, WS.EventObject); 148 149 (function (methods) 150 { 151 var OnProgress = function (event) 152 { 153 if (event.lengthComputable) 154 { 155 var percentage = parseFloat((event.loaded / event.total * 100).toFixed(2)); 156 var loaded = event.loaded; 157 if (loaded > this.file.size) loaded = this.file.size; 158 159 if (this.hasElement) 160 { 161 this.element.progress.bar.css("width", percentage + "%"); 162 this.element.progress.percentage.html(percentage); 163 this.element.progress.size.html(FormatSize(loaded, this.fileSize.unit, 2).value); 164 if (loaded == this.file.size) this.element.loading.overlay.show(); 165 } 166 167 this.RaiseEvent("progress", loaded - this.loaded); 168 this.loaded = loaded; 169 } 170 }; 171 172 var OnDone = function (event) 173 { 174 if (event.target.status == 200) this.success = true; 175 176 if (!this.loadEndSupport) OnComplete.call(this, event); 177 }; 178 179 var OnError = function (event) 180 { 181 if (!this.loadEndSupport) OnComplete.call(this, event); 182 }; 183 184 var OnAbort = function (event) 185 { 186 if (!this.loadEndSupport) OnComplete.call(this, event); 187 }; 188 189 var OnComplete = function (event) 190 { 191 if (this.hasElement) this.element.cancel.hide(); 192 var result = null; 193 if (this.success) 194 { 195 var response = event.target.response; 196 if (typeof response == "object") 197 result = response; 198 else 199 result = (JSON && JSON.parse ? JSON.parse(response)
199: eval("(" + response + ")")).Files; 200 } 201 202 this.xhr = null; 203 this.completed = true 204 if (this.autoclear) this.Dispose(); 205 if (!this.success) this.RaiseEvent("cancel", this.file.size, this.loaded); 206 this.RaiseEvent("complete", result); 207 }; 208 209 methods.ShowPreview = function () 210 { 211 if (this.hasElement && this.element.preview.length > 0) 212 { 213 if (Support.BlobUrl) 214 { 215 this.blobUrl = URL.createObjectURL(this.file); 216 this.element.preview.css({ backgroundImage: "url(" + this.blobUrl + ")", backgroundSize: "contain", backgroundPosition: "center center", backgroundRepeat: "no-repeat" }); 217 this.element.preview.filter("[crop]").css({ backgroundSize: "cover" }).removeAttr("crop"); 218 } 219 } 220 }; 221 222 methods.Start = function (url, params) 223 { 224 if (!this.cancelled) 225 { 226 if (Support.FormData) 227 { 228 this.started = true; 229 var form = new FormData(); 230 form.append("file", this.file); 231 for (var key in params) 232 { 233 form.append(key, params[key]); 234 } 235 236 var xhr = new XMLHttpRequest(); 237 if (xhr.upload) xhr.upload.addEventListener("progress", WS.Exts.BindMethod(OnProgress, this), false); 238 xhr.addEventListener("progress", function () { }, false); 239 xhr.addEventListener("load", WS.Exts.BindMethod(OnDone, this), false); 240 xhr.addEventListener("error", WS.Exts.BindMethod(OnError, this), false); 241 xhr.addEventListener("abort", WS.Exts.BindMethod(OnAbort, this), false); 242 xhr.addEventListener("loadend", WS.Exts.BindMethod(OnComplete, this), false); 243 if (xhr.onloadend === undefined) this.loadEndSupport = false; 244 245 this.xhr = xhr; 246 xhr.open("POST", url); 247 this.RaiseEvent("start"); 248 if (this.hasElement) this.element.progress.main.show(); 249 xhr.send(form); 250 } 251 } 252 }; 253 254 methods.Dispose = function () 255 { 256 if (!this.disposed) 257 { 258 if (Support.BlobUrlDispose && this.blobUrl) URL.revokeObjectURL(this.blobUrl); 259 if (this.hasElement) this.element.main.remove(); 260 this.disposed = true; 261 } 262 }; 263 })(Upload.prototype); 264 265 var ValidateExts = function (mimes, filetype) 266 { 267 var isValid = false; 268 for (var i = 0; i < mimes.length && !isValid; i++) 269 { 270 var regExp = new RegExp(mimes[i].replace("*", ".*")); 271 isValid = regExp.test(filetype); 272 } 273 274 return isValid; 275 }; 276 277 var OnUploadStart = function () 278 { 279 if (this.currentUploads == 0) this.RaiseEvent("start"); 280 this.currentUploads++; 281 }; 282 283 var OnUploadProgress = function (loaded) 284 { 285 this.loaded += loaded; 286 if (this.loaded > this.totalSize) this.loaded = this.totalSize; 287 if (this.element) this.element.progress.main.show(); 288 UpdateGlobalProgress.call(this, true); 289 }; 290 291 var OnFileCancel = function (fileSize, loaded) 292 { 293 this.totalSize -= fileSize; 294 this.loaded -= loaded; 295 this.totalSizeFormatted = FormatSize(this.totalSize, null, 2); 296 if (this.loaded > this.totalSize) this.loaded = this.totalSize; 297 UpdateGlobalProgress.call(this); 298 }; 299 300 var OnUploadComplete = function (fileinfo) 301 { 302 if (fileinfo) 303 { 304 for (var i = 0; i < fileinfo.length; i++) this.filesinfo.push(fileinfo[i]); 305 this.RaiseEvent("filecomplete", fileinfo); 306 } 307 308 this.currentUploads--; 309 if (this.currentUploads == 0) 310 { 311 if (this.filesinfo.length > 0) 312 this.RaiseEvent("complete", this.filesinfo); 313 else 314 this.RaiseEvent("cancel"); 315 316 this.filesinfo = []; 317 this.disabled = false; 318 } 319 }; 320 321 var OnChange = function (event) 322 { 323 var files = event.target.files; 324 OnSelect.call(this, files); 325 this.input.wrap(document.createElement("form")); 326 this.input.closest("form")[0].reset(); 327 this.input.unwrap(); 328 }; 329 330 var OnDragOver = function (event) 331 { 332 if (event.stopPropagation) event.stopPropagation(); 333 if (event.preventDefault) event.preventDefault(); 334 if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy'; 335 if (this.drops) { 336 var textdrop = $(document).find("[name=StartWrapper] div")[0]; 337 if (textdrop) 338 { 339 textdrop.innerText = this.params.dragover; 340 } 341 } 342 }; 343 344 var OnDragLeave = function (event) { 345 if (event.stopPropagation) event.stopPropagation(); 346 if (event.preventDefault) event.preventDefault(); 347 if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy'; 348 if (this.drops) { 349 var textdrop = $(document).find("[name=StartWrapper] div")[0]; 350 if (textdrop) { 351 textdrop.innerText = this.params.dragleave 352 } 353 } 354 }; 355 356 var OnDrop = function (event) 357 { 358 if (event.stopPropagation) event.stopPropagation(); 359 if (event.preventDefault) event.preventDefault(); 360 if (event.originalEvent.dataTransfer && !this.disabled) OnSelect.call(this, event.originalEvent.dataTransfer.files); 361 }; 362 363 var OnSelect = function (files) 364 { 365 var nbValid = 0; 366 var nbLimitedByDiskSpace = 0; 367 var nbLimitedBySize = 0; 368 for (var i = 0; i < files.length && (this.options.multiple || nbValid == 0) ; i++) 369 { 370 if (ValidateExts(this.options.mimes, files[i].type) 371 && (this.options.availableDiskSpace === null || this.options.availableDiskSpace >= files[i].size) 372 && (this.options.maximumFileSize === null || this.options.maximumFileSize >= files[i].size)) 373 { 374 nbValid++; 375 if (this.options.availableDiskSpace !== null) this.options.availableDiskSpace -= files[i].size; 376 var upload = new Upload(this.list, this.listTemplate, files[i], this.options.autoclear); 377 upload.RegisterEvent("start", WS.Exts.BindMethod(OnUploadStart, this)); 378 upload.RegisterEvent("progress", WS.Exts.BindMethod(OnUploadProgress, this)); 379 upload.RegisterEvent("complete", WS.Exts.BindMethod(OnUploadComplete, this)); 380 upload.RegisterEvent("cancel", WS.Exts.BindMethod(OnFileCancel, this)); 381 this.uploads.push(upload); 382 this.totalSize += files[i].size; 383 this.totalSizeFormatted = FormatSize(this.totalSize, null, 2); 384 UpdateGlobalProgress.call(this); 385 386 if (files[i].type.match("image/.*")) 387 { 388 upload.ShowPreview(); 389 } 390 391 if (this.options.autostart) 392 { 393 if (!this.options.multiple) this.disabled = true; 394 upload.Start(this.url, this.params); 395 } 396 } 397 398 else 399 { 400 if (this.options.availableDiskSpace !== null && this.options.availableDiskSpace < files[i].size) nbLimitedByDiskSpace++; 401 if (this.options.maximumFileSize !== null && this.options.maximumFileSize < files[i].size) nbLimitedBySize++; 402 } 403 } 404 405 if (!nbValid) this.RaiseEvent("error"); 406 407 if (window.MarketingUpgrade && window.pageData && pageData.xkeyPanel) 408 { 409 var me = this; 410 var MarketingData = { 411 Title: "", 412 Descr: "", 413 Upgrade: { 414 Key: pageData.xkeyPanel, 415 IdSite: pageData.siteId 416 } 417 }; 418 419 if (nbLimitedByDiskSpace > 0) 420 { 421 if (nbLimitedByDiskSpace == files.length) { 422 data = [ 423 { Key: "HARD_DRIVE_SPACE_TITLE", Type: "editor" }, 424 { Key: "HARD_DRIVE_SPACE_DESCR_REACH", Type: "editor" } 425 ]; 426 } 427 else 428 { 429 data = [ 430 { Key: "HARD_DRIVE_SPACE_TITLE", Type: "editor" }, 431 { Key: "HARD_DRIVE_SPACE_DESCR_EXCEED", Type: "editor" } 432 ]; 433 } 434 435 AjaxManager.Post("/Editor/Trad/Get", data, 436 function (Data) 437 { 438 if(Data != null && Data.length > 1) 439 { 440 MarketingData.Title = Data[0]; 441 MarketingData.Descr = Data[1].replace("[HARD_DRIVE_SPACE]", Math.floor(me.options.maximumDiskSpace / 1024 / 1024)); 442 443 MarketingUpgrade(me.buttons.eq(0), MarketingData); 444 } 445 446 }, function (error) { /*error*/ }); 447 } 448 else if (nbLimitedBySize > 0) 449 { 450 data = [ 451 { Key : "FILE_SIZE_TITLE", Type : "editor" }, 452 { Key: "FILE_SIZE_DESCR", Type: "editor" } 453 ] 454 455 AjaxManager.Post("/Editor/Trad/Get", data, 456 function (Data) 457 { 458 if (Data != null && Data.length > 1) 459 { 460 MarketingData.Title = Data[0]; 461 MarketingData.Descr = Data[1].replace("[FILE_SIZE]", Math.floor(me.options.maximumFileSize / 1024 / 1024)); 462 463 MarketingUpgrade(me.buttons.eq(0), MarketingData); 464 } 465 466 }, function (error) { /*error*/ }); 467 } 468 } 469 }; 470 471 var UpdateGlobalProgress = function (updateOnlyProgress) 472 { 473 updateOnlyProgress = updateOnlyProgress || false; 474 if (this.element) 475 { 476 if (!updateOnlyProgress) 477 { 478 this.element.size.html(this.totalSizeFormatted.value); 479 this.element.unit.html(this.totalSizeFormatted.unit); 480 this.element.progress.unit.html(this.totalSizeFormatted.unit); 481 } 482 483 var percentage = parseFloat((this.loaded / this.totalSize * 100).toFixed(2)); 484 this.element.progress.bar.css("width", percentage + "%"); 485 this.element.progress.percentage.html(percentage); 486 this.element.progress.size.html(FormatSize(this.loaded, this.totalSizeFormatted.unit, 2).value); 487 } 488 489 if (this.loaded == this.totalSize) this.RaiseEvent("transfercomplete"); 490 }; 491 492 var _class = function (buttonElements, listElement, params, options, dropElements, listingTemplate, globalProgressElements) 493 { 494 /** 495 Fired when an upload or a group of uploads has started. 496 497 @event start 498 **/ 499 /** 500 Fired when an upload or a group of uploads has been completed. 501 502 @event complete 503 @param {Array}
503 filesInfo An Array of object containing uploaded files identifiers, names and extensions. 504 **/ 505 /** 506 Fired when an upload or a group of uploads has been cancelled.<br /> 507 When options.multiple is set to true, only fired when all uploads have been cancelled. 508 509 @event cancel 510 **/ 511 /** 512 Fired when the data transfer for an upload or a group of uploads has been completed.<br /> 513 Fired before the event "complete". 514 515 @event transfercomplete 516 **/ 517 WS.EventObject.call(this, ["start", "complete", "cancel", "error", "transfercomplete", "filecomplete"]); 518 519 if (!buttonElements) throw "buttonElements cannot be null."; 520 if (buttonElements.length == 0) throw "buttonElements must contain at least one element."; 521 if (!params) throw "params cannot be null."; 522 if (!params.url) throw "Missing parameter : url."; 523 524 params.keeporiginal = (params.keeporiginal === false ? false : true); 525 params.wantresize = params.wantresize || false; 526 params.resizeformat = params.resizeformat || ""; 527 if (params.resizeformat && _class.support.imageformats.indexOf(params.resizeformat) == -1) throw "Invalid resize format : " + params.resizeformat + "."; 528 params.resizewidth = params.resizewidth || ""; 529 params.resizeheight = params.resizeheight || ""; 530 params.wantmipmapping = params.wantmipmapping || false; 531 if (params.wantresize) 532 { 533 if (!params.resizewidth && !params.resizeheight) throw "Missing resize information."; 534 } 535 536 options = options || {}; 537 options.mimes = options.mimes || ["*"]; 538 options.multiple = options.multiple || false; 539 options.autostart = (options.autostart === false ? false : true); 540 options.autoclear = options.autoclear || false; 541 options.availableDiskSpace = null; 542 543 if (listElement) listElement = listElement.eq(0); 544 if (listingTemplate) listingTemplate = listingTemplate.eq(0); 545 546 this.buttons = buttonElements; 547 this.list = listElement || null; 548 this.drops = dropElements || null; 549 this.listTemplate = (listingTemplate && listingTemplate.clone()) || null; 550 this.params = params; 551 this.options = options; 552 this.url = params.url; 553 delete params.url; 554 this.uploads = []; 555 this.currentUploads = 0; 556 this.filesinfo = []; 557 this.loaded = 0; 558 this.totalSize = 0; 559 this.totalSizeFormatted = FormatSize(this.totalSize, null, 2); 560 this.element = null; 561 this.disabled = false; 562 563 if (globalProgressElements) 564 { 565 this.element = {}; 566 this.element.main = globalProgressElements; 567 this.element.size = this.element.main.find("[data=size]"); 568 this.element.unit = this.element.main.find("[data=unit]"); 569 this.element.progress = {}; 570 this.element.progress.main = this.element.main.find("[data=progress]"); 571 this.element.progress.bar = this.element.main.find("[data=progress-bar]"); 572 this.element.progress.percentage = this.element.main.find("[data=progress-percentage]"); 573 this.element.progress.size = this.element.main.find("[data=progress-size]"); 574 this.element.progress.unit = this.element.main.find("[data=progress-unit]"); 575 UpdateGlobalProgress.call(this); 576 } 577 578 if (this.listTemplate) 579 { 580 this.listTemplate.removeAttr("id"); 581 this.listTemplate.find("[id]").removeAttr("id"); 582 } 583 584 this.input = $('<input type="file"' + (options.multiple ? ' multiple="multiple"' : '') + ' accept="' + options.mimes.join(",") + '" style="display: inline-block; width: 0px; height: 0px; visibility: hidden; position: absolute; top: 0px; left: 0px;" />'); 585 $("body").append(this.input); 586 587 var _me = this; 588 if (Support.File) 589 { 590 this.input.on("change", WS.Exts.BindMethod(OnChange, this)); 591 this.buttons.on("click", function () { if (!_me.disabled) _me.input.click(); }); 592 if (this.drops) 593 { 594 this.drops.on("dragover", WS.Exts.BindMethod(OnDragOver, this)); 595 this.drops.on("dragleave", WS.Exts.BindMethod(OnDragLeave, this)); 596 this.drops.on("drop", WS.Exts.BindMethod(OnDrop, this)); 597 } 598 } 599 }; 600 601 (function (statics) 602 { 603 statics.support = { 604 imageformats: ["image/bmp", "image/jpeg", "image/gif", "image/png"] 605 }; 606 })(_class); 607 608 WS.Exts.Inherits(_class, WS.EventObject); 609 610 (function (methods) 611 { 612 /**
613 Remove completed uploads preview. 614 615 @method Clear 616 **/ 617 methods.Clear = function () 618 { 619 if (!this.options.autoclear) 620 { 621 for (var i = 0; i < this.uploads.length; i++) 622 { 623 if (this.uploads[i].completed) 624 { 625 this.uploads[i].Dispose(); 626 } 627 } 628 } 629 630 if (this.currentUploads == 0) 631 { 632 this.uploads.splice(0, this.uploads.length); 633 this.loaded = 0; 634 this.totalSize = 0; 635 this.totalSizeFormatted = FormatSize(this.totalSize, null, 2); 636 if (this.element) this.element.progress.main.hide(); 637 UpdateGlobalProgress.call(this); 638 } 639 }; 640 641 /** 642 Start uploads that are currently pending. 643 644 @method Start 645 **/ 646 methods.Start = function () 647 { 648 if (!this.options.autostart) 649 { 650 for (var i = 0; i < this.uploads.length; i++) 651 { 652 if (!this.uploads[i].started) this.uploads[i].Start(); 653 } 654 } 655 }; 656 657 /** 658 Destroy the uploader. 659 660 @method Dispose 661 **/ 662 methods.Dispose = function () 663 { 664 if (this.currentUploads == 0) 665 { 666 this.Clear(); 667 668 this.input.remove(); 669 this.buttons.off("click"); 670 if (this.drops) this.drops.off("dragover").off("drop"); 671 } 672 }; 673 })(_class.prototype); 674 675 return _class; 676})()); 677/** 678Explanation of the tag that can be used in upload preview templates. 679 680<pre><code> 681data="preview" : uploaded file preview will be displayed in the elements that have this property. If elements have a crop attribute, the preview will be cropped to completely fill the element. 682data="name" : uploaded file name will be displayed in the elements that have this property. 683data="size" : uploaded file size will be displayed in the elements that have this property. 684data="unit" : uploaded file size unit will be displayed in the elements that have this property. 685data="progress" : elements that have this property will be hidden until upload starts. 686data="progress-bar" : elements that have this property should represent the upload progression. 687data="progress-percentage" : upload progress percentage will be displayed in the elements that have this property. 688data="progress-size" : upload progress size will be displayed in the elements that have this property. 689data="progress-unit" : upload progress size unit will be displayed in the elements that have this property. 690data="loadingoverlay" : elements that will be displayed when the files transfer is over and the files are being handled server-side. 691data="loading" : elements that will display a loading image. Should be contained inside a loading overlay. Image will be displayed inside the overlay if no elements have this property. 692action="cancel" : elements that have this property will cancel the upload when clicked. 693</code></pre> 694 695@class listingTemplate 696@namespace WS.Uploader 697@static 698**/
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.