UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,330 lines (1,105 loc) 101 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); require('./kendo.core.js'); require('./kendo.progressbar.js'); require('./kendo.icons.js'); require('./kendo.html.button.js'); require('./kendo.licensing.js'); require('@progress/kendo-licensing'); require('./kendo.html.icon.js'); require('./kendo.html.base.js'); require('@progress/kendo-svg-icons'); const __meta__ = { id: "upload", name: "Upload", category: "web", description: "The Upload widget uses progressive enhancement to deliver the best possible uploading experience to users.", depends: ["core", "progressbar", "icons", "html.button"] }; (function($, undefined$1) { var kendo = window.kendo, Widget = kendo.ui.Widget, antiForgeryTokens = kendo.antiForgeryTokens, logToConsole = kendo.logToConsole, rFileExtension = /\.([^\.]+)$/, NS = ".kendoUpload", SELECT = "select", UPLOAD = "upload", SUCCESS = "success", ERROR = "error", COMPLETE = "complete", CANCEL = "cancel", CLEAR = "clear", PAUSE = "pause", RESUME = "resume", PROGRESS = "progress", REMOVE = "remove", VALIDATIONERRORS = "validationErrors", INVALIDMAXFILESIZE = "invalidMaxFileSize", INVALIDMINFILESIZE = "invalidMinFileSize", INVALIDFILEEXTENSION = "invalidFileExtension", PROGRESSHIDEDELAY = 1000, PROGRESSHIDEDURATION = 2000, HOVER_STATE = "k-hover", FOCUS_STATE = "k-focus", PROGRESSBAR_CLASS = "k-progressbar", PROGRESSBAR_SELECTOR = "." + PROGRESSBAR_CLASS, PROGRESSBAR_TEMPLATE_SELECTOR = ".k-progress", TABINDEX = "tabindex", WARNINGICON_SELECTOR = `.k-i-exclamation-circle,.k-svg-i-exclamation-circle`; var headerStatusIconName = { loading: "upload", warning: "exclamation-circle", success: "check" }; var Upload = Widget.extend({ init: function(element, options) { var that = this; that.progressbars = []; Widget.fn.init.call(that, element, options); that.name = element.name; that.multiple = that.options.multiple; that.directory = that.options.directory; that.localization = that.options.localization; var activeInput = that.element; that.wrapper = activeInput.closest(".k-upload"); if (that.wrapper.length === 0) { that.wrapper = that._wrapInput(activeInput); } that._activeInput(activeInput); that.element.addClass("k-hidden"); that.toggle(that.options.enabled); var ns = that._ns = NS + "-" + kendo.guid(); activeInput.closest("form") .on("submit" + ns, that._onParentFormSubmit.bind(that)) .on("reset" + ns, that._onParentFormReset.bind(that)); that._initUploadModule(); that._toggleDropZone(); that.wrapper .on("keydown", ".k-upload-button", that._onUploadButtonKeydown.bind(that)) .on("click", ".k-upload-action", that._onFileAction.bind(that)) .on("click", ".k-clear-selected", that._onClearSelected.bind(that)) .on("click", ".k-upload-button", function(e) { e.preventDefault(); that.element.click(); }) .on("click", ".k-upload-selected", that._onUploadSelected.bind(that)) .on("keydown", that._onKeyDown.bind(that)) .on("focusout", that._focusout.bind(that)); if (that.element.val()) { that._onInputChange({ target: that.element }); } }, events: [ SELECT, UPLOAD, SUCCESS, ERROR, COMPLETE, CANCEL, CLEAR, PROGRESS, REMOVE, PAUSE, RESUME ], options: { name: "Upload", enabled: true, multiple: true, directory: false, showFileList: true, template: "", files: [], async: { autoRetryAfter: 0, bufferChunkSize: 10000000, maxAutoRetries: 1, removeVerb: "POST", autoUpload: true, withCredentials: true, accept: "*/*; q=0.5, application/json", useArrayBuffer: false }, localization: { "select": "Select files...", "cancel": "Cancel", "retry": "Retry", "remove": "Remove", "pause": "Pause", "resume": "Resume", "clearSelectedFiles": "Clear", "uploadSelectedFiles": "Upload", "dropFilesHere": "Drop files here to upload", "invalidFiles": "Invalid file(s). Please check file upload requirements.", "statusUploading": "uploading", "statusUploaded": "uploaded", "statusWarning": "warning", "statusFailed": "failed", "headerStatusUploading": "Uploading...", "headerStatusPaused": "Paused", "headerStatusUploaded": "Done", "uploadSuccess": "File(s) uploaded successfully.", "uploadFail": "File(s) failed to upload.", "invalidMaxFileSize": "File size too large.", "invalidMinFileSize": "File size too small.", "invalidFileExtension": "File type not allowed." }, validation: { allowedExtensions: [], maxFileSize: 0, minFileSize: 0 }, dropZone: "" }, _initUploadModule: function() { var that = this, options = that.options; if (options.async.saveUrl) { that._module = that._supportsFormData() ? new formDataUploadModule(that) : new iframeUploadModule(that); that._async = true; var initialFiles = options.files; if (initialFiles.length > 0) { that._renderInitialFiles(initialFiles); } } else { that._module = new syncUploadModule(that); } }, setOptions: function(options) { var that = this, activeInput = that.element; $(that.options.dropZone).off(that._ns); Widget.fn.setOptions.call(that, options); that.multiple = that.options.multiple; that.directory = that.options.directory; activeInput.attr("multiple", that._supportsMultiple() ? that.multiple : false); if (that.directory) { activeInput.attr("webkitdirectory", that.directory); activeInput.attr("directory", that.directory); } that.toggle(that.options.enabled); that._initUploadModule(); that._toggleDropZone(); }, enable: function(enable) { enable = typeof (enable) === "undefined" ? true : enable; this.toggle(enable); }, disable: function() { this.toggle(false); }, toggle: function(enable) { enable = typeof (enable) === "undefined" ? enable : !enable; this.wrapper.toggleClass("k-disabled", enable); this.element.prop("disabled", enable); }, focus: function() { this.wrapper.find(".k-upload-button").trigger("focus"); }, destroy: function() { var that = this; var customDropZone = $(that.options.dropZone); $(document) .add($(".k-dropzone", that.wrapper)) .add(that.wrapper.closest("form")) .off(that._ns); if (customDropZone.length > 0) { customDropZone.off(that._ns); } $(that.element).off(NS); if (that.progressbars) { that.progressbars.forEach(progressbar => { progressbar.destroy(); }); } Widget.fn.destroy.call(that); }, pause: function(fileEntry) { this._module.onPause({ target: $(fileEntry, this.wrapper) }); var pauseIcon = fileEntry.find(".k-i-pause-sm,.k-svg-i-pause-sm"); var resume = kendo.htmlEncode(this.localization.resume); kendo.ui.icon(pauseIcon, { icon: "play-sm" }); pauseIcon.attr("title", resume); $(pauseIcon).parent().attr("aria-label", resume); }, resume: function(fileEntry) { this._module.onResume({ target: $(fileEntry, this.wrapper) }); var playIcon = fileEntry.find(".k-i-play-sm,.k-svg-i-play-sm"); var pause = kendo.htmlEncode(this.localization.pause); kendo.ui.icon(playIcon, { icon: "pause-sm" }); playIcon.attr("title", pause); $(playIcon).parent().attr("aria-label", pause); }, upload: function() { var that = this; that._module.onSaveSelected(); }, getFiles: function() { var that = this; var filesData; var allFiles = []; var listItems = that.wrapper.find(".k-file"); for (var i = 0; i < listItems.length; i++) { filesData = $(listItems[i]).data("fileNames"); if (filesData) { for (var j = 0; j < filesData.length; j++) { allFiles.push(filesData[j]); } } } return allFiles; }, clearAllFiles: function() { var that = this; var files = that.wrapper.find(".k-file"); files.each(function(index, file) { that._removeFileByDomElement(file, false); }); }, removeAllFiles: function() { var that = this; var files = that.wrapper.find(".k-file"); files.each(function(index, file) { that._removeFileByDomElement(file, true); }); }, removeFileByUid: function(uid) { this._removeFileByUid(uid, true); }, clearFileByUid: function(uid) { this._removeFileByUid(uid, false); }, _removeFileByUid: function(uid, shouldSendRemoveRequest) { var that = this; var fileEntry; if (typeof uid !== 'string') { return; } fileEntry = $('.k-file[' + kendo.attr('uid') + '="' + uid + '"]', that.wrapper); if (fileEntry.length > 0) { that._removeFileByDomElement(fileEntry, shouldSendRemoveRequest); } }, clearFile: function(callback) { this._removeFile(callback, false); }, removeFile: function(callback) { this._removeFile(callback, true); }, _removeFile: function(callback, shouldSendRemoveRequest) { var that = this; var files = that.wrapper.find(".k-file"); var fileData; if (typeof callback === "function") { files.each(function(index, file) { fileData = $(file).data("fileNames"); if (callback(fileData)) { that._removeFileByDomElement(file, shouldSendRemoveRequest); } }); } }, _removeFileByDomElement: function(fileEntry, shouldSendRemoveRequest) { var that = this; var fileData = { target: $(fileEntry, that.wrapper) }; var allFiles; if (that.options.async.saveUrl) { if ($(fileEntry).hasClass("k-file-progress")) { that._module.onCancel(fileData); } else { that._module.onRemove(fileData, {}, shouldSendRemoveRequest); } allFiles = $(".k-file", that.wrapper); if (allFiles.length === 0) { that._hideHeaderUploadstatus(); } else { that._updateHeaderUploadStatus(); } } else { that._module.onRemove(fileData, {}, shouldSendRemoveRequest); } }, _addInput: function(sourceInput) { //check if source input is a DOM element. Required for some unit tests if (!sourceInput[0].nodeType) { return; } var that = this, input = sourceInput.clone().val(""); input .insertAfter(that.element) .data("kendo" + that.options.prefix + that.options.name, that); $(that.element) .attr(TABINDEX, "-1") .removeAttr("id") .off(NS); that._activeInput(input); that.wrapper.find(".k-upload-button").trigger("focus"); }, _activeInput: function(input) { var that = this, wrapper = that.wrapper; that.element = input; if (that.directory) { input.attr("webkitdirectory", that.directory); input.attr("directory", that.directory); } input .attr("multiple", that._supportsMultiple() ? that.multiple : false) .attr("autocomplete", "off") .on("click" + NS, function(e) { if (wrapper.hasClass("k-disabled")) { e.preventDefault(); } }) .on("change" + NS, that._onInputChange.bind(that)); }, _adjustFocusState: function(focusedItem, toFocus) { focusedItem.removeClass(FOCUS_STATE); focusedItem.attr(TABINDEX, -1); toFocus.addClass(FOCUS_STATE); toFocus.attr(TABINDEX, 0); }, _arrowKeyNavigation: function(e, key, focusedItem) { var that = this, kendoKeys = kendo.keys, toFocus; if (key === kendoKeys.DOWN) { e.preventDefault(); e.stopPropagation(); toFocus = that.wrapper.find(".k-upload-files .k-file").first(); if (focusedItem.length > 0) { if (focusedItem.hasClass("k-upload-action")) { focusedItem.removeClass(FOCUS_STATE); focusedItem = focusedItem.closest(".k-file"); } toFocus = focusedItem.next(); } that._adjustFocusState(focusedItem, toFocus); if (!toFocus || toFocus.length === 0) { toFocus = that.wrapper.find(".k-clear-selected"); } } else if (key === kendoKeys.UP) { e.preventDefault(); e.stopPropagation(); toFocus = that.wrapper.find(".k-upload-files .k-file:last"); if (focusedItem.length > 0) { if (focusedItem.hasClass("k-upload-action")) { focusedItem.removeClass(FOCUS_STATE); focusedItem = focusedItem.closest(".k-file"); } toFocus = focusedItem.prev(); } that._adjustFocusState(focusedItem, toFocus); } else if (key === kendoKeys.RIGHT) { if (focusedItem.hasClass("k-upload-action")) { toFocus = focusedItem.next(".k-upload-action"); if (!toFocus || toFocus.length === 0) { toFocus = focusedItem.parent().find(".k-upload-action:first"); } } else if (focusedItem.length > 0) { toFocus = focusedItem.find(".k-upload-action:first"); } if (toFocus && toFocus.length > 0) { focusedItem.removeClass(FOCUS_STATE); toFocus.addClass(FOCUS_STATE); } } else if (key === kendoKeys.LEFT) { if (focusedItem.hasClass("k-upload-action")) { toFocus = focusedItem.prev(".k-upload-action"); if (!toFocus || toFocus.length === 0) { toFocus = focusedItem.parent().find(".k-upload-action:last"); } } else if (focusedItem.length > 0) { toFocus = focusedItem.find(".k-upload-action:last"); } if (toFocus && toFocus.length > 0) { focusedItem.removeClass(FOCUS_STATE); toFocus.addClass(FOCUS_STATE); } } if ((!toFocus || toFocus.length === 0) && (key === kendoKeys.UP || key === kendoKeys.DOWN)) { toFocus = that.wrapper.find(".k-upload-button"); } if (toFocus && toFocus.length > 0) { that._preventFocusRemove = true; toFocus.trigger("focus"); } }, _asyncCommandKeyNavigation: function(key, focusedItem, eventArgs) { var that = this, kendoKeys = kendo.keys, fileEntry = $(focusedItem, that.wrapper); that._retryClicked = false; if (key === kendoKeys.ESC && focusedItem.find(".k-i-cancel,.k-svg-i-cancel").length > 0) { that.trigger(CANCEL, eventArgs); that._module.onCancel({ target: fileEntry }); that._checkAllComplete(); that._updateHeaderUploadStatus(); that._preventFocusRemove = true; that.wrapper.find(".k-upload-button").trigger("focus"); } else if (key === kendoKeys.SPACEBAR) { if (focusedItem.find(".k-i-pause-sm,.k-svg-i-pause-sm").length > 0) { that.trigger(PAUSE, eventArgs); that.pause(focusedItem); that._updateHeaderUploadStatus(); } else if (focusedItem.find(".k-i-play-sm,.k-svg-i-play-sm").length > 0) { that.trigger(RESUME, eventArgs); that.resume(focusedItem); } } else if (key === kendoKeys.ENTER && !focusedItem.is(".k-file-progress, .k-file-success, .k-file-invalid")) { if (that.options.async.chunkSize && !that.options.async.concurrent && $('.k-file-progress', that.wrapper).length > 0) { return; } $(WARNINGICON_SELECTOR, focusedItem).remove(); $(PROGRESSBAR_SELECTOR, focusedItem).finish().show(); if (!that._module.metaData[fileEntry.data("uid")]) { that._module.prepareChunk(fileEntry); } that._module.onRetry({ target: fileEntry }); that._retryClicked = true; } }, _commandKeyNavigation: function(key, focusedItem) { var that = this, kendoKeys = kendo.keys, files = focusedItem.data("fileNames"), hasValidationErrors = that._filesContainValidationErrors(files), eventArgs = { files: files, headers: {} }; if (key === kendoKeys.DELETE) { if (!that.trigger(REMOVE, eventArgs)) { that._module.onRemove({ target: $(focusedItem, that.wrapper) }, eventArgs, !hasValidationErrors); that._preventFocusRemove = true; that.wrapper.find(".k-upload-button").trigger("focus"); } } else if (key === kendoKeys.TAB) { focusedItem.removeClass(FOCUS_STATE); focusedItem.attr(TABINDEX, -1); } else if (!!that.options.async.saveUrl) { that._asyncCommandKeyNavigation(key, focusedItem, eventArgs); } }, _focusout: function() { var focusedItem = this.wrapper.find(".k-upload-files .k-file." + FOCUS_STATE); if (!this._preventFocusRemove) { focusedItem.removeClass(FOCUS_STATE); focusedItem.attr(TABINDEX, -1); } else { this._preventFocusRemove = false; } }, _onKeyDown: function(e) { var that = this, focusedItem = that.wrapper.find(".k-upload-files .k-file." + FOCUS_STATE + "," + ".k-upload-action." + FOCUS_STATE), kendoKeys = kendo.keys, commandKeys = [kendoKeys.DELETE, kendoKeys.ESC, kendoKeys.ENTER, kendoKeys.SPACEBAR, kendoKeys.TAB], key = e.keyCode; if (key === kendoKeys.DOWN || key === kendoKeys.UP || key === kendoKeys.LEFT || key === kendoKeys.RIGHT) { that._arrowKeyNavigation(e, key, focusedItem); } else if (focusedItem.length > 0 && focusedItem.hasClass("k-file") && commandKeys.indexOf(key) > -1 && !that.wrapper.hasClass("k-disabled")) { if (key === kendoKeys.SPACEBAR) { e.preventDefault(); e.stopPropagation(); } that._commandKeyNavigation(key, focusedItem); } }, _onInputChange: function(e) { var that = this; var input = $(e.target); var files = assignGuidToFiles(that._inputFiles(input), that._isAsyncNonBatch()); validateFiles(files, that.options.validation); var prevented = that.trigger(SELECT, { files: files }); if (prevented) { that._addInput(input); input.remove(); } else { that._module.onSelect({ target: input }, files); } that.focus(); }, _onUploadButtonKeydown: function(e) { var key = e.keyCode, kendoKeys = kendo.keys; if (key === kendoKeys.ENTER || key === kendoKeys.SPACEBAR) { this.wrapper.find(".k-upload-button-wrap input").last().trigger("click"); } }, _readDirectory: function(item) { var deferred = new $.Deferred(); var dirReader = item.createReader(); var allFolderFiles = []; var readEntries = function() { dirReader.readEntries(function(entries) { if (!entries.length) { deferred.resolve(allFolderFiles); } else { allFolderFiles = allFolderFiles.concat(entries); readEntries(); } }, deferred.reject); }; readEntries(); return deferred.promise(); }, _readFile: function(item) { var that = this; var fullpath = item.fullPath; item.file(function(file) { file.relativePath = fullpath.slice(1); that.droppedFolderFiles.push(file); that.droppedFolderCounter --; if (that.droppedFolderCounter === 0) { setTimeout(function() { if (that.droppedFolderCounter === 0) { if (that.droppedFolderFiles.length) { that._proceedDroppedItems(that.droppedFolderFiles); that.droppedFolderFiles = []; } } },0); } }, function() { logToConsole("File error."); }); }, _traverseFileTree: function(item, skipCounter) { var that = this; if (!skipCounter) { that.droppedFolderCounter--; } this._readDirectory(item).then(function(items) { that.droppedFolderCounter += items.length; for (var i = 0; i < items.length; i++) { if (items[i].isFile) { that._readFile(items[i]); } else if (items[i].isDirectory) { that._traverseFileTree(items[i]); } } }); }, _onDrop: function(e) { var dt = e.originalEvent.dataTransfer; var that = this; var droppedFiles = dt.files; var length; stopEvent(e); if (that.options.directoryDrop && dt.items) { length = dt.items.length; that.droppedFolderCounter = 0; that.droppedFolderFiles = []; for (var i = 0; i < length; i++) { if (dt.items[i].webkitGetAsEntry) { var entry = dt.items[i].webkitGetAsEntry(); if (entry.isDirectory) { that._traverseFileTree(entry, true); } else if (entry.isFile) { that.droppedFolderFiles.push(dt.files[i]); } } else { that._proceedDroppedItems(droppedFiles); } } } else { that._proceedDroppedItems(droppedFiles); } }, _proceedDroppedItems: function(droppedFiles) { var that = this; var files = assignGuidToFiles(getAllFileInfo(droppedFiles), that._isAsyncNonBatch()); if (droppedFiles.length > 0 && !that.wrapper.hasClass("k-disabled")) { if (!that.multiple && files.length > 1) { files.splice(1, files.length - 1); } validateFiles(files, that.options.validation); var prevented = that.trigger(SELECT, { files: files }); if (!prevented) { that._module.onSelect({ target: $(".k-dropzone", that.wrapper) }, files); } } }, _filesContainValidationErrors: function(files) { var hasErrors = false; $(files).each(function(index, file) { if (file[VALIDATIONERRORS] && file[VALIDATIONERRORS].length > 0) { hasErrors = true; return false; } }); return hasErrors; }, _isAsyncNonBatch: function() { return (this._async && !this.options.async.batch) || false; }, _renderInitialFiles: function(files) { var that = this; var idx = 0; files = assignGuidToFiles(files, true); for (idx = 0; idx < files.length; idx++) { var currentFile = files[idx]; var fileEntry = that._enqueueFile(currentFile.name, { fileNames: [currentFile] }); fileEntry.addClass("k-file-success").data("files", [files[idx]]); if (that._supportsRemove()) { that._fileAction(fileEntry, REMOVE); } } }, _prepareTemplateData: function(name, data) { var filesData = data.fileNames, templateData = {}, totalSize = 0, idx = 0; for (idx = 0; idx < filesData.length; idx++) { totalSize += filesData[idx].size; } templateData.name = name; templateData.size = totalSize; templateData.files = data.fileNames; return templateData; }, _createProgressbarWapper: function() { return "<div class='" + PROGRESSBAR_CLASS + " k-hidden'></div>"; }, _createFileIconWrapper: function(fileTypeIcon) { return "<span class='k-file-icon-wrapper'>" + kendo.ui.icon({ icon: fileTypeIcon, iconClass: "k-file-icon", size: "xxlarge" }) + "<span class='k-file-state'></span>" + "</span>"; }, _progressbarInit: function(wrapper) { let progressbar = wrapper.kendoProgressBar({ animation: false, showStatus: false }).data("kendoProgressBar"); this.progressbars.push(progressbar); }, _prepareDefaultSingleFileEntryTemplate: function(data) { var that = this; var file = data.fileNames[0]; var fileSize = getTotalFilesSizeMessage(data.fileNames); var fileGroup = kendo.getFileGroup(file.extension, true); var errors = file[VALIDATIONERRORS]; var isError = errors && errors.length > 0; var invalidClass = isError ? " k-file-invalid k-file-error" : ""; var fileDetails = isError ? "<span class='k-file-validation-message' aria-live='polite'>" + kendo.htmlEncode(that.localization[errors[0]]) + "</span>" : "<span class='k-file-size'>" + fileSize + "</span>"; let encodedFileName = kendo.htmlEncode(file.name, true); var template = ""; template += "<li class='k-file" + invalidClass + "'><div class='k-file-single'>" + this._createProgressbarWapper() + this._createFileIconWrapper(fileGroup) + "<span class='k-file-info'>" + "<span class='k-file-name' title='" + encodedFileName + "'>" + encodedFileName + "</span>" + fileDetails + "</span>"; template += "<span class='k-upload-actions'></span></div>"; return $(template); }, _prepareDefaultMultipleFileEntriesTemplate: function(data) { var that = this; var files = data.fileNames; var filesHaveValidationErrors = that._filesContainValidationErrors(files); var totalFileSize = getTotalFilesSizeMessage(files); var template = ""; var i, currentFile; var invalidClass = filesHaveValidationErrors ? " k-file-invalid k-file-error" : ""; template += "<li class='k-file" + invalidClass + "'><div class='k-file-multiple'>" + this._createProgressbarWapper() + this._createFileIconWrapper("copy"); files.sort(function(a, b) { if (a[VALIDATIONERRORS]) { return -1; } if (b[VALIDATIONERRORS]) { return 1; } return 0; }); template += "<span class='k-multiple-files-wrapper'>"; for (i = 0; i < files.length; i++) { currentFile = files[i]; var fileSize = getTotalFilesSizeMessage([currentFile]); let encodedFileName = kendo.htmlEncode(currentFile.name, true); template += "<span class='k-file-info'>"; if (currentFile[VALIDATIONERRORS] && currentFile[VALIDATIONERRORS].length > 0) { template += "<span class='k-file-name k-file-name-invalid' title='" + encodedFileName + "'>" + encodedFileName + "</span>"; } else { template += "<span class='k-file-name' title='" + encodedFileName + "'>" + encodedFileName + "</span>"; } template += "<span class='k-file-size'>" + fileSize + "</span></span>"; } if (filesHaveValidationErrors) { template += "<span class='k-file-validation-message' aria-live='polite'>" + kendo.htmlEncode(that.localization.invalidFiles) + "</span>"; } else { template += "<span class='k-file-summary'>Total: " + files.length + " files, " + totalFileSize + "</span>"; } template += "</span><span class='k-upload-actions'></span></div>"; return $(template); }, _enqueueFile: function(name, data) { var that = this; var existingFileEntries; var fileEntry; var fileUid = data.fileNames[0].uid; var fileList = $(".k-upload-files", that.wrapper); var options = that.options; var template = options.template; var templateData; var removeEventArgs; var progressbarSelector = template ? PROGRESSBAR_TEMPLATE_SELECTOR : PROGRESSBAR_SELECTOR; var progressbar; var isProgressbar; if (fileList.length === 0) { fileList = $("<ul class='k-upload-files'></ul>").appendTo(that.wrapper); if (!that.options.showFileList) { fileList.hide(); } that.wrapper.removeClass("k-upload-empty"); } existingFileEntries = $(".k-file", fileList); if (!template) { if (data.fileNames.length === 1) { fileEntry = that._prepareDefaultSingleFileEntryTemplate(data); } else { fileEntry = that._prepareDefaultMultipleFileEntriesTemplate(data); } } else { templateData = that._prepareTemplateData(name, data); template = kendo.template(template); fileEntry = $("<li class='k-file'>" + template(templateData) + "</li>"); fileEntry.find(".k-upload-action").addClass("k-button k-icon-button k-button-md k-rounded-md k-button-flat k-button-flat-base"); } progressbar = $(progressbarSelector, fileEntry[0]); isProgressbar = progressbar.length > 0; if (isProgressbar) { that._progressbarInit(progressbar); } fileEntry .attr(kendo.attr("uid"), fileUid) .appendTo(fileList) .data(data); if (!that._async && isProgressbar) { progressbar.data("kendoProgressBar").value(100); } if (!that.multiple && existingFileEntries.length > 0) { removeEventArgs = { files: existingFileEntries.data("fileNames"), headers: {} }; if (!that.trigger(REMOVE, removeEventArgs)) { that._module.onRemove({ target: $(existingFileEntries, that.wrapper) }, removeEventArgs); } } return fileEntry; }, _removeFileEntry: function(fileEntry) { var that = this; var fileList = fileEntry.closest(".k-upload-files"); var allFiles, allCompletedFiles; fileEntry.remove(); allFiles = $(".k-file", fileList); allCompletedFiles = $(".k-file-success, .k-file-error", fileList); if (allCompletedFiles.length === allFiles.length) { this._hideActionButtons(); } if (allFiles.length === 0) { fileList.remove(); that.wrapper.addClass("k-upload-empty"); that._hideHeaderUploadstatus(); } else { that._updateHeaderUploadStatus(); } }, _fileAction: function(fileElement, actionKey, skipClear) { var iconsNameDictionary = { remove: "x", cancel: "cancel", retry: "arrow-rotate-cw-small", pause: "pause-sm" }; var firstActionButton; let actionKeyText = kendo.htmlEncode(this.localization[actionKey]); if (!iconsNameDictionary.hasOwnProperty(actionKey)) { return; } if (!skipClear) { this._clearFileAction(fileElement); } if (!this.options.template) { if (!skipClear) { fileElement.find(".k-upload-action").remove(); } fileElement.find(".k-upload-actions").append( this._renderAction(iconsNameDictionary[actionKey], actionKeyText, actionKey == "retry" ? "k-i-retry" : "") ); } else { firstActionButton = fileElement.find(".k-upload-action").first(); if (!firstActionButton.find(".k-icon,.k-svg-icon").length) { let firstActionIcon = kendo.ui.icon($(`<span title="${actionKeyText}" aria-label="${actionKeyText}"></span>`), { icon: iconsNameDictionary[actionKey], iconClass: "k-button-icon" + (actionKey == "retry" ? " k-i-retry" : "") }); firstActionButton .addClass("k-button k-button-md k-rounded-md k-button-solid k-button-solid-base k-icon-button") .append(firstActionIcon) .show(); } else if (firstActionButton.next(".k-upload-action").length) { let firstActionIcon = kendo.ui.icon($(`<span title="${actionKeyText}" aria-label="${actionKeyText}"></span>`), { icon: iconsNameDictionary[actionKey], iconClass: "k-button-icon" + (actionKey == "retry" ? " k-i-retry" : "") }); firstActionButton.next(".k-upload-action") .addClass("k-button k-button-md k-rounded-md k-button-solid k-button-solid-base k-icon-button") .append(firstActionIcon) .show(); } } }, _fileState: function(fileEntry, stateKey) { var localization = this.localization, states = { uploading: { text: localization.statusUploading }, uploaded: { text: localization.statusUploaded }, failed: { text: localization.statusFailed } }, currentState = states[stateKey]; if (currentState) { $("span.k-file-state", fileEntry).text(kendo.htmlEncode(currentState.text)); } }, _renderAction: function(iconName, actionText, iconClass) { if (iconName !== "") { return $( "<button type='button' class='k-button k-icon-button k-button-md k-rounded-md k-button-flat k-button-flat-base k-upload-action' aria-hidden='true' aria-label='" + actionText + "' tabindex='-1'>" + kendo.ui.icon($(`<span title="${actionText}"></span>`), { icon: iconName, iconClass: "k-button-icon" + (iconClass ? ` ${iconClass}` : "") }) + "</button>" ).on("focus", function() { $(this).addClass(FOCUS_STATE); }) .on("blur", function() { $(this).removeClass(FOCUS_STATE); }); } else { return $( "<button type='button' class='k-button k-button-md k-rounded-md k-button-solid k-button-solid-base'>" + '<span class="k-button-text">' + actionText + '</span>' + "</button>" ); } }, _clearFileAction: function(fileElement) { $(".k-upload-action", fileElement).empty().hide(); }, _onFileAction: function(e) { var that = this; if (!that.wrapper.hasClass("k-disabled")) { var button = $(e.target).closest(".k-upload-action"); var icon = button.find(".k-icon,.k-svg-icon"); var fileEntry = button.closest(".k-file"); var files = fileEntry.data("fileNames"); var hasValidationErrors = that._filesContainValidationErrors(files); var eventArgs = { files: files, headers: {} }; that._retryClicked = false; if (icon.is(".k-i-x,.k-svg-i-x")) { if (!that.trigger(REMOVE, eventArgs)) { that._module.onRemove({ target: $(fileEntry, that.wrapper) }, eventArgs, !hasValidationErrors); that.wrapper.find(".k-upload-button").trigger("focus"); } } else if (icon.is(".k-i-cancel,.k-svg-i-cancel")) { that.trigger(CANCEL, eventArgs); that._module.onCancel({ target: $(fileEntry, that.wrapper) }); that._checkAllComplete(); that._updateHeaderUploadStatus(); that.wrapper.find(".k-upload-button").trigger("focus"); } else if (icon.is(".k-i-pause-sm,.k-svg-i-pause-sm")) { that.trigger(PAUSE, eventArgs); that.pause(fileEntry); that._updateHeaderUploadStatus(); } else if (icon.is(".k-i-play-sm,.k-svg-i-play-sm")) { that.trigger(RESUME, eventArgs); that.resume(fileEntry); } else if (icon.hasClass("k-i-retry")) { $(".k-i-exclamation-circle", fileEntry).remove(); $(PROGRESSBAR_SELECTOR, fileEntry).finish().show(); that._module.onRetry({ target: $(fileEntry, that.wrapper) }); that._retryClicked = true; } fileEntry.addClass(FOCUS_STATE); } return false; }, _onUploadSelected: function() { var that = this; var wrapper = that.wrapper; if (!wrapper.hasClass("k-disabled")) { this._module.onSaveSelected(); } return false; }, _onClearSelected: function() { var that = this; var wrapper = that.wrapper; var clearEventArgs = { }; if (!wrapper.hasClass("k-disabled") && !that.trigger(CLEAR, clearEventArgs)) { that.clearAllFiles(); } return false; }, _onFileProgress: function(e, percentComplete) { var progressPct; var progressBar = $(PROGRESSBAR_SELECTOR, e.target).data("kendoProgressBar"); if (percentComplete > 100) { percentComplete = 100; } $(PROGRESSBAR_SELECTOR, e.target).removeClass('k-hidden'); if (!this.options.template) { progressPct = $(".k-upload-pct", e.target); if (progressPct.length === 0) { $(".k-upload-actions", e.target).prepend("<span class='k-upload-pct'></span>"); } if (percentComplete !== 100) { $(".k-upload-pct", e.target).text(percentComplete + "%"); } else { $(".k-upload-pct", e.target).remove(); } } if (progressBar) { progressBar.value(percentComplete); } this.trigger(PROGRESS, { files: getFileEntry(e).data("fileNames"), percentComplete: percentComplete }); }, _onUploadSuccess: function(e, response, xhr) { var that = this; var fileEntry = getFileEntry(e); var files = fileEntry.data("fileNames"); var fileInfo = fileEntry.find('.k-file-summary'); var fileSize = fileEntry.find('.k-file-size'); var prevented = that.trigger(SUCCESS, { files: fileEntry.data("fileNames"), response: response, operation: "upload", XMLHttpRequest: xhr }); if (prevented) { that._setUploadErrorState(fileEntry); } else { that._fileState(fileEntry, "uploaded"); fileEntry.removeClass('k-file-progress').addClass('k-file-success'); if (fileInfo.length > 0) { fileInfo.addClass('k-hidden') .after('<span class="k-file-validation-message" aria-live="polite">' + files.length + ' ' + kendo.htmlEncode(that.localization.uploadSuccess) + '</span>'); } else if (fileSize.length > 0) { fileSize.addClass('k-hidden') .after('<span class="k-file-validation-message" aria-live="polite">' + kendo.htmlEncode(that.localization.uploadSuccess) + '</span>'); } that._updateHeaderUploadStatus(); if (that._supportsRemove()) { that._fileAction(fileEntry, REMOVE); } else { that._clearFileAction(fileEntry); } } that._hideUploadProgress(fileEntry); that._checkAllComplete(); }, _onUploadError: function(e, xhr) { var that = this; var module = that._module; var fileEntry = getFileEntry(e); var fileUid = fileEntry.data("uid"); that._setUploadErrorState(fileEntry); that.trigger(ERROR, { operation: "upload", files: fileEntry.data("fileNames"), XMLHttpRequest: xhr }); logToConsole("Server response: " + xhr.responseText); if (!that.options.async.chunkSize) { that._hideUploadProgress(fileEntry); } else { if (module._decreasePosition) { module._decreasePosition(fileUid); } } that._checkAllComplete(); if (this.options.async.autoRetryAfter) { this._autoRetryAfter(fileEntry); } }, _autoRetryAfter: function(fileEntry) { var that = this; var retries = this._module.retries; if (!retries) { return; } if (!retries[fileEntry.data("uid")]) { retries[fileEntry.data("uid")] = 1; } if (retries[fileEntry.data("uid")] <= this.options.async.maxAutoRetries) { retries[fileEntry.data("uid")]++; setTimeout(function() { that._module.performUpload(fileEntry); },this.options.async.autoRetryAfter); } }, _setUploadErrorState: function(fileEntry) { var that = this, uploadPercentage, files = fileEntry.data("fileNames"), fileInfo = fileEntry.find('.k-file-summary'), fileSize = fileEntry.find('.k-file-size'); that._fileState(fileEntry, "failed"); fileEntry.removeClass('k-file-progress').addClass('k-file-error'); if (fileInfo.length > 0) { fileInfo.addClass('k-hidden') .after('<span class="k-file-validation-message" aria-live="polite">' + files.length + ' ' + kendo.htmlEncode(that.localization.uploadFail) + '</span>'); } else if (fileSize.length > 0) { fileSize.addClass('k-hidden') .after('<span class="k-file-validation-message" aria-live="polite">' + kendo.htmlEncode(that.localization.uploadFail) + '</span>'); } that._updateUploadProgress(fileEntry); uploadPercentage = $('.k-upload-pct', fileEntry); if (uploadPercentage.length > 0) { uploadPercentage.remove(); } this._updateHeaderUploadStatus(); this._fileAction(fileEntry, "retry"); this._fileAction(fileEntry, REMOVE, true); if (that._retryClicked) { fileEntry.trigger("focus"); } }, _updateUploadProgress: function(fileEntry) { var that = this; var progressbar = $( PROGRESSBAR_SELECTOR, fileEntry); var isProgressbar = progressbar.length > 0; if (!that.options.async.chunkSize && isProgressbar) { progressbar.data("kendoProgressBar").value(100); } else { var fileUid = fileEntry.data("uid"); if (that._module.metaData) { var fileMetaData = that._module.metaData[fileUid]; if (fileMetaData) { var percentComplete = fileMetaData.totalChunks ? Math.round(((fileMetaData.chunkIndex) / fileMetaData.totalChunks) * 100) : 100; that._onFileProgress({ target: $(fileEntry, that.wrapper) }, percentComplete); } } } }, _hideUploadProgress: function(fileEntry) { $(PROGRESSBAR_SELECTOR, fileEntry) .delay(PROGRESSHIDEDELAY) .fadeOut(PROGRESSHIDEDURATION, function() { if ($(this).data("kendoProgressBar")) { $(this).data("kendoProgressBar").value(0); }