1(function ($) 2{ 3 $.widget("ui.PLUploadWrapper", { 4 uploader: null, 5 6 options: { 7 showImagePreview: true, 8 maxsize: null, 9 extensions: 'jpg,png,gif,jpeg,webp', 10 imageMimeTypes: 'image/gif,image/jpeg,image/png,image/webp', 11 show_delete_existing: true, 12 upload_button_label: 'Drop or Select', 13 upload_button_autohide: false, 14 delete_button_label: '<i class="fas fa-cut"></i> Delete Existing File', 15 restore_button_label: '<i class="fas fa-undo"></i> Restore Existing File', 16 delete_message: 'Existing file will be deleted.', 17 extra_button_class: '', 18 restore_message: '', 19 file_id: 'UploadFileId', 20 file_name: 'UploadFileName', 21 delete_existing: 'DeleteExistingFile', 22 delete_existing_value: 'false', 23 Error: function (uploader, error) { return undefined; }, 24 FileUploaded: function (uploader, file) { return undefined; }, 25 FilesAdded: function (uploader, file) { return undefined; }, 26 DeleteExistingToggled: function (deleteExisting) { return undefined; }, 27 Init: function (uploader) { return undefined; }, 28 PostInit: function (uploader) { return undefined; } 29 }, 30 31 _destroy: function () 32 { 33 // now do other stuff particular to this widget 34 $(this.element) 35 .empty() 36 .removeClass("vpuploader"); 37 }, 38 _init: function () 39 { 40 return undefined; 41 }, 42 _initVars: function () 43 { 44 let elementId = this.element.attr('id'); 45 let nameFileId; 46 if (!this.options.file_id) 47 { 48 nameFileId = `${elementId}_file_id`; 49 } 50 else if (typeof this.options.file_id === 'function') 51 { 52 nameFileId = this.options.file_id(); 53 } 54 else 55 { 56 nameFileId = this.options.file_id; 57 } 58 59 let nameFilename; 60 if (!this.options.file_name) 61 { 62 nameFilename = `${elementId}_file_name`; 63 } 64 else if ((typeof this.options.file_name) === 'function') 65 { 66 nameFilename = this.options.file_name(); 67 } 68 else 69 { 70 nameFilename = this.options.file_name; 71 } 72 73 this.vars = { 74 nameFileId: nameFileId, 75 nameFilename: nameFilename, 76 idElement: elementId, 77 idFileId: `${elementId}_file_id`, 78 idFilename: `${elementId}_file_name`, 79 idPreview: `${elementId}_file_preview`, 80 idSummary: `${elementId}_summary`, 81 idButtonBrowse: `${elementId}_button`, 82 idButtonDelete: `${elementId}_delete_button`, 83 idButtonExisting: `${elementId}_delete_existing`, 84 idMessageDelete: `${elementId}_delete_message`, 85 idProgress: `${elementId}_file_progress`, 86 }; 87 }, 88 _getDeleteButton: function () 89 { 90 return $(`#${this.vars.idButtonDelete}`); 91 }, 92 _setDeleteButtonHtml: function (html) 93 { 94 return this._getDeleteButton().html(html) 95 }, 96 _setDeleteMessageHtml: function(html) 97 { 98 return $(`#${this.vars.idMessageDelete}`).html(html) 99 }, 100 _setFileIdValue: function(value) 101 { 102 return $(`#${this.vars.idFileId}`).val(value) 103 }, 104 _setFileNameValue: function(value) 105 { 106 return $(`#${this.vars.idFilename}`).val(value) 107 }, 108 _setSummaryHtml: function(html, haveImage) 109 { 110 if (haveImage) 111 { 112 $(`#${this.vars.idSummary}`).html(''); 113 } 114 else 115 { 116 $(`#${this.vars.idSummary}`).html(html); 117 } 118 }, 119 _setPreviewHtml: function(html) 120 { 121 if (this.options.showImagePreview) 122 { 123 $(`#${this.vars.idPreview}`).html(html ?? ''); 124 } 125 }, 126 _setDeleteExistingValue: function(value) 127 { 128 return $(`#${this.vars.idButtonExisting}`).val(value) 129 }, 130 _getDeleteExistingValue: function() 131 { 132 return $(`#${this.vars.idButtonExisting}`).val() 133 }, 134 _create: function () 135 { 136 $(this.element).addClass("vpuploader"); 137 this._initVars();
138 139 let self = this; 140 141 let html = `<input type="hidden" value="${self.element.data('fileid') ?? ''}" id="${this.vars.idFileId}" name="${this.vars.nameFileId}"/> 142 <input type="hidden" value="${self.element.data('filename') ?? ''}" id="${this.vars.idFilename}" name="${self.vars.nameFilename}" type="hidden"/>`; 143 144 if (this.options.showImagePreview) 145 { 146 html += `<div id="${this.vars.idPreview}" class="vpuploader-preview"></div>`; 147 } 148 149 html += `<div id="${this.vars.idSummary}" class="vpuploader-summary">${self.element.data('filename') ?? ''}</div>`; 150 html += `<button type="button" class="vpuploader-upload-button vp-btn vp-btn-primary ${self.options.extra_button_class} " id="${this.vars.idButtonBrowse}"><i class="fas fa-upload"></i> ${self.options.upload_button_label}</button>\n`; 151 152 if (self.options.show_delete_existing === true) 153 { 154 html += `<input type="hidden" value="" id="${this.vars.idButtonExisting}" name="${self.options.delete_existing}" type="hidden"/> 155 <button type="button" class="vpuploader-delete-button vp-btn vp-btn-danger ${self.options.extra_button_class}" id="${this.vars.idButtonDelete}"><i class="fas fa-trash"></i> ${self.options.delete_button_label}</button> 156 <span id="${this.vars.idMessageDelete}" class="vpuploader-delete-message"></span>\n`; 157 } 158 159 html += `<div id="${this.vars.idProgress}" class="vpuploader-progress"></div>`; 160 161 $(self.element).append(html); 162 163 // Initialize PL Uploader 164 self.uploader = new plupload.Uploader({ 165 drop_element: this.vars.idElement, 166 runtimes: 'html5', 167 browse_button: self.vars.idButtonBrowse, 168 container: this.vars.idElement, 169 unique_names: true, 170 multi_selection: false, 171 chunk_size: '1mb', 172 url: '/Core/PLUpload', 173 filters: 174 { 175 mime_types: [{ title: "Recommended Files", extensions: self.options.extensions }], 176 max_file_size: '250mb', 177 prevent_duplicates: false 178 } 179 }); 180 181 // http://www.plupload.com/docs/Uploader#Init-event 182 self.uploader.bind('Init', function (uploader) 183 { 184 console.debug(`Uploader ${self.vars.idElement} Init`); 185 if (typeof self.options.Init === 'function') 186 { 187 self.options.Init.call(self, uploader); 188 } 189 190 if (uploader.features.dragdrop) 191 { 192 let elementSelector = `#${self.vars.idElement}`; 193 $(window).bind({ 194 dragover: function (event) 195 { 196 $(elementSelector).addClass("vpuploader-ondragover"); 197 //event.dataTransfer.dropEffect = "copy"; 198 }, 199 dragenter: function () 200 { 201 $(elementSelector).addClass("vpuploader-ondragover"); 202 }, 203 dragleave: function (event) 204 { 205 $(elementSelector).removeClass("vpuploader-ondragover"); 206 }, 207 drop: function () 208 { 209 $(elementSelector).removeClass("vpuploader-ondragover"); 210 } 211 }); 212 213 $(elementSelector).bind({ 214 dragover: function (event) 215 { 216 }, 217 dragenter: function () 218 { 219 $(this).addClass("vpuploader-ondragenter"); 220 }, 221 dragleave: function (event) 222 { 223 $target = $(event.target); 224 if ($target.hasClass("vpuploader") && 0 === $target.find(event.relatedTarget).length) 225 { 226 $(this).removeClass("vpuploader-ondragenter"); 227 } 228 }, 229 drop: function () 230 { 231 $(this).removeClass("vpuploader-ondragenter").removeClass("vpuploader-ondragover"); 232 } 233 }); 234 } 235 236 237 }); 238 239 // http://www.plupload.com/docs/Uploader#PostInit 240 self.uploader.bind('PostInit', function (uploader) 241 { 242 console.debug(`Uploader ${self.vars.idElement} PostInit`); 243 if (typeof self.options.PostInit === 'function') 244 { 245 self.options.PostInit.call(self, uploader); 246 } 247 $(self.element).find('input[type=file]').attr('aria-label', self.options.upload_button_label); 248 }); 249 250 // http://www.plupload.com/docs/Uploader#Error-event 251 self.uploader.bind('Error', function (uploader, error) 252 { 253 console.error(`Uploader ${self.vars.idElement} Error: ${error.message}`); 254 if (error.file) 255 { 256 let errorMessage; 257 if (plupload.FILE_SIZE_ERROR === error.code) 258 { 259 errorMessage = 'Your file is too large. Please upload a smaller file.'; 260 } 261 else if (plupload.FILE_EXTENSION_ERROR === error.code) 262 { 263 errorMessage = 'The file is not an allowed type. Please select a new file of type image.'; 264 } 265 else if (plupload.IMAGE_FORMAT_ERROR === error.code) 266 { 267 errorMessage = 'The file does not appear to be in a known image format. Please select a new file of type image.'; 268 } 269 else if (plupload.IMAGE_DIMENSIONS_ERROR === error.code) 270 { 271 errorMessage = 'Your images is too large. Please upload a smaller image.'; 272 } 273 else 274 { 275 errorMessage = 'An error occurred.'; 276 } 277 278 console.error(`${error.file.name} (${plupload.formatSize(error.file.size)}) Error: ${error.code}, Message: ${error.message}`); 279 self._setSummaryHtml(`${error.file.name}<br/>(${plupload.formatSize(error.file.size)}) ${errorMessage}`); 280 self._setPreviewHtml(''); 281 uploader.refresh();
282 } 283 284 if (typeof self.options.Error === 'function') 285 { 286 self.options.Error.call(self, uploader, error); 287 } 288 }); 289 290 self.uploader.init(); 291 292 // http://www.plupload.com/docs/Uploader#FilesAdded-event 293 self.uploader.bind('FilesAdded', function (uploader, files) 294 { 295 console.debug(`Uploader ${self.vars.idElement} FilesAdded`); 296 if (uploader.files.length > 1) 297 { 298 uploader.splice(0, uploader.files.length - 1); 299 } 300 301 let success = false; 302 303 $.each(files, function (i, file) 304 { 305 let fileSizeFormatted = plupload.formatSize(file.size); 306 if (self.options.maxsize && file.size > self.options.maxsize) 307 { 308 let maxSizeFormatted = plupload.formatSize(self.options.maxsize); 309 uploader.splice(0, uploader.files.length); 310 console.warn(`PLUpload Warning: Selected file is too big. File Size: ${fileSizeFormatted}. Max Allowed: ${maxSizeFormatted}.`); 311 self._setSummaryHtml(`The size of the select file is ${fileSizeFormatted}. <br/>The maximum size allowed is ${maxSizeFormatted}. <br/>Please select a smaller file.`); 312 self._setPreviewHtml(''); 313 uploader.refresh(); 314 } 315 else if (file.size === 0) 316 { 317 uploader.splice(0, uploader.files.length); 318 console.warn("PLUpload Warning: Selected file is empty."); 319 self._setSummaryHtml("The selected file is empty. Please choose a different file."); 320 self._setPreviewHtml(''); 321 uploader.refresh(); 322 } 323 else 324 { 325 let isImage = (self.options.imageMimeTypes ?? '').split(',').find(type => type === file.type) !== undefined; 326 self._setFileNameValue(file.name); 327 self._setSummaryHtml(`${file.name} <br/> (${fileSizeFormatted})`, isImage); 328 if (isImage && self.options.showImagePreview) 329 { 330 let nativeFile = file.getSource().getSource(); 331 let objectUrl = URL.createObjectURL(nativeFile); 332 let img = new Image(); 333 img.onload = function() { 334 self._setPreviewHtml(`<img src="${objectUrl}">`); 335 } 336 img.src = objectUrl; 337 if (self.options.upload_button_autohide) 338 { 339 self._showHideUploadButton(false); 340 } 341 } 342 else 343 { 344 self._showHideUploadButton(true); 345 self._setPreviewHtml(''); 346 } 347 success = true; 348 } 349 }); 350 351 uploader.refresh(); 352 353 if (success) 354 { 355 if (typeof self.options.FilesAdded === 'function') 356 { 357 self.options.FilesAdded.call(self, uploader, files); 358 } 359 } 360 }); 361 362 // http://www.plupload.com/docs/Uploader#UploadProgress-event 363 self.uploader.bind('UploadProgress', function (_uploader, file) 364 { 365 console.debug(`Uploader ${self.vars.idElement} UploadProgress`); 366 self._setSummaryHtml(`${file.name} <br/> (${plupload.formatSize(file.size)}) ${file.percent}%`); 367 self._setPreviewHtml(''); 368 $(`#${self.vars.idProgress}`).progressbar({ value: file.percent }); 369 }); 370 371 // http://www.plupload.com/docs/Uploader#FileUploaded-event 372 self.uploader.bind('FileUploaded', function (uploader, file, _response) 373 { 374 console.debug(`Uploader ${self.vars.idElement} FileUploaded`); 375 376 $(`#${self.vars.idProgress}`).progressbar({ value: file.percent }); 377 self._setSummaryHtml(`${file.name} <br/> (${plupload.formatSize(file.size)}) 100%`); 378 self._setPreviewHtml(''); 379 self._setFileIdValue(file.target_name); 380 self._setFileNameValue(file.name); 381 382 if (typeof self.options.FileUploaded === 'function') 383 { 384 self.options.FileUploaded.call(self, uploader, file); 385 } 386 }); 387 388 self.uploader.bind('BeforeUpload', function (uploader, file) 389 { 390 console.debug(`Uploader ${self.vars.idElement} BeforeUpload`); 391 // Called right before the upload for a given file starts, can be used to cancel it if required 392 uploader.settings.multipart_params = { 393 filename: file.name 394 }; 395 }); 396 397 if (self.options.show_delete_existing === true) 398 { 399 self._setDeleteExistingValue(self.options.delete_existing_value === "true" ? "false" : "true"); 400 self._toggleDeleteButton(); 401 self._showHideDeleteButton(false); 402 self._getDeleteButton().click(function (e) 403 { 404 e.preventDefault(); 405 self._toggleDeleteButton(); 406 return false; 407 }); 408 } 409 }, 410 start: function () 411 { 412 if (this.uploader && this.uploader.files.length > 0) 413 { 414 this.uploader.start(); 415 } 416 else 417 { 418 if (typeof this.options.FileUploaded === 'function') 419 { 420 this.options.FileUploaded.call(this, this.uploader, null); 421 } 422 } 423 }, 424 isFileSelected: function () 425 { 426 return (this.uploader ? (this.uploader.files.length > 0) : false); 427 }, 428 reset: function () 429 { 430 if (this.uploader && this.uploader.files.length > 0) 431 { 432 this.uploader.splice(0, this.uploader.files.length); 433 } 434 435 if ($(`#${this.vars.idProgress}`).progressbar("instance") !== undefined) 436 { 437 $(`#${this.vars.idProgress}`).progressbar("destroy"); 438 } 439 440 this._showHideUploadButton(true); 441 this._setSummaryHtml(''); 442 this._setPreviewHtml(''); 443 this._setFileIdValue(''); 444 this._setFileNameValue(''); 445 }, 446 enableDelete: function () 447 { 448 if (this.options.show_delete_existing === true) 449 { 450 this._showHideDeleteButton(true); 451 } 452 }, 453 disableDelete: function () 454 { 455 if (this.options.show_delete_existing === true) 456 { 457 this._showHideDeleteButton(false); 458 } 459 }, 460 _getUploadButton: function () 461 { 462 return $(`#${this.vars.idButtonBrowse}`); 463 }, 464 _showHideUploadButton: function (show) 465 { 466 467 let button = this._getUploadButton(); 468 if (show) 469 { 470 button.show(); 471 } 472 else 473 { 474 button.hide(); 475 } 476 }, 477 _showHideDeleteButton: function (show) 478 { 479 let button = this._getDeleteButton(); 480 if (show) 481 { 482 button.show(); 483 } 484 else 485 { 486 button.hide(); 487 } 488 }, 489 _toggleDeleteButton: function () 490 { 491 let toggledValue = (this._getDeleteExistingValue() !== 'true'); 492 this._setDeleteExistingValue(toggledValue); 493 this._setDeleteMessageHtml(toggledValue ? this.options.delete_message : this.options.restore_message); 494 this._setDeleteButtonHtml(toggledValue ? this.options.restore_button_label : this.options.delete_button_label); 495 if (this.options.DeleteExistingToggled !== undefined && typeof this.options.DeleteExistingToggled === 'function') 496 { 497 this.options.DeleteExistingToggled.call(this, toggledValue); 498 } 499 } 500 });
501}(jQuery));
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.