diff --git a/vendor/assets/javascripts/jquery-fileupload/app.js b/vendor/assets/javascripts/jquery-fileupload/app.js new file mode 100755 index 0000000..60a3fed --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/app.js @@ -0,0 +1,101 @@ +/* + * jQuery File Upload Plugin Angular JS Example 1.2.1 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, regexp: true */ +/*global window, angular */ + +(function () { + 'use strict'; + + var isOnGitHub = window.location.hostname === 'blueimp.github.io', + url = isOnGitHub ? '//jquery-file-upload.appspot.com/' : 'server/php/'; + + angular.module('demo', [ + 'blueimp.fileupload' + ]) + .config([ + '$httpProvider', 'fileUploadProvider', + function ($httpProvider, fileUploadProvider) { + delete $httpProvider.defaults.headers.common['X-Requested-With']; + fileUploadProvider.defaults.redirect = window.location.href.replace( + /\/[^\/]*$/, + '/cors/result.html?%s' + ); + if (isOnGitHub) { + // Demo settings: + angular.extend(fileUploadProvider.defaults, { + // Enable image resizing, except for Android and Opera, + // which actually support image resizing, but fail to + // send Blob objects via XHR requests: + disableImageResize: /Android(?!.*Chrome)|Opera/ + .test(window.navigator.userAgent), + maxFileSize: 5000000, + acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i + }); + } + } + ]) + + .controller('DemoFileUploadController', [ + '$scope', '$http', '$filter', '$window', + function ($scope, $http) { + $scope.options = { + url: url + }; + if (!isOnGitHub) { + $scope.loadingFiles = true; + $http.get(url) + .then( + function (response) { + $scope.loadingFiles = false; + $scope.queue = response.data.files || []; + }, + function () { + $scope.loadingFiles = false; + } + ); + } + } + ]) + + .controller('FileDestroyController', [ + '$scope', '$http', + function ($scope, $http) { + var file = $scope.file, + state; + if (file.url) { + file.$state = function () { + return state; + }; + file.$destroy = function () { + state = 'pending'; + return $http({ + url: file.deleteUrl, + method: file.deleteType + }).then( + function () { + state = 'resolved'; + $scope.clear(file); + }, + function () { + state = 'rejected'; + } + ); + }; + } else if (!file.$cancel && !file._index) { + file.$cancel = function () { + $scope.clear(file); + }; + } + } + ]); + +}()); diff --git a/vendor/assets/javascripts/jquery-fileupload/cors/jquery.postmessage-transport.js b/vendor/assets/javascripts/jquery-fileupload/cors/jquery.postmessage-transport.js index 931b635..2b4cbc5 100755 --- a/vendor/assets/javascripts/jquery-fileupload/cors/jquery.postmessage-transport.js +++ b/vendor/assets/javascripts/jquery-fileupload/cors/jquery.postmessage-transport.js @@ -1,5 +1,5 @@ /* - * jQuery postMessage Transport Plugin 1.1 + * jQuery postMessage Transport Plugin 1.1.1 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan @@ -64,8 +64,9 @@ xhrUpload = options.xhr().upload; return { send: function (_, completeCallback) { + counter += 1; var message = { - id: 'postmessage-transport-' + (counter += 1) + id: 'postmessage-transport-' + counter }, eventName = 'message.' + message.id; iframe = $( diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js index e7ba784..8f4abac 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload AngularJS Plugin 1.0.1 + * jQuery File Upload AngularJS Plugin 1.4.4 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan @@ -10,20 +10,42 @@ */ /*jslint nomen: true, unparam: true */ -/*global angular */ +/*global define, angular */ -(function () { +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'angular', + './jquery.fileupload-image', + './jquery.fileupload-audio', + './jquery.fileupload-video', + './jquery.fileupload-validate' + ], factory); + } else { + factory(); + } +}(function () { 'use strict'; angular.module('blueimp.fileupload', []) + // The fileUpload service provides configuration options + // for the fileUpload directive and default handlers for + // File Upload events: .provider('fileUpload', function () { var scopeApply = function () { var scope = angular.element(this) - .fileupload('option', 'scope')(); - if (!scope.$$phase) { + .fileupload('option', 'scope')(), + $timeout = angular.injector(['ng']) + .get('$timeout'); + // Safe apply, makes sure $apply is called + // asynchronously outside of the $digest cycle: + $timeout(function () { scope.$apply(); - } + }); }, $config; $config = this.defaults = { @@ -47,19 +69,22 @@ submit = function () { return data.submit(); }; + angular.forEach(data.files, function (file, index) { + file._index = index; + file.$state = function () { + return data.state(); + }; + file.$progress = function () { + return data.progress(); + }; + file.$response = function () { + return data.response(); + }; + }); file.$cancel = function () { scope.clear(data.files); return data.abort(); }; - file.$state = function () { - return data.state(); - }; - file.$progress = function () { - return data.progress(); - }; - file.$response = function () { - return data.response(); - }; if (file.$state() === 'rejected') { file._$submit = submit; } else { @@ -96,10 +121,11 @@ if (data.errorThrown === 'abort') { return; } - if (data.dataType.indexOf('json') === data.dataType.length - 4) { + if (data.dataType && + data.dataType.indexOf('json') === data.dataType.length - 4) { try { data.result = angular.fromJson(data.jqXHR.responseText); - } catch (err) {} + } catch (ignore) {} } data.scope().$apply(function () { data.handleResponse.call(that, e, data); @@ -112,7 +138,6 @@ return this.scope().queue.length; }, dataType: 'json', - prependFiles: true, autoUpload: false }; this.$get = [ @@ -124,8 +149,9 @@ ]; }) + // Format byte numbers to readable presentations: .provider('formatFileSizeFilter', function () { - var $config = this.defaults = { + var $config = { // Byte units following the IEC format // http://en.wikipedia.org/wiki/Kilobyte units: [ @@ -134,28 +160,58 @@ {size: 1000, suffix: ' KB'} ] }; + this.defaults = $config; this.$get = function () { return function (bytes) { if (!angular.isNumber(bytes)) { return ''; } var unit = true, - i = -1; + i = 0, + prefix, + suffix; while (unit) { - unit = $config.units[i += 1]; + unit = $config.units[i]; + prefix = unit.prefix || ''; + suffix = unit.suffix || ''; if (i === $config.units.length - 1 || bytes >= unit.size) { - return (bytes / unit.size).toFixed(2) + unit.suffix; + return prefix + (bytes / unit.size).toFixed(2) + suffix; } + i += 1; } }; }; }) + // The FileUploadController initializes the fileupload widget and + // provides scope methods to control the File Upload functionality: .controller('FileUploadController', [ - '$scope', '$element', '$attrs', 'fileUpload', - function ($scope, $element, $attrs, fileUpload) { - $scope.disabled = angular.element('') - .prop('disabled'); + '$scope', '$element', '$attrs', '$window', 'fileUpload', + function ($scope, $element, $attrs, $window, fileUpload) { + var uploadMethods = { + progress: function () { + return $element.fileupload('progress'); + }, + active: function () { + return $element.fileupload('active'); + }, + option: function (option, data) { + return $element.fileupload('option', option, data); + }, + add: function (data) { + return $element.fileupload('add', data); + }, + send: function (data) { + return $element.fileupload('send', data); + }, + process: function (data) { + return $element.fileupload('process', data); + }, + processing: function (data) { + return $element.fileupload('processing', data); + } + }; + $scope.disabled = !$window.jQuery.support.fileInput; $scope.queue = $scope.queue || []; $scope.clear = function (files) { var queue = this.queue, @@ -167,7 +223,8 @@ length = files.length; } while (i) { - if (queue[i -= 1] === file) { + i -= 1; + if (queue[i] === file) { return queue.splice(i, length); } } @@ -186,27 +243,6 @@ } } }; - $scope.progress = function () { - return $element.fileupload('progress'); - }; - $scope.active = function () { - return $element.fileupload('active'); - }; - $scope.option = function (option, data) { - return $element.fileupload('option', option, data); - }; - $scope.add = function (data) { - return $element.fileupload('add', data); - }; - $scope.send = function (data) { - return $element.fileupload('send', data); - }; - $scope.process = function (data) { - return $element.fileupload('process', data); - }; - $scope.processing = function (data) { - return $element.fileupload('processing', data); - }; $scope.applyOnQueue = function (method) { var list = this.queue.slice(0), i, @@ -224,6 +260,8 @@ $scope.cancel = function () { this.applyOnQueue('$cancel'); }; + // Add upload methods to the scope: + angular.extend($scope, uploadMethods); // The fileupload widget will initialize with // the options provided via "data-"-parameters, // as well as those given via options object: @@ -260,12 +298,23 @@ 'fileuploadprocessalways', 'fileuploadprocessstop' ].join(' '), function (e, data) { - $scope.$emit(e.type, data); + if ($scope.$emit(e.type, data).defaultPrevented) { + e.preventDefault(); + } + }).on('remove', function () { + // Remove upload methods from the scope, + // when the widget is removed: + var method; + for (method in uploadMethods) { + if (uploadMethods.hasOwnProperty(method)) { + delete $scope[method]; + } + } }); // Observe option changes: $scope.$watch( - $attrs.fileupload, - function (newOptions, oldOptions) { + $attrs.fileUpload, + function (newOptions) { if (newOptions) { $element.fileupload('option', newOptions); } @@ -274,10 +323,11 @@ } ]) + // Provide File Upload progress feedback: .controller('FileUploadProgressController', [ '$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) { - var fn = $parse($attrs.progress), + var fn = $parse($attrs.fileUploadProgress), update = function () { var progress = fn($scope); if (!progress || !progress.total) { @@ -289,7 +339,7 @@ }; update(); $scope.$watch( - $attrs.progress + '.loaded', + $attrs.fileUploadProgress + '.loaded', function (newValue, oldValue) { if (newValue !== oldValue) { update(); @@ -299,10 +349,11 @@ } ]) + // Display File Upload previews: .controller('FileUploadPreviewController', [ '$scope', '$element', '$attrs', '$parse', function ($scope, $element, $attrs, $parse) { - var fn = $parse($attrs.preview), + var fn = $parse($attrs.fileUploadPreview), file = fn($scope); if (file.preview) { $element.append(file.preview); @@ -310,26 +361,28 @@ } ]) - .directive('fileupload', function () { + .directive('fileUpload', function () { return { controller: 'FileUploadController' }; }) - .directive('progress', function () { + .directive('fileUploadProgress', function () { return { controller: 'FileUploadProgressController' }; }) - .directive('preview', function () { + .directive('fileUploadPreview', function () { return { controller: 'FileUploadPreviewController' }; }) + // Enhance the HTML5 download attribute to + // allow drag&drop of files to the desktop: .directive('download', function () { - return function (scope, elm, attrs) { + return function (scope, elm) { elm.on('dragstart', function (e) { try { e.originalEvent.dataTransfer.setData( @@ -340,9 +393,9 @@ elm.prop('href') ].join(':') ); - } catch (err) {} + } catch (ignore) {} }); }; }); -}()); +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-audio.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-audio.js new file mode 100755 index 0000000..f59c2fa --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-audio.js @@ -0,0 +1,106 @@ +/* + * jQuery File Upload Audio Preview Plugin 1.0.3 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'load-image', + './jquery.fileupload-process' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery, + window.loadImage + ); + } +}(function ($, loadImage) { + 'use strict'; + + // Prepend to the default processQueue: + $.blueimp.fileupload.prototype.options.processQueue.unshift( + { + action: 'loadAudio', + // Use the action as prefix for the "@" options: + prefix: true, + fileTypes: '@', + maxFileSize: '@', + disabled: '@disableAudioPreview' + }, + { + action: 'setAudio', + name: '@audioPreviewName', + disabled: '@disableAudioPreview' + } + ); + + // The File Upload Audio Preview plugin extends the fileupload widget + // with audio preview functionality: + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + // The regular expression for the types of audio files to load, + // matched against the file type: + loadAudioFileTypes: /^audio\/.*$/ + }, + + _audioElement: document.createElement('audio'), + + processActions: { + + // Loads the audio file given via data.files and data.index + // as audio element if the browser supports playing it. + // Accepts the options fileTypes (regular expression) + // and maxFileSize (integer) to limit the files to load: + loadAudio: function (data, options) { + if (options.disabled) { + return data; + } + var file = data.files[data.index], + url, + audio; + if (this._audioElement.canPlayType && + this._audioElement.canPlayType(file.type) && + ($.type(options.maxFileSize) !== 'number' || + file.size <= options.maxFileSize) && + (!options.fileTypes || + options.fileTypes.test(file.type))) { + url = loadImage.createObjectURL(file); + if (url) { + audio = this._audioElement.cloneNode(false); + audio.src = url; + audio.controls = true; + data.audio = audio; + return data; + } + } + return data; + }, + + // Sets the audio element as a property of the file object: + setAudio: function (data, options) { + if (data.audio && !options.disabled) { + data.files[data.index][options.name || 'preview'] = data.audio; + } + return data; + } + + } + + }); + +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js new file mode 100755 index 0000000..84474a7 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js @@ -0,0 +1,292 @@ +/* + * jQuery File Upload Image Preview & Resize Plugin 1.2.3 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document, DataView, Blob, Uint8Array */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'load-image', + 'load-image-meta', + 'load-image-exif', + 'load-image-ios', + 'canvas-to-blob', + './jquery.fileupload-process' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery, + window.loadImage + ); + } +}(function ($, loadImage) { + 'use strict'; + + // Prepend to the default processQueue: + $.blueimp.fileupload.prototype.options.processQueue.unshift( + { + action: 'loadImageMetaData', + disableImageHead: '@', + disableExif: '@', + disableExifThumbnail: '@', + disableExifSub: '@', + disableExifGps: '@', + disabled: '@disableImageMetaDataLoad' + }, + { + action: 'loadImage', + // Use the action as prefix for the "@" options: + prefix: true, + fileTypes: '@', + maxFileSize: '@', + noRevoke: '@', + disabled: '@disableImageLoad' + }, + { + action: 'resizeImage', + // Use "image" as prefix for the "@" options: + prefix: 'image', + maxWidth: '@', + maxHeight: '@', + minWidth: '@', + minHeight: '@', + crop: '@', + disabled: '@disableImageResize' + }, + { + action: 'saveImage', + disabled: '@disableImageResize' + }, + { + action: 'saveImageMetaData', + disabled: '@disableImageMetaDataSave' + }, + { + action: 'resizeImage', + // Use "preview" as prefix for the "@" options: + prefix: 'preview', + maxWidth: '@', + maxHeight: '@', + minWidth: '@', + minHeight: '@', + crop: '@', + orientation: '@', + thumbnail: '@', + canvas: '@', + disabled: '@disableImagePreview' + }, + { + action: 'setImage', + name: '@imagePreviewName', + disabled: '@disableImagePreview' + } + ); + + // The File Upload Resize plugin extends the fileupload widget + // with image resize functionality: + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + // The regular expression for the types of images to load: + // matched against the file type: + loadImageFileTypes: /^image\/(gif|jpeg|png)$/, + // The maximum file size of images to load: + loadImageMaxFileSize: 10000000, // 10MB + // The maximum width of resized images: + imageMaxWidth: 1920, + // The maximum height of resized images: + imageMaxHeight: 1080, + // Define if resized images should be cropped or only scaled: + imageCrop: false, + // Disable the resize image functionality by default: + disableImageResize: true, + // The maximum width of the preview images: + previewMaxWidth: 80, + // The maximum height of the preview images: + previewMaxHeight: 80, + // Defines the preview orientation (1-8) or takes the orientation + // value from Exif data if set to true: + previewOrientation: true, + // Create the preview using the Exif data thumbnail: + previewThumbnail: true, + // Define if preview images should be cropped or only scaled: + previewCrop: false, + // Define if preview images should be resized as canvas elements: + previewCanvas: true + }, + + processActions: { + + // Loads the image given via data.files and data.index + // as img element if the browser supports canvas. + // Accepts the options fileTypes (regular expression) + // and maxFileSize (integer) to limit the files to load: + loadImage: function (data, options) { + if (options.disabled) { + return data; + } + var that = this, + file = data.files[data.index], + dfd = $.Deferred(); + if (($.type(options.maxFileSize) === 'number' && + file.size > options.maxFileSize) || + (options.fileTypes && + !options.fileTypes.test(file.type)) || + !loadImage( + file, + function (img) { + if (img.src) { + data.img = img; + } + dfd.resolveWith(that, [data]); + }, + options + )) { + return data; + } + return dfd.promise(); + }, + + // Resizes the image given as data.canvas or data.img + // and updates data.canvas or data.img with the resized image. + // Accepts the options maxWidth, maxHeight, minWidth, + // minHeight, canvas and crop: + resizeImage: function (data, options) { + if (options.disabled) { + return data; + } + var that = this, + dfd = $.Deferred(), + resolve = function (newImg) { + data[newImg.getContext ? 'canvas' : 'img'] = newImg; + dfd.resolveWith(that, [data]); + }, + thumbnail, + img, + newImg; + options = $.extend({canvas: true}, options); + if (data.exif) { + if (options.orientation === true) { + options.orientation = data.exif.get('Orientation'); + } + if (options.thumbnail) { + thumbnail = data.exif.get('Thumbnail'); + if (thumbnail) { + loadImage(thumbnail, resolve, options); + return dfd.promise(); + } + } + } + img = (options.canvas && data.canvas) || data.img; + if (img) { + newImg = loadImage.scale(img, options); + if (newImg.width !== img.width || + newImg.height !== img.height) { + resolve(newImg); + return dfd.promise(); + } + } + return data; + }, + + // Saves the processed image given as data.canvas + // inplace at data.index of data.files: + saveImage: function (data, options) { + if (!data.canvas || options.disabled) { + return data; + } + var that = this, + file = data.files[data.index], + name = file.name, + dfd = $.Deferred(), + callback = function (blob) { + if (!blob.name) { + if (file.type === blob.type) { + blob.name = file.name; + } else if (file.name) { + blob.name = file.name.replace( + /\..+$/, + '.' + blob.type.substr(6) + ); + } + } + // Store the created blob at the position + // of the original file in the files list: + data.files[data.index] = blob; + dfd.resolveWith(that, [data]); + }; + // Use canvas.mozGetAsFile directly, to retain the filename, as + // Gecko doesn't support the filename option for FormData.append: + if (data.canvas.mozGetAsFile) { + callback(data.canvas.mozGetAsFile( + (/^image\/(jpeg|png)$/.test(file.type) && name) || + ((name && name.replace(/\..+$/, '')) || + 'blob') + '.png', + file.type + )); + } else if (data.canvas.toBlob) { + data.canvas.toBlob(callback, file.type); + } else { + return data; + } + return dfd.promise(); + }, + + loadImageMetaData: function (data, options) { + if (options.disabled) { + return data; + } + var that = this, + dfd = $.Deferred(); + loadImage.parseMetaData(data.files[data.index], function (result) { + $.extend(data, result); + dfd.resolveWith(that, [data]); + }, options); + return dfd.promise(); + }, + + saveImageMetaData: function (data, options) { + if (!(data.imageHead && data.canvas && + data.canvas.toBlob && !options.disabled)) { + return data; + } + var file = data.files[data.index], + blob = new Blob([ + data.imageHead, + // Resized images always have a head size of 20 bytes, + // including the JPEG marker and a minimal JFIF header: + this._blobSlice.call(file, 20) + ], {type: file.type}); + blob.name = file.name; + data.files[data.index] = blob; + return data; + }, + + // Sets the resized version of the image as a property of the + // file object, must be called after "saveImage": + setImage: function (data, options) { + var img = data.canvas || data.img; + if (img && !options.disabled) { + data.files[data.index][options.name || 'preview'] = img; + } + return data; + } + + } + + }); + +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-jquery-ui.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-jquery-ui.js new file mode 100755 index 0000000..05dd7a6 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-jquery-ui.js @@ -0,0 +1,138 @@ +/* + * jQuery File Upload jQuery UI Plugin 8.7.0 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true */ +/*global define, window */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery', './jquery.fileupload-ui'], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + progress: function (e, data) { + if (data.context) { + data.context.find('.progress').progressbar( + 'option', + 'value', + parseInt(data.loaded / data.total * 100, 10) + ); + } + }, + progressall: function (e, data) { + var $this = $(this); + $this.find('.fileupload-progress') + .find('.progress').progressbar( + 'option', + 'value', + parseInt(data.loaded / data.total * 100, 10) + ).end() + .find('.progress-extended').each(function () { + $(this).html( + ($this.data('blueimp-fileupload') || + $this.data('fileupload')) + ._renderExtendedProgress(data) + ); + }); + } + }, + + _renderUpload: function (func, files) { + var node = this._super(func, files), + showIconText = $(window).width() > 480; + node.find('.progress').empty().progressbar(); + node.find('.start').button({ + icons: {primary: 'ui-icon-circle-arrow-e'}, + text: showIconText + }); + node.find('.cancel').button({ + icons: {primary: 'ui-icon-cancel'}, + text: showIconText + }); + return node; + }, + + _renderDownload: function (func, files) { + var node = this._super(func, files), + showIconText = $(window).width() > 480; + node.find('.delete').button({ + icons: {primary: 'ui-icon-trash'}, + text: showIconText + }); + return node; + }, + + _transition: function (node) { + var deferred = $.Deferred(); + if (node.hasClass('fade')) { + node.fadeToggle( + this.options.transitionDuration, + this.options.transitionEasing, + function () { + deferred.resolveWith(node); + } + ); + } else { + deferred.resolveWith(node); + } + return deferred; + }, + + _create: function () { + this._super(); + this.element + .find('.fileupload-buttonbar') + .find('.fileinput-button').each(function () { + var input = $(this).find('input:file').detach(); + $(this) + .button({icons: {primary: 'ui-icon-plusthick'}}) + .append(input); + }) + .end().find('.start') + .button({icons: {primary: 'ui-icon-circle-arrow-e'}}) + .end().find('.cancel') + .button({icons: {primary: 'ui-icon-cancel'}}) + .end().find('.delete') + .button({icons: {primary: 'ui-icon-trash'}}) + .end().find('.progress').progressbar(); + }, + + _destroy: function () { + this.element + .find('.fileupload-buttonbar') + .find('.fileinput-button').each(function () { + var input = $(this).find('input:file').detach(); + $(this) + .button('destroy') + .append(input); + }) + .end().find('.start') + .button('destroy') + .end().find('.cancel') + .button('destroy') + .end().find('.delete') + .button('destroy') + .end().find('.progress').progressbar('destroy'); + this._super(); + } + + }); + +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js index 2f9eeed..87042c3 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload Processing Plugin 1.1 + * jQuery File Upload Processing Plugin 1.2.2 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2012, Sebastian Tschan @@ -98,14 +98,20 @@ _transformProcessQueue: function (options) { var processQueue = []; $.each(options.processQueue, function () { - var settings = {}; + var settings = {}, + action = this.action, + prefix = this.prefix === true ? action : this.prefix; $.each(this, function (key, value) { if ($.type(value) === 'string' && value.charAt(0) === '@') { - settings[key] = options[value.slice(1)]; + settings[key] = options[ + value.slice(1) || (prefix ? prefix + + key.charAt(0).toUpperCase() + key.slice(1) : key) + ]; } else { settings[key] = value; } + }); processQueue.push(settings); }); @@ -127,7 +133,7 @@ if (this._processing === 0) { this._trigger('processstart'); } - $.each(data.files, function (index, file) { + $.each(data.files, function (index) { var opts = index ? $.extend({}, options) : options, func = function () { return that._processFile(opts); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js index 5d22346..4006a64 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload User Interface Plugin 8.2.1 + * jQuery File Upload User Interface Plugin 8.8.5 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan @@ -19,7 +19,9 @@ define([ 'jquery', 'tmpl', - './jquery.fileupload-resize', + './jquery.fileupload-image', + './jquery.fileupload-audio', + './jquery.fileupload-video', './jquery.fileupload-validate' ], factory); } else { @@ -118,7 +120,7 @@ !$.support.transition && 'progress-animated' ) .attr('aria-valuenow', 100) - .find('.bar').css( + .children().first().css( 'width', '100%' ); @@ -137,8 +139,8 @@ if (data.context) { data.context.each(function (index) { var file = files[index] || - {error: 'Empty file upload result'}, - deferred = that._addFinishedDeferreds(); + {error: 'Empty file upload result'}; + deferred = that._addFinishedDeferreds(); that._transition($(this)).done( function () { var node = $(this); @@ -157,8 +159,9 @@ ); }); } else { - template = that._renderDownload(files) - .appendTo(that.options.filesContainer); + template = that._renderDownload(files)[ + that.options.prependFiles ? 'prependTo' : 'appendTo' + ](that.options.filesContainer); that._forceReflow(template); deferred = that._addFinishedDeferreds(); that._transition(template).done( @@ -213,8 +216,9 @@ } }); } else if (data.errorThrown !== 'abort') { - data.context = that._renderUpload(data.files) - .appendTo(that.options.filesContainer) + data.context = that._renderUpload(data.files)[ + that.options.prependFiles ? 'prependTo' : 'appendTo' + ](that.options.filesContainer) .data('data', data); that._forceReflow(data.context); deferred = that._addFinishedDeferreds(); @@ -234,14 +238,16 @@ }, // Callback for upload progress events: progress: function (e, data) { + var progress = Math.floor(data.loaded / data.total * 100); if (data.context) { - var progress = Math.floor(data.loaded / data.total * 100); - data.context.find('.progress') - .attr('aria-valuenow', progress) - .find('.bar').css( - 'width', - progress + '%' - ); + data.context.each(function () { + $(this).find('.progress') + .attr('aria-valuenow', progress) + .children().first().css( + 'width', + progress + '%' + ); + }); } }, // Callback for global upload progress events: @@ -260,7 +266,7 @@ globalProgressNode .find('.progress') .attr('aria-valuenow', progress) - .find('.bar').css( + .children().first().css( 'width', progress + '%' ); @@ -289,7 +295,7 @@ function () { $(this).find('.progress') .attr('aria-valuenow', '0') - .find('.bar').css('width', '0%'); + .children().first().css('width', '0%'); $(this).find('.progress-extended').html(' '); deferred.resolve(); } @@ -304,16 +310,19 @@ // Callback for file deletion: destroy: function (e, data) { var that = $(this).data('blueimp-fileupload') || - $(this).data('fileupload'); - if (data.url) { - $.ajax(data).done(function () { + $(this).data('fileupload'), + removeNode = function () { that._transition(data.context).done( function () { $(this).remove(); that._trigger('destroyed', e, data); } ); - }); + }; + if (data.url) { + $.ajax(data).done(removeNode); + } else { + removeNode(); } } }, @@ -453,9 +462,11 @@ _cancelHandler: function (e) { e.preventDefault(); - var template = $(e.currentTarget).closest('.template-upload'), + var template = $(e.currentTarget) + .closest('.template-upload,.template-download'), data = template.data('data') || {}; if (!data.jqXHR) { + data.context = data.context || template; data.errorThrown = 'abort'; this._trigger('fail', e, data); } else { @@ -606,6 +617,9 @@ _create: function () { this._super(); this._resetFinishedDeferreds(); + if (!$.support.fileInput) { + this._disableFileInputButton(); + } }, enable: function () { diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js index 2599da8..ee1c2f2 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload Validation Plugin 1.0.2 + * jQuery File Upload Validation Plugin 1.1.1 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan @@ -37,10 +37,10 @@ // even if the previous action was rejected: always: true, // Options taken from the global options map: - acceptFileTypes: '@acceptFileTypes', - maxFileSize: '@maxFileSize', - minFileSize: '@minFileSize', - maxNumberOfFiles: '@maxNumberOfFiles', + acceptFileTypes: '@', + maxFileSize: '@', + minFileSize: '@', + maxNumberOfFiles: '@', disabled: '@disableValidation' } ); @@ -83,16 +83,17 @@ } var dfd = $.Deferred(), settings = this.options, - file = data.files[data.index], - numberOfFiles = settings.getNumberOfFiles(); - if (numberOfFiles && $.type(options.maxNumberOfFiles) === 'number' && - numberOfFiles + data.files.length > options.maxNumberOfFiles) { + file = data.files[data.index]; + if ($.type(options.maxNumberOfFiles) === 'number' && + (settings.getNumberOfFiles() || 0) + data.files.length > + options.maxNumberOfFiles) { file.error = settings.i18n('maxNumberOfFiles'); } else if (options.acceptFileTypes && !(options.acceptFileTypes.test(file.type) || options.acceptFileTypes.test(file.name))) { file.error = settings.i18n('acceptFileTypes'); - } else if (options.maxFileSize && file.size > options.maxFileSize) { + } else if (options.maxFileSize && file.size > + options.maxFileSize) { file.error = settings.i18n('maxFileSize'); } else if ($.type(file.size) === 'number' && file.size < options.minFileSize) { diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-video.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-video.js new file mode 100755 index 0000000..c8b1019 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-video.js @@ -0,0 +1,106 @@ +/* + * jQuery File Upload Video Preview Plugin 1.0.3 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'load-image', + './jquery.fileupload-process' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery, + window.loadImage + ); + } +}(function ($, loadImage) { + 'use strict'; + + // Prepend to the default processQueue: + $.blueimp.fileupload.prototype.options.processQueue.unshift( + { + action: 'loadVideo', + // Use the action as prefix for the "@" options: + prefix: true, + fileTypes: '@', + maxFileSize: '@', + disabled: '@disableVideoPreview' + }, + { + action: 'setVideo', + name: '@videoPreviewName', + disabled: '@disableVideoPreview' + } + ); + + // The File Upload Video Preview plugin extends the fileupload widget + // with video preview functionality: + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + // The regular expression for the types of video files to load, + // matched against the file type: + loadVideoFileTypes: /^video\/.*$/ + }, + + _videoElement: document.createElement('video'), + + processActions: { + + // Loads the video file given via data.files and data.index + // as video element if the browser supports playing it. + // Accepts the options fileTypes (regular expression) + // and maxFileSize (integer) to limit the files to load: + loadVideo: function (data, options) { + if (options.disabled) { + return data; + } + var file = data.files[data.index], + url, + video; + if (this._videoElement.canPlayType && + this._videoElement.canPlayType(file.type) && + ($.type(options.maxFileSize) !== 'number' || + file.size <= options.maxFileSize) && + (!options.fileTypes || + options.fileTypes.test(file.type))) { + url = loadImage.createObjectURL(file); + if (url) { + video = this._videoElement.cloneNode(false); + video.src = url; + video.controls = true; + data.video = video; + return data; + } + } + return data; + }, + + // Sets the video element as a property of the file object: + setVideo: function (data, options) { + if (data.video && !options.disabled) { + data.files[data.index][options.name || 'preview'] = data.video; + } + return data; + } + + } + + }); + +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js index 03678f3..0fe69fa 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload Plugin 5.31.1 + * jQuery File Upload Plugin 5.32.5 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan @@ -10,7 +10,7 @@ */ /*jslint nomen: true, unparam: true, regexp: true */ -/*global define, window, document, File, Blob, FormData, location */ +/*global define, window, document, location, File, Blob, FormData */ (function (factory) { 'use strict'; @@ -27,12 +27,28 @@ }(function ($) { 'use strict'; + // Detect file input support, based on + // http://viljamis.com/blog/2012/file-upload-support-on-mobile/ + $.support.fileInput = !(new RegExp( + // Handle devices which give false positives for the feature detection: + '(Android (1\\.[0156]|2\\.[01]))' + + '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' + + '|(w(eb)?OSBrowser)|(webOS)' + + '|(Kindle/(1\\.0|2\\.[05]|3\\.0))' + ).test(window.navigator.userAgent) || + // Feature detection for all other devices: + $('').prop('disabled')); + // The FileReader API is not actually used, but works as feature detection, // as e.g. Safari supports XHR file uploads via the FormData API, // but not non-multipart XHR file uploads: $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader); $.support.xhrFormDataFileUpload = !!window.FormData; + // Detect support for Blob slicing (required for chunked uploads): + $.support.blobSlice = window.Blob && (Blob.prototype.slice || + Blob.prototype.webkitSlice || Blob.prototype.mozSlice); + // The fileupload widget listens for change events on file input fields defined // via fileInput setting and paste or drop events of the given dropZone. // In addition to the default jQuery Widget methods, the fileupload widget @@ -144,13 +160,16 @@ // The add callback is invoked as soon as files are added to the fileupload // widget (via file input selection, drag & drop, paste or add API call). // If the singleFileUploads option is enabled, this callback will be - // called once for each file in the selection for XHR file uplaods, else + // called once for each file in the selection for XHR file uploads, else // once for each file selection. + // // The upload starts when the submit method is invoked on the data parameter. // The data object contains a files property holding the added files - // and allows to override plugin options as well as define ajax settings. + // and allows you to override plugin options as well as define ajax settings. + // // Listeners for this callback can also be bound the following way: // .bind('fileuploadadd', func); + // // data.submit() returns a Promise object and allows to attach additional // handlers using jQuery's Deferred callbacks: // data.submit().done(func).fail(func).always(func); @@ -233,6 +252,11 @@ 'forceIframeTransport' ], + _blobSlice: $.support.blobSlice && function () { + var slice = this.slice || this.webkitSlice || this.mozSlice; + return slice.apply(this, arguments); + }, + _BitrateTimer: function () { this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); this.loaded = 0; @@ -375,13 +399,15 @@ // Ignore non-multipart setting if not supported: multipart = options.multipart || !$.support.xhrFileUpload, paramName = options.paramName[0]; - options.headers = options.headers || {}; + options.headers = $.extend({}, options.headers); if (options.contentRange) { options.headers['Content-Range'] = options.contentRange; } - if (!multipart) { + if (!multipart || options.blob || !this._isInstanceOf('File', file)) { options.headers['Content-Disposition'] = 'attachment; filename="' + encodeURI(file.name) + '"'; + } + if (!multipart) { options.contentType = file.type; options.data = options.blob || file; } else if ($.support.xhrFormDataFileUpload) { @@ -414,8 +440,6 @@ }); } if (options.blob) { - options.headers['Content-Disposition'] = 'attachment; filename="' + - encodeURI(file.name) + '"'; formData.append(paramName, options.blob, file.name); } else { $.each(options.files, function (index, file) { @@ -439,13 +463,13 @@ }, _initIframeSettings: function (options) { + var targetHost = $('').prop('href', options.url).prop('host'); // Setting the dataType to iframe enables the iframe transport: options.dataType = 'iframe ' + (options.dataType || ''); // The iframe transport accepts a serialized array as form data: options.formData = this._getFormData(options); // Add redirect url to form data on cross-domain uploads: - if (options.redirect && $('').prop('href', options.url) - .prop('host') !== location.host) { + if (options.redirect && targetHost && targetHost !== location.host) { options.formData.push({ name: options.redirectParamName || 'redirect', value: options.redirect @@ -627,12 +651,13 @@ // should be uploaded in chunks, but does not invoke any // upload requests: _chunkedUpload: function (options, testOnly) { + options.uploadedBytes = options.uploadedBytes || 0; var that = this, file = options.files[0], fs = file.size, - ub = options.uploadedBytes = options.uploadedBytes || 0, + ub = options.uploadedBytes, mcs = options.maxChunkSize || fs, - slice = file.slice || file.webkitSlice || file.mozSlice, + slice = this._blobSlice, dfd = $.Deferred(), promise = dfd.promise(), jqXHR, @@ -850,7 +875,8 @@ this._slots.push(slot); pipe = slot.pipe(send); } else { - pipe = (this._sequence = this._sequence.pipe(send, send)); + this._sequence = this._sequence.pipe(send, send); + pipe = this._sequence; } // Return the piped Promise object, enhanced with an abort method, // which is delegated to the jqXHR object of the current upload, @@ -1092,17 +1118,16 @@ data.files.push(file); } }); - if (this._trigger('paste', e, data) === false || - this._onAdd(e, data) === false) { - return false; + if (this._trigger('paste', e, data) !== false) { + this._onAdd(e, data); } } }, _onDrop: function (e) { + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; var that = this, - dataTransfer = e.dataTransfer = e.originalEvent && - e.originalEvent.dataTransfer, + dataTransfer = e.dataTransfer, data = {}; if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { e.preventDefault(); @@ -1116,14 +1141,16 @@ }, _onDragOver: function (e) { - var dataTransfer = e.dataTransfer = e.originalEvent && - e.originalEvent.dataTransfer; - if (dataTransfer) { - if (this._trigger('dragover', e) === false) { - return false; - } - if ($.inArray('Files', dataTransfer.types) !== -1) { - dataTransfer.dropEffect = 'copy'; + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; + var dataTransfer = e.dataTransfer, + data = { + dropEffect: 'copy', + preventDefault: true + }; + if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && + this._trigger('dragover', e, data) !== false) { + dataTransfer.dropEffect = data.dropEffect; + if (data.preventDefault) { e.preventDefault(); } } @@ -1139,9 +1166,11 @@ paste: this._onPaste }); } - this._on(this.options.fileInput, { - change: this._onChange - }); + if ($.support.fileInput) { + this._on(this.options.fileInput, { + change: this._onChange + }); + } }, _destroyEventHandlers: function () { @@ -1275,6 +1304,10 @@ if (aborted) { return; } + if (!files.length) { + dfd.reject(); + return; + } data.files = files; jqXHR = that._onSend(null, data).then( function (result, textStatus, jqXHR) { diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js b/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js index e04e7a0..073c5fb 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js @@ -1,5 +1,5 @@ /* - * jQuery Iframe Transport Plugin 1.6.2 + * jQuery Iframe Transport Plugin 1.7 * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan @@ -170,7 +170,15 @@ }); // The iframe transport returns the iframe content document as response. - // The following adds converters from iframe to text, json, html, and script: + // The following adds converters from iframe to text, json, html, xml + // and script. + // Please note that the Content-Type for JSON responses has to be text/plain + // or text/html, if the browser doesn't include application/json in the + // Accept header, else IE will show a download dialog. + // The Content-Type for XML responses on the other hand has to be always + // application/xml or text/xml, so IE properly parses the XML response. + // See also + // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation $.ajaxSetup({ converters: { 'iframe text': function (iframe) { @@ -182,6 +190,12 @@ 'iframe html': function (iframe) { return iframe && $(iframe[0].body).html(); }, + 'iframe xml': function (iframe) { + var xmlDoc = iframe && iframe[0]; + return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : + $.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) || + $(xmlDoc.body).html()); + }, 'iframe script': function (iframe) { return iframe && $.globalEval($(iframe[0].body).text()); } diff --git a/vendor/assets/javascripts/jquery-fileupload/main.js b/vendor/assets/javascripts/jquery-fileupload/main.js new file mode 100755 index 0000000..11b948a --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/main.js @@ -0,0 +1,76 @@ +/* + * jQuery File Upload Plugin JS Example 8.8.2 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, regexp: true */ +/*global $, window, blueimp */ + +$(function () { + 'use strict'; + + // Initialize the jQuery File Upload widget: + $('#fileupload').fileupload({ + // Uncomment the following to send cross-domain cookies: + //xhrFields: {withCredentials: true}, + url: 'server/php/' + }); + + // Enable iframe cross-domain access via redirect option: + $('#fileupload').fileupload( + 'option', + 'redirect', + window.location.href.replace( + /\/[^\/]*$/, + '/cors/result.html?%s' + ) + ); + + if (window.location.hostname === 'blueimp.github.io') { + // Demo settings: + $('#fileupload').fileupload('option', { + url: '//jquery-file-upload.appspot.com/', + // Enable image resizing, except for Android and Opera, + // which actually support image resizing, but fail to + // send Blob objects via XHR requests: + disableImageResize: /Android(?!.*Chrome)|Opera/ + .test(window.navigator.userAgent), + maxFileSize: 5000000, + acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i + }); + // Upload server status check for browsers with CORS support: + if ($.support.cors) { + $.ajax({ + url: '//jquery-file-upload.appspot.com/', + type: 'HEAD' + }).fail(function () { + $('
') + .text('Upload server currently unavailable - ' + + new Date()) + .appendTo('#fileupload'); + }); + } + } else { + // Load existing files: + $('#fileupload').addClass('fileupload-processing'); + $.ajax({ + // Uncomment the following to send cross-domain cookies: + //xhrFields: {withCredentials: true}, + url: $('#fileupload').fileupload('option', 'url'), + dataType: 'json', + context: $('#fileupload')[0] + }).always(function () { + $(this).removeClass('fileupload-processing'); + }).done(function (result) { + $(this).fileupload('option', 'done') + .call(this, null, {result: result}); + }); + } + +}); diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js old mode 100644 new mode 100755 index fd2948f..2d37089 --- a/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js @@ -1,5 +1,5 @@ /* - * jQuery UI Widget 1.10.1+amd + * jQuery UI Widget 1.10.3+amd * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013 jQuery Foundation and other contributors