1(function($){ 2 3 $.fn.WebEditionXHRUpload = function(action){ 4 5 var actions = { 6 7 init: function(options){ 8 var $field = $(this), 9 $form = $field.closest('form'), 10 config = { 11 // URL to post this XHR Upload to 12 url: '/asset/upload', 13 14 // Valid jQuery object that can be used as a progress bar 15 progressBar: $("<progress class='upload-bar' value='0' max='100'></progress>"), 16 17 // wrapper for the progress bar area and image (if preview is enabled) 18 progressWrapper: $("<div class='upload-area'></div>"), 19 20 // wrapper to report status messages in 21 messageWrapper: $("<div class='upload-message'></div>"), 22 23 // wrapper to place file name and details 24 fileWrapper: $("<div class='upload-file'></div>"), 25 26 // Class prefix for message statuses. For example a message status of 'fail' with a messageStatusPrevix of 'upload-' would apply a class of upload-fail to the messageWrapper when that message is displayed 27 messageStatusPrefix: 'upload-', 28 29 // By default, this is how long you should wait to remove a failed upload 30 failRemove: 5000, 31 32 // Class applied to the progress bar before uploading 33 preUploadClass: 'is-preupload', 34 35 // Applied once an object uploading 36 uploading: 'is-uploading', 37 38 // Applied to wrapper once an object is done uploading 39 uploadComplete: 'is-complete', 40 41 // Applied to wrapper once an object fails to upload 42 uploadFailed: 'is-failed', 43 44 // Applied to progress wrapper once object is done 45 progressComplete: 'is-progress-complete', 46 47 // Wrapper area, this becomes droppable NOTE: $this [input type file] must be a child of this wrapper! 48 wrapper: 'div', 49 50 // Class to apply when the droppable area is activated 51 dropActive: 'is-droppable', 52 53 // class to apply when hovering a drag over the drop area 54 dropHover: 'is-drophover', 55 56 // after a drop upload takes place this gets added 57 dropOver: 'is-dropover', 58 59 // Allow multiple file uploads 60 multiple: false, 61 62 // enable drag/drop uploader 63 droppable: true, 64 65 // Allowed file types 66 images: true, 67 68 // Use thumbnail 69 preview: true, 70 71 // Thumbnail class applied to wrapper when uploading images 72 previewClass: 'upload-preview', 73 74 // Amount of ms to wait till firing the success event 75 successDelay: 1000, 76 77 // Preview builder method 78 upload: function(file, wrapper){ 79 $field.WebEditionXHRUpload('upload', file, wrapper); 80 }, 81 82 // Progress action callback 83 progress: function(e, wrapper, progressBar){ 84 var percent = (e.loaded / e.total * 100 | 0); 85 86 if (percent < 100) 87 $field.WebEditionXHRUpload('message', percent + '% uploaded', wrapper, 'progress'); 88 else 89 $field.WebEditionXHRUpload('message', 'Processing Upload', wrapper, 'progress'); 90 91 // now just update the given progress bar 92 progressBar.val(percent * 0.75); 93 }, 94 95 // Slowly creeps the progress bar, will never complete 96 // you can re-assign this to boolean false to remove creep 97 creep: function(wrapper) { 98 var config = this; 99 setTimeout(function(){ 100 var $progressBar = wrapper.find('progress'), 101 current = $progressBar.val(), 102 remainingVal = (100 - current), 103 creep = current + (remainingVal * 0.10); 104 if (remainingVal) { 105 $progressBar.val(creep); 106 config.creep(wrapper); 107 } 108 }, 500); 109 }, 110 111 // FileType filter, simply return true or false for each file object 112 fileFilter: function (file){ return true; }, 113 114 // Do something after the upload is complete 115 success: function (data, wrapper) { 116 var config = $field.data('WebEditionXHRUpload'), 117 $droppable = $field.closest(config.wrapper); 118 119 $droppable 120 .removeClass(config.uploading) 121 .addClass(config.uploadComplete); 122 123 wrapper.find('progress').remove(); 124 wrapper.find('.upload-message').remove(); 125 }, 126 error: function (wrapper, errorMessage) { 127 console.log('errorTriggered'); 128 } 129 }; 130 131 132 // === EXTEND OUR CONFIGURATION 133 options = (options === undefined) ? {}:options; 134 $.extend(config, options); 135 136 137 // === FILTER CALLBACK FOR IMAGES 138 if (config.images && options.fileFilter === undefined) 139 config.fileFilter = function(file) { 140 return file.type.match('image.*'); 141 }; 142 143 144 // === UPLOAD EVENT FOR IMAGE PREVIEWS 145 if (config.images && config.preview && options.upload === undefined) { 146 config.upload = function(file, wrapper, e){ 147 var image = new Image(); 148 149 // Create our image 150 image.src = e.target.result; 151 wrapper.append(image); 152 153 // Begin the upload process 154 $field.WebEditionXHRUpload('upload', file, wrapper); 155 }; 156 } 157 158 if (config.multiple) $field.attr('multiple','true'); 159 160 161 // add the pre-upload class, ideally this would hide the progress bar 162 $field.data('WebEditionXHRUpload', config); 163 164 if (window.FormData === undefined) console.warn('Your browser does not support form uploading in WebEdition!'); 165 166 if (config.droppable) $field.WebEditionXHRUpload('droppable'); 167 168 169 // this is what actually triggers the upload event 170 $field.on('change', function(){ 171 $field.WebEditionXHRUpload('prepareUpload'); 172 }); 173 174 }, 175 176 prepareUpload: function(){ 177 var $field = $(this), 178 config = $field.data('WebEditionXHRUpload'), 179 $wrapper = $field.closest(config.wrapper), 180 data = new FormData(), 181 count = 0; 182 183 // produce a new FormData object with the proper file types, and call any necessary processing 184 $.each($field.get(0).files, function(idx, file) { 185 var $progressWrapper = $(config.progressWrapper).clone(false), // in case they sent a jquery object 186 $messageWrapper = $(config.messageWrapper).clone(false); 187 188 // Create the upload area 189 $wrapper.append($progressWrapper); 190 $progressWrapper.append($messageWrapper); 191 if (config.images && config.preview) { 192 $progressWrapper.addClass(config.previewClass); 193 } 194 195 if (config.fileFilter(file)) { 196 if (count < 1 || config.multiple) { 197 // If using images, and previews, create the preview image 198 if (config.images && config.preview) { 199 // If we are using an image preview, the preview will take care of the rest 200 $field.WebEditionXHRUpload('imagePreview', file, $progressWrapper); 201 } else { 202 // if we are uploading a file, upload directly from here after outputting name 203 $fileWrapper = $(config.fileWrapper).clone(false); 204 $progressWrapper.append($fileWrapper.html(file.name)); 205 config.upload(file, $progressWrapper); 206 } 207 count++; 208 } else { 209 $field.WebEditionXHRUpload('message','You may only upload one file at a time!', $progressWrapper, 'fail'); 210 console.warn('This XHRUploader was configured to accept a single file, you attempted to upload multiple'); 211 } 212 } else { 213 $field.WebEditionXHRUpload('message', 'Whoops! That ' + file.name + ' is the wrong filetype.', $progressWrapper, 'fail'); 214 console.warn('File type ' + file.type + ' did not match requirements'); 215 } 216 }); 217 218 $field.val(''); 219 }, 220 221 upload: function(file, wrapper){ 222 var $field = $(this), 223 config = $field.data('WebEditionXHRUpload'), 224 $droppable = $field.closest(config.wrapper), 225 xhr = $field.WebEditionXHRUpload('XHRFactory', wrapper), 226 data = new FormData(); 227 228 data.append($field.attr('name'), file); 229 230 $droppable 231 .addClass(config.uploading) 232 .addClass(config.dropOver); 233 234 if (typeof config.creep == 'function') { 235 // Begin an artificial, asymptotic progression of progress bar 236 setTimeout(function(){ 237 config.creep(wrapper); 238 }, 500); 239 } 240 241 242 // Perform the actual upload 243 Webe.ajax({ 244 url: config.url, 245 method: 'post', 246 cache: false, 247 contentType: false, 248 processData: false, 249 xhr: xhr, 250 data: data, 251 passthrough: false, 252 error: function(xhr, errorType, exeption){ 253 $droppable.removeClass(config.dropOver); 254 if (errorType == 'parsererror') { 255 $field.WebEditionXHRUpload('message', "An unknown error occurred processing your upload", wrapper, 'fail'); 256 } else { 257 $field.WebEditionXHRUpload('message', "An error occurred processing your upload: " + errorType, wrapper, 'fail'); 258 } 259 260 wrapper.find('progress').val(100); 261 }, 262 success: function(results) { 263 var completeUpload = function() { 264 $droppable 265 .removeClass(config.uploading) 266 .addClass(config.uploadComplete); 267 config.success(result, wrapper); 268 }; 269 270 results = (!(results instanceof Array) ? [results] : results); 271 272 for (var i in results) { 273 result = results[i]; 274 wrapper.find('progress').val(100); // this also terminates the creep 275 276 try { 277 if (result.status) { 278 // If the upload was successful: 279 wrapper.addClass(config.progressComplete); 280 $field.WebEditionXHRUpload('message', result.message, wrapper, 'success'); 281 setTimeout(completeUpload, config.successDelay); 282 283 // if the upload failed in some way 284 } else { 285 var message = (result.message === undefined) ? "An unknown error occurred while processing your upload." : result.message; 286 $field.WebEditionXHRUpload('message', message, wrapper, 'fail'); 287 $droppable.addClass(config.uploadFailed); 288 config.error(wrapper, message); 289 } 290 } catch(error) { 291 $field.WebEditionXHRUpload('message', "An unknown error occurred processing your upload", wrapper, 'fail'); 292 } 293 } 294 } 295 }); 296 }, 297 298 reset: function(wrapper) { 299 var $field = $(this), 300 config = $field.data('WebEditionXHRUpload'), 301 $droppable = $field.closest(config.wrapper); 302 303 $field.val(''); 304 305 $droppable 306 .removeClass(config.uploadComplete) 307 .removeClass(config.uploading) 308 .removeClass(config.dropOver); 309 310 wrapper.remove(); 311 }, 312 313 droppable: function(){ 314 var $field = $(this), 315 config = $field.data('WebEditionXHRUpload'), 316 $droppable = $field.closest(config.wrapper), 317 $help = $droppable.next('.help'); 318 319 // Apply the droppable class 320 $droppable.addClass(config.dropActive); 321 322 // Move help text within the uploader 323 $droppable.append($help); 324 325 // Listen for dragenter, and apply the dropHover class 326 $droppable.on('dragenter', function(e){ 327 e.stopPropagation(); 328 e.preventDefault(); 329 $droppable.addClass(config.dropHover); 330 }); 331 332 // Dragover event end 333 $droppable.on('dragover', function(e){ 334 e.stopPropagation(); 335 e.preventDefault(); 336 }); 337 338 // Remove classes when dragging is over 339 $droppable.on('dragleave', function(e){ 340 $droppable.removeClass(config.dropHover); 341 }); 342 343 // Perform the upload when the object is dropped 344 $droppable.on('drop', function(e){ 345 e.preventDefault(); 346 var files = e.originalEvent.dataTransfer.files; 347 348 $field.get(0).files = files; // assign the files to our uploader (triggering change event) 349 $droppable.removeClass(config.dropHover); 350 }); 351 }, 352 353 imagePreview: function(file, wrapper){ 354 var $field = $(this), 355 config = $field.data('WebEditionXHRUpload'), 356 reader = new FileReader(); 357 358 // Assign our callback event, with a double closure to provide 359 // the file as well as the event object to our upload() callback 360 $(reader).on('load', (function(f){ 361 return function(e){ 362 config.upload(f, wrapper, e); 363 }; 364 })(file)); 365 366 // Initiate
367 reader.readAsDataURL(file); 368 }, 369 370 message: function(message, wrapper, type) { 371 var $field = $(this), 372 config = $field.data('WebEditionXHRUpload'), 373 $messageContainer = wrapper.find('.'+($(config.messageWrapper).attr('class'))), 374 firstClass = $(config.messageWrapper).attr('class').split(" ")[0]; 375 376 type = (type === undefined) ? 'info' : type; 377 if (!firstClass) console.warn('Your messageWrapper must contain a class by default!'); 378 379 $messageContainer.attr('class', firstClass); 380 $messageContainer.addClass(config.messageStatusPrefix + type); 381 $messageContainer.html("<span>" + message + "</span>"); 382 }, 383 384 XHRFactory: function(wrapper){ 385 var $field = $(this), 386 config = $field.data('WebEditionXHRUpload'), 387 xhr = jQuery.ajaxSettings.xhr(), 388 $progressInstance = config.progressBar.clone(false); 389 $(wrapper).append($progressInstance); 390 391 if (xhr instanceof window.XMLHttpRequest) { 392 xhr.upload.addEventListener('progress', (function(progressBar){ 393 return function(e){ 394 config.progress(e, wrapper, progressBar); 395 }; 396 })($progressInstance)); 397 } else { 398 console.warn('Unable to properly build the XHR Object!'); 399 } 400 401 // return a closure with our special sauce xhr object 402 return function() { 403 return xhr; 404 }; 405 } 406 407 }; 408 409 if(actions[action]) return actions[action].apply(this, Array.prototype.slice.call(arguments, 1)); 410 else if(typeof action === 'object' || !action) return actions.init.apply(this, arguments); 411 else $.error(action + ' is an undefined action of WebEditionXHRUpload'); 412 413 }; 414 415})(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.