From 4c5b4875030de1932cb6a4da96641270167205ea Mon Sep 17 00:00:00 2001
From: Ciprian Florescu
Date: Sun, 23 Feb 2014 02:49:14 +0000
Subject: [PATCH 1/2] Uploaded assets to version 9.5.6 - adapted for images
---
lib/jquery/fileupload/rails/version.rb | 2 +-
.../cors/jquery.postmessage-transport.js | 8 +-
.../cors/jquery.xdr-transport.js | 3 +-
.../javascripts/jquery-fileupload/index.js | 18 +-
.../jquery-fileupload/jquery.fileupload-fp.js | 227 ----------
.../jquery.fileupload-image.js | 309 +++++++++++++
.../jquery.fileupload-process.js | 172 +++++++
.../jquery-fileupload/jquery.fileupload-ui.js | 422 +++++++-----------
.../jquery.fileupload-validate.js | 119 +++++
.../jquery-fileupload/jquery.fileupload.js | 375 ++++++++++++----
.../jquery.iframe-transport.js | 57 ++-
.../vendor/jquery.ui.widget.js | 12 +-
.../stylesheets/jquery.fileupload-ui.scss | 77 ++--
13 files changed, 1129 insertions(+), 672 deletions(-)
delete mode 100644 vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-fp.js
create mode 100644 vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js
create mode 100644 vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js
create mode 100644 vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js
diff --git a/lib/jquery/fileupload/rails/version.rb b/lib/jquery/fileupload/rails/version.rb
index 10fbdc9..e325029 100644
--- a/lib/jquery/fileupload/rails/version.rb
+++ b/lib/jquery/fileupload/rails/version.rb
@@ -1,7 +1,7 @@
module JQuery
module FileUpload
module Rails
- VERSION = "0.4.1"
+ VERSION = "0.4.2"
end
end
end
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..2b4851e 100644
--- 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
@@ -9,8 +9,7 @@
* http://www.opensource.org/licenses/MIT
*/
-/*jslint unparam: true, nomen: true */
-/*global define, window, document */
+/* global define, window, document */
(function (factory) {
'use strict';
@@ -64,8 +63,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/cors/jquery.xdr-transport.js b/vendor/assets/javascripts/jquery-fileupload/cors/jquery.xdr-transport.js
index d769f45..0044cc2 100644
--- a/vendor/assets/javascripts/jquery-fileupload/cors/jquery.xdr-transport.js
+++ b/vendor/assets/javascripts/jquery-fileupload/cors/jquery.xdr-transport.js
@@ -12,8 +12,7 @@
* https://github.com/jaubourg/ajaxHooks/
*/
-/*jslint unparam: true */
-/*global define, window, XDomainRequest */
+/* global define, window, XDomainRequest */
(function (factory) {
'use strict';
diff --git a/vendor/assets/javascripts/jquery-fileupload/index.js b/vendor/assets/javascripts/jquery-fileupload/index.js
index 0cda385..569a8d5 100644
--- a/vendor/assets/javascripts/jquery-fileupload/index.js
+++ b/vendor/assets/javascripts/jquery-fileupload/index.js
@@ -1,9 +1,9 @@
-//=require jquery-fileupload/vendor/jquery.ui.widget
-//=require jquery-fileupload/vendor/load-image
-//=require jquery-fileupload/vendor/canvas-to-blob
-//=require jquery-fileupload/vendor/tmpl
-//=require jquery-fileupload/jquery.iframe-transport
-//=require jquery-fileupload/jquery.fileupload
-//=require jquery-fileupload/jquery.fileupload-fp
-//=require jquery-fileupload/jquery.fileupload-ui
-//=require jquery-fileupload/locale
+//= require jquery-fileupload/vendor/jquery.ui.widget
+//= require jquery-fileupload/vendor/load-image
+//= require jquery-fileupload/jquery.iframe-transport
+//= require jquery-fileupload/jquery.fileupload
+//= require jquery-fileupload/jquery.fileupload-process
+//= require jquery-fileupload/jquery.fileupload-validate
+//= require jquery-fileupload/jquery.fileupload-image
+//= require jquery-fileupload/jquery.fileupload-ui
+//= require jquery-fileupload/locale
diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-fp.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-fp.js
deleted file mode 100644
index c782f1e..0000000
--- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-fp.js
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * jQuery File Upload File Processing Plugin 1.2.3
- * https://github.com/blueimp/jQuery-File-Upload
- *
- * Copyright 2012, 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',
- 'canvas-to-blob',
- './jquery.fileupload'
- ], factory);
- } else {
- // Browser globals:
- factory(
- window.jQuery,
- window.loadImage
- );
- }
-}(function ($, loadImage) {
- 'use strict';
-
- // The File Upload FP version extends the fileupload widget
- // with file processing functionality:
- $.widget('blueimp.fileupload', $.blueimp.fileupload, {
-
- options: {
- // The list of file processing actions:
- process: [
- /*
- {
- action: 'load',
- fileTypes: /^image\/(gif|jpeg|png)$/,
- maxFileSize: 20000000 // 20MB
- },
- {
- action: 'resize',
- maxWidth: 1920,
- maxHeight: 1200,
- minWidth: 800,
- minHeight: 600
- },
- {
- action: 'save'
- }
- */
- ],
-
- // The add callback is invoked as soon as files are added to the
- // fileupload widget (via file input selection, drag & drop or add
- // API call). See the basic file upload widget for more information:
- add: function (e, data) {
- if (data.autoUpload || (data.autoUpload !== false &&
- ($(this).data('blueimp-fileupload') ||
- $(this).data('fileupload')).options.autoUpload)) {
- $(this).fileupload('process', data).done(function () {
- data.submit();
- });
- }
- }
- },
-
- 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:
- load: function (data, options) {
- var that = this,
- file = data.files[data.index],
- dfd = $.Deferred();
- if (window.HTMLCanvasElement &&
- window.HTMLCanvasElement.prototype.toBlob &&
- ($.type(options.maxFileSize) !== 'number' ||
- file.size < options.maxFileSize) &&
- (!options.fileTypes ||
- options.fileTypes.test(file.type))) {
- loadImage(
- file,
- function (img) {
- if (!img.src) {
- return dfd.rejectWith(that, [data]);
- }
- data.img = img;
- dfd.resolveWith(that, [data]);
- }
- );
- } else {
- dfd.rejectWith(that, [data]);
- }
- return dfd.promise();
- },
- // Resizes the image given as data.img and updates
- // data.canvas with the resized image as canvas element.
- // Accepts the options maxWidth, maxHeight, minWidth and
- // minHeight to scale the given image:
- resize: function (data, options) {
- var img = data.img,
- canvas;
- options = $.extend({canvas: true}, options);
- if (img) {
- canvas = loadImage.scale(img, options);
- if (canvas.width !== img.width ||
- canvas.height !== img.height) {
- data.canvas = canvas;
- }
- }
- return data;
- },
- // Saves the processed image given as data.canvas
- // inplace at data.index of data.files:
- save: function (data, options) {
- // Do nothing if no processing has happened:
- if (!data.canvas) {
- 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 {
- data.canvas.toBlob(callback, file.type);
- }
- return dfd.promise();
- }
- },
-
- // Resizes the file at the given index and stores the created blob at
- // the original position of the files list, returns a Promise object:
- _processFile: function (files, index, options) {
- var that = this,
- dfd = $.Deferred().resolveWith(that, [{
- files: files,
- index: index
- }]),
- chain = dfd.promise();
- that._processing += 1;
- $.each(options.process, function (i, settings) {
- chain = chain.pipe(function (data) {
- return that.processActions[settings.action]
- .call(this, data, settings);
- });
- });
- chain.always(function () {
- that._processing -= 1;
- if (that._processing === 0) {
- that.element
- .removeClass('fileupload-processing');
- }
- });
- if (that._processing === 1) {
- that.element.addClass('fileupload-processing');
- }
- return chain;
- },
-
- // Processes the files given as files property of the data parameter,
- // returns a Promise object that allows to bind a done handler, which
- // will be invoked after processing all files (inplace) is done:
- process: function (data) {
- var that = this,
- options = $.extend({}, this.options, data);
- if (options.process && options.process.length &&
- this._isXHRUpload(options)) {
- $.each(data.files, function (index, file) {
- that._processingQueue = that._processingQueue.pipe(
- function () {
- var dfd = $.Deferred();
- that._processFile(data.files, index, options)
- .always(function () {
- dfd.resolveWith(that);
- });
- return dfd.promise();
- }
- );
- });
- }
- return this._processingQueue;
- },
-
- _create: function () {
- this._super();
- this._processing = 0;
- this._processingQueue = $.Deferred().resolveWith(this)
- .promise();
- }
-
- });
-
-}));
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 100644
index 0000000..f73c24e
--- /dev/null
+++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js
@@ -0,0 +1,309 @@
+/*
+ * jQuery File Upload Image Preview & Resize Plugin 1.7.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
+ */
+
+/* jshint nomen:false */
+/* global define, window */
+
+(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: '@',
+ orientation: '@',
+ forceResize: '@',
+ disabled: '@disableImageResize'
+ },
+ {
+ action: 'saveImage',
+ quality: '@imageQuality',
+ type: '@imageType',
+ 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'
+ },
+ {
+ action: 'deleteImageReferences',
+ disabled: '@disableImageReferencesDeletion'
+ }
+ );
+
+ // 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|svg\+xml)$/,
+ // 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,
+ // Defines the image orientation (1-8) or takes the orientation
+ // value from Exif data if set to true:
+ imageOrientation: false,
+ // 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 the File API.
+ // 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.
+ // Also stores the resized image as preview property.
+ // Accepts the options maxWidth, maxHeight, minWidth,
+ // minHeight, canvas and crop:
+ resizeImage: function (data, options) {
+ if (options.disabled || !(data.canvas || data.img)) {
+ return data;
+ }
+ options = $.extend({canvas: true}, options);
+ var that = this,
+ dfd = $.Deferred(),
+ img = (options.canvas && data.canvas) || data.img,
+ resolve = function (newImg) {
+ if (newImg && (newImg.width !== img.width ||
+ newImg.height !== img.height ||
+ options.forceResize)) {
+ data[newImg.getContext ? 'canvas' : 'img'] = newImg;
+ }
+ data.preview = newImg;
+ dfd.resolveWith(that, [data]);
+ },
+ thumbnail;
+ 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();
+ }
+ }
+ }
+ if (img) {
+ resolve(loadImage.scale(img, options));
+ 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],
+ dfd = $.Deferred();
+ if (data.canvas.toBlob) {
+ data.canvas.toBlob(
+ 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)
+ );
+ }
+ }
+ // Don't restore invalid meta data:
+ if (file.type !== blob.type) {
+ delete data.imageHead;
+ }
+ // Store the created blob at the position
+ // of the original file in the files list:
+ data.files[data.index] = blob;
+ dfd.resolveWith(that, [data]);
+ },
+ options.type || file.type,
+ options.quality
+ );
+ } else {
+ return data;
+ }
+ return dfd.promise();
+ },
+
+ loadImageMetaData: function (data, options) {
+ if (options.disabled) {
+ return data;
+ }
+ var that = this,
+ dfd = $.Deferred();
+ loadImage(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) {
+ if (data.preview && !options.disabled) {
+ data.files[data.index][options.name || 'preview'] = data.preview;
+ }
+ return data;
+ },
+
+ deleteImageReferences: function (data, options) {
+ if (!options.disabled) {
+ delete data.img;
+ delete data.canvas;
+ delete data.preview;
+ delete data.imageHead;
+ }
+ return data;
+ }
+
+ }
+
+ });
+
+}));
diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js
new file mode 100644
index 0000000..8a6b929
--- /dev/null
+++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js
@@ -0,0 +1,172 @@
+/*
+ * jQuery File Upload Processing Plugin 1.3.0
+ * https://github.com/blueimp/jQuery-File-Upload
+ *
+ * Copyright 2012, Sebastian Tschan
+ * https://blueimp.net
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/MIT
+ */
+
+/* jshint nomen:false */
+/* global define, window */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ 'jquery',
+ './jquery.fileupload'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.jQuery
+ );
+ }
+}(function ($) {
+ 'use strict';
+
+ var originalAdd = $.blueimp.fileupload.prototype.options.add;
+
+ // The File Upload Processing plugin extends the fileupload widget
+ // with file processing functionality:
+ $.widget('blueimp.fileupload', $.blueimp.fileupload, {
+
+ options: {
+ // The list of processing actions:
+ processQueue: [
+ /*
+ {
+ action: 'log',
+ type: 'debug'
+ }
+ */
+ ],
+ add: function (e, data) {
+ var $this = $(this);
+ data.process(function () {
+ return $this.fileupload('process', data);
+ });
+ originalAdd.call(this, e, data);
+ }
+ },
+
+ processActions: {
+ /*
+ log: function (data, options) {
+ console[options.type](
+ 'Processing "' + data.files[data.index].name + '"'
+ );
+ }
+ */
+ },
+
+ _processFile: function (data, originalData) {
+ var that = this,
+ dfd = $.Deferred().resolveWith(that, [data]),
+ chain = dfd.promise();
+ this._trigger('process', null, data);
+ $.each(data.processQueue, function (i, settings) {
+ var func = function (data) {
+ if (originalData.errorThrown) {
+ return $.Deferred()
+ .rejectWith(that, [originalData]).promise();
+ }
+ return that.processActions[settings.action].call(
+ that,
+ data,
+ settings
+ );
+ };
+ chain = chain.pipe(func, settings.always && func);
+ });
+ chain
+ .done(function () {
+ that._trigger('processdone', null, data);
+ that._trigger('processalways', null, data);
+ })
+ .fail(function () {
+ that._trigger('processfail', null, data);
+ that._trigger('processalways', null, data);
+ });
+ return chain;
+ },
+
+ // Replaces the settings of each processQueue item that
+ // are strings starting with an "@", using the remaining
+ // substring as key for the option map,
+ // e.g. "@autoUpload" is replaced with options.autoUpload:
+ _transformProcessQueue: function (options) {
+ var processQueue = [];
+ $.each(options.processQueue, function () {
+ 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) || (prefix ? prefix +
+ key.charAt(0).toUpperCase() + key.slice(1) : key)
+ ];
+ } else {
+ settings[key] = value;
+ }
+
+ });
+ processQueue.push(settings);
+ });
+ options.processQueue = processQueue;
+ },
+
+ // Returns the number of files currently in the processsing queue:
+ processing: function () {
+ return this._processing;
+ },
+
+ // Processes the files given as files property of the data parameter,
+ // returns a Promise object that allows to bind callbacks:
+ process: function (data) {
+ var that = this,
+ options = $.extend({}, this.options, data);
+ if (options.processQueue && options.processQueue.length) {
+ this._transformProcessQueue(options);
+ if (this._processing === 0) {
+ this._trigger('processstart');
+ }
+ $.each(data.files, function (index) {
+ var opts = index ? $.extend({}, options) : options,
+ func = function () {
+ if (data.errorThrown) {
+ return $.Deferred()
+ .rejectWith(that, [data]).promise();
+ }
+ return that._processFile(opts, data);
+ };
+ opts.index = index;
+ that._processing += 1;
+ that._processingQueue = that._processingQueue.pipe(func, func)
+ .always(function () {
+ that._processing -= 1;
+ if (that._processing === 0) {
+ that._trigger('processstop');
+ }
+ });
+ });
+ }
+ return this._processingQueue;
+ },
+
+ _create: function () {
+ this._super();
+ this._processing = 0;
+ this._processingQueue = $.Deferred().resolveWith(this)
+ .promise();
+ }
+
+ });
+
+}));
diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js
index 0386fb2..248e9f6 100644
--- 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 7.4.1
+ * jQuery File Upload User Interface Plugin 9.5.2
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
@@ -9,8 +9,8 @@
* http://www.opensource.org/licenses/MIT
*/
-/*jslint nomen: true, unparam: true, regexp: true */
-/*global define, window, URL, webkitURL, FileReader */
+/* jshint nomen:false */
+/* global define, window blada*/
(function (factory) {
'use strict';
@@ -19,20 +19,25 @@
define([
'jquery',
'tmpl',
- 'load-image',
- './jquery.fileupload-fp'
+ './jquery.fileupload-image',
+ './jquery.fileupload-validate'
], factory);
} else {
// Browser globals:
factory(
window.jQuery,
- window.tmpl,
- window.loadImage
+ window.tmpl
);
}
-}(function ($, tmpl, loadImage) {
+}(function ($, tmpl) {
'use strict';
+ $.blueimp.fileupload.prototype._specialOptions.push(
+ 'filesContainer',
+ 'uploadTemplateId',
+ 'downloadTemplateId'
+ );
+
// The UI version extends the file upload widget
// and adds complete user interface interaction:
$.widget('blueimp.fileupload', $.blueimp.fileupload, {
@@ -42,29 +47,6 @@
// as the user clicks on the start buttons. To enable automatic
// uploads, set the following option to true:
autoUpload: false,
- // The following option limits the number of files that are
- // allowed to be uploaded using this widget:
- maxNumberOfFiles: undefined,
- // The maximum allowed file size:
- maxFileSize: undefined,
- // The minimum allowed file size:
- minFileSize: undefined,
- // The regular expression for allowed file types, matches
- // against either file type or file name:
- acceptFileTypes: /.+$/i,
- // The regular expression to define for which files a preview
- // image is shown, matched against the file type:
- previewSourceFileTypes: /^image\/(gif|jpeg|png)$/,
- // The maximum file size of images that are to be displayed as preview:
- previewSourceMaxFileSize: 5000000, // 5MB
- // The maximum width of the preview images:
- previewMaxWidth: 80,
- // The maximum height of the preview images:
- previewMaxHeight: 80,
- // By default, preview images are displayed as canvas elements
- // if supported by the browser. Set the following option to false
- // to always display preview images as img elements:
- previewAsCanvas: true,
// The ID of the upload template:
uploadTemplateId: 'template-upload',
// The ID of the download template:
@@ -79,48 +61,74 @@
// option of the $.ajax upload requests:
dataType: 'json',
+ // Function returning the current number of files,
+ // used by the maxNumberOfFiles validation:
+ getNumberOfFiles: function () {
+ return this.filesContainer.children()
+ .not('.processing').length;
+ },
+
+ // Callback to retrieve the list of files from the server response:
+ getFilesFromResponse: function (data) {
+ if (data.result && $.isArray(data.result.files)) {
+ return data.result.files;
+ }
+ return [];
+ },
+
// The add callback is invoked as soon as files are added to the fileupload
// widget (via file input selection, drag & drop or add API call).
// See the basic file upload widget for more information:
add: function (e, data) {
- var that = $(this).data('blueimp-fileupload') ||
- $(this).data('fileupload'),
- options = that.options,
- files = data.files;
- $(this).fileupload('process', data).done(function () {
- that._adjustMaxNumberOfFiles(-files.length);
- data.maxNumberOfFilesAdjusted = true;
- data.files.valid = data.isValidated = that._validate(files);
- data.context = that._renderUpload(files).data('data', data);
- options.filesContainer[
- options.prependFiles ? 'prepend' : 'append'
- ](data.context);
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+ var $this = $(this),
+ that = $this.data('blueimp-fileupload') ||
+ $this.data('fileupload'),
+ options = that.options;
+ data.context = that._renderUpload(data.files)
+ .data('data', data)
+ .addClass('processing');
+ options.filesContainer[
+ options.prependFiles ? 'prepend' : 'append'
+ ](data.context);
+ that._forceReflow(data.context);
+ that._transition(data.context);
+ data.process(function () {
+ return $this.fileupload('process', data);
+ }).always(function () {
+ data.context.each(function (index) {
+ $(this).find('.size').text(
+ that._formatFileSize(data.files[index].size)
+ );
+ }).removeClass('processing');
that._renderPreviews(data);
- that._forceReflow(data.context);
- that._transition(data.context).done(
- function () {
- if ((that._trigger('added', e, data) !== false) &&
- (options.autoUpload || data.autoUpload) &&
- data.autoUpload !== false && data.isValidated) {
- data.submit();
+ }).done(function () {
+ data.context.find('.start').prop('disabled', false);
+ if ((that._trigger('added', e, data) !== false) &&
+ (options.autoUpload || data.autoUpload) &&
+ data.autoUpload !== false) {
+ data.submit();
+ }
+ }).fail(function () {
+ if (data.files.error) {
+ data.context.each(function (index) {
+ var error = data.files[index].error;
+ if (error) {
+ $(this).find('.error').text(error);
}
- }
- );
+ });
+ }
});
},
// Callback for the start of each file upload request:
send: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
var that = $(this).data('blueimp-fileupload') ||
$(this).data('fileupload');
- if (!data.isValidated) {
- if (!data.maxNumberOfFilesAdjusted) {
- that._adjustMaxNumberOfFiles(-data.files.length);
- data.maxNumberOfFilesAdjusted = true;
- }
- if (!that._validate(data.files)) {
- return false;
- }
- }
if (data.context && data.dataType &&
data.dataType.substr(0, 6) === 'iframe') {
// Iframe Transport does not support progress events.
@@ -131,7 +139,7 @@
!$.support.transition && 'progress-animated'
)
.attr('aria-valuenow', 100)
- .find('.bar').css(
+ .children().first().css(
'width',
'100%'
);
@@ -140,19 +148,21 @@
},
// Callback for successful uploads:
done: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
var that = $(this).data('blueimp-fileupload') ||
$(this).data('fileupload'),
- files = that._getFilesFromResponse(data),
+ getFilesFromResponse = data.getFilesFromResponse ||
+ that.options.getFilesFromResponse,
+ files = getFilesFromResponse(data),
template,
deferred;
if (data.context) {
data.context.each(function (index) {
var file = files[index] ||
- {error: 'Empty file upload result'},
- deferred = that._addFinishedDeferreds();
- if (file.error) {
- that._adjustMaxNumberOfFiles(1);
- }
+ {error: 'Empty file upload result'};
+ deferred = that._addFinishedDeferreds();
that._transition($(this)).done(
function () {
var node = $(this);
@@ -171,19 +181,9 @@
);
});
} else {
- if (files.length) {
- $.each(files, function (index, file) {
- if (data.maxNumberOfFilesAdjusted && file.error) {
- that._adjustMaxNumberOfFiles(1);
- } else if (!data.maxNumberOfFilesAdjusted &&
- !file.error) {
- that._adjustMaxNumberOfFiles(-1);
- }
- });
- data.maxNumberOfFilesAdjusted = true;
- }
- 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(
@@ -198,13 +198,13 @@
},
// Callback for failed (abort or error) uploads:
fail: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
var that = $(this).data('blueimp-fileupload') ||
$(this).data('fileupload'),
template,
deferred;
- if (data.maxNumberOfFilesAdjusted) {
- that._adjustMaxNumberOfFiles(data.files.length);
- }
if (data.context) {
data.context.each(function (index) {
if (data.errorThrown !== 'abort') {
@@ -241,8 +241,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();
@@ -262,18 +263,26 @@
},
// Callback for upload progress events:
progress: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+ 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:
progressall: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
var $this = $(this),
progress = Math.floor(data.loaded / data.total * 100),
globalProgressNode = $this.find('.fileupload-progress'),
@@ -288,13 +297,16 @@
globalProgressNode
.find('.progress')
.attr('aria-valuenow', progress)
- .find('.bar').css(
+ .children().first().css(
'width',
progress + '%'
);
},
// Callback for uploads start, equivalent to the global ajaxStart event:
start: function (e) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
var that = $(this).data('blueimp-fileupload') ||
$(this).data('fileupload');
that._resetFinishedDeferreds();
@@ -306,6 +318,9 @@
},
// Callback for uploads stop, equivalent to the global ajaxStop event:
stop: function (e) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
var that = $(this).data('blueimp-fileupload') ||
$(this).data('fileupload'),
deferred = that._addFinishedDeferreds();
@@ -317,26 +332,47 @@
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();
}
);
},
+ processstart: function (e) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+ $(this).addClass('fileupload-processing');
+ },
+ processstop: function (e) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
+ $(this).removeClass('fileupload-processing');
+ },
// Callback for file deletion:
destroy: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
var that = $(this).data('blueimp-fileupload') ||
- $(this).data('fileupload');
+ $(this).data('fileupload'),
+ removeNode = function () {
+ that._transition(data.context).done(
+ function () {
+ $(this).remove();
+ that._trigger('destroyed', e, data);
+ }
+ );
+ };
if (data.url) {
- $.ajax(data);
- that._adjustMaxNumberOfFiles(1);
+ data.dataType = data.dataType || that.options.dataType;
+ $.ajax(data).done(removeNode).fail(function () {
+ that._trigger('destroyfailed', e, data);
+ });
+ } else {
+ removeNode();
}
- that._transition(data.context).done(
- function () {
- $(this).remove();
- that._trigger('destroyed', e, data);
- }
- );
}
},
@@ -356,13 +392,6 @@
return this._finishedUploads;
},
- _getFilesFromResponse: function (data) {
- if (data.result && $.isArray(data.result.files)) {
- return data.result.files;
- }
- return [];
- },
-
// Link handler, that allows to download files
// by drag & drop of the links to the desktop:
_enableDragToDesktop: function () {
@@ -376,21 +405,10 @@
'DownloadURL',
[type, name, url].join(':')
);
- } catch (err) {}
+ } catch (ignore) {}
});
},
- _adjustMaxNumberOfFiles: function (operand) {
- if (typeof this.options.maxNumberOfFiles === 'number') {
- this.options.maxNumberOfFiles += operand;
- if (this.options.maxNumberOfFiles < 1) {
- this._disableFileInputButton();
- } else {
- this._enableFileInputButton();
- }
- }
- },
-
_formatFileSize: function (bytes) {
if (typeof bytes !== 'number') {
return '';
@@ -446,46 +464,6 @@
this._formatFileSize(data.total);
},
- _hasError: function (file) {
- if (file.error) {
- return file.error;
- }
- // The number of added files is subtracted from
- // maxNumberOfFiles before validation, so we check if
- // maxNumberOfFiles is below 0 (instead of below 1):
- if (this.options.maxNumberOfFiles < 0) {
- return 'Maximum number of files exceeded';
- }
- // Files are accepted if either the file type or the file name
- // matches against the acceptFileTypes regular expression, as
- // only browsers with support for the File API report the type:
- if (!(this.options.acceptFileTypes.test(file.type) ||
- this.options.acceptFileTypes.test(file.name))) {
- return 'Filetype not allowed';
- }
- if (this.options.maxFileSize &&
- file.size > this.options.maxFileSize) {
- return 'File is too big';
- }
- if (typeof file.size === 'number' &&
- file.size < this.options.minFileSize) {
- return 'File is too small';
- }
- return null;
- },
-
- _validate: function (files) {
- var that = this,
- valid = !!files.length;
- $.each(files, function (index, file) {
- file.error = that._hasError(file);
- if (file.error) {
- valid = false;
- }
- });
- return valid;
- },
-
_renderTemplate: function (func, files) {
if (!func) {
return $();
@@ -501,63 +479,10 @@
return $(this.options.templatesContainer).html(result).children();
},
- _renderPreview: function (file, node) {
- var that = this,
- options = this.options,
- dfd = $.Deferred();
- return ((loadImage && loadImage(
- file,
- function (img) {
- node.append(img);
- that._forceReflow(node);
- that._transition(node).done(function () {
- dfd.resolveWith(node);
- });
- if (!$.contains(that.document[0].body, node[0])) {
- // If the element is not part of the DOM,
- // transition events are not triggered,
- // so we have to resolve manually:
- dfd.resolveWith(node);
- }
- node.on('remove', function () {
- // If the element is removed before the
- // transition finishes, transition events are
- // not triggered, resolve manually:
- dfd.resolveWith(node);
- });
- },
- {
- maxWidth: options.previewMaxWidth,
- maxHeight: options.previewMaxHeight,
- canvas: options.previewAsCanvas
- }
- )) || dfd.resolveWith(node)) && dfd;
- },
-
_renderPreviews: function (data) {
- var that = this,
- options = this.options;
- data.context.find('.preview span').each(function (index, element) {
- var file = data.files[index];
- if (options.previewSourceFileTypes.test(file.type) &&
- ($.type(options.previewSourceMaxFileSize) !== 'number' ||
- file.size < options.previewSourceMaxFileSize)) {
- that._processingQueue = that._processingQueue.pipe(function () {
- var dfd = $.Deferred(),
- ev = $.Event('previewdone', {
- target: element
- });
- that._renderPreview(file, $(element)).done(
- function () {
- that._trigger(ev.type, ev, data);
- dfd.resolveWith(that);
- }
- );
- return dfd.promise();
- });
- }
+ data.context.find('.preview').each(function (index, elm) {
+ $(elm).append(data.files[index].preview);
});
- return this._processingQueue;
},
_renderUpload: function (files) {
@@ -579,20 +504,23 @@
var button = $(e.currentTarget),
template = button.closest('.template-upload'),
data = template.data('data');
- if (data && data.submit && !data.jqXHR && data.submit()) {
- button.prop('disabled', true);
+ button.prop('disabled', true);
+ if (data && data.submit) {
+ data.submit();
}
},
_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;
+ if (data.abort) {
+ data.abort();
+ } else {
data.errorThrown = 'abort';
this._trigger('fail', e, data);
- } else {
- data.jqXHR.abort();
}
},
@@ -601,8 +529,7 @@
var button = $(e.currentTarget);
this._trigger('destroy', e, $.extend({
context: button.closest('.template-download'),
- type: 'DELETE',
- dataType: this.options.dataType
+ type: 'DELETE'
}, button.data()));
},
@@ -731,55 +658,18 @@
}
},
- _stringToRegExp: function (str) {
- var parts = str.split('/'),
- modifiers = parts.pop();
- parts.shift();
- return new RegExp(parts.join('/'), modifiers);
- },
-
- _initRegExpOptions: function () {
- var options = this.options;
- if ($.type(options.acceptFileTypes) === 'string') {
- options.acceptFileTypes = this._stringToRegExp(
- options.acceptFileTypes
- );
- }
- if ($.type(options.previewSourceFileTypes) === 'string') {
- options.previewSourceFileTypes = this._stringToRegExp(
- options.previewSourceFileTypes
- );
- }
- },
-
_initSpecialOptions: function () {
this._super();
this._initFilesContainer();
this._initTemplates();
- this._initRegExpOptions();
- },
-
- _setOption: function (key, value) {
- this._super(key, value);
- if (key === 'maxNumberOfFiles') {
- this._adjustMaxNumberOfFiles(0);
- }
},
_create: function () {
this._super();
- this._refreshOptionsList.push(
- 'filesContainer',
- 'uploadTemplateId',
- 'downloadTemplateId'
- );
- if (!this._processingQueue) {
- this._processingQueue = $.Deferred().resolveWith(this).promise();
- this.process = function () {
- return this._processingQueue;
- };
- }
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
new file mode 100644
index 0000000..f93a18f
--- /dev/null
+++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js
@@ -0,0 +1,119 @@
+/*
+ * jQuery File Upload Validation Plugin 1.1.2
+ * 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
+ */
+
+/* global define, window */
+
+(function (factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ // Register as an anonymous AMD module:
+ define([
+ 'jquery',
+ './jquery.fileupload-process'
+ ], factory);
+ } else {
+ // Browser globals:
+ factory(
+ window.jQuery
+ );
+ }
+}(function ($) {
+ 'use strict';
+
+ // Append to the default processQueue:
+ $.blueimp.fileupload.prototype.options.processQueue.push(
+ {
+ action: 'validate',
+ // Always trigger this action,
+ // even if the previous action was rejected:
+ always: true,
+ // Options taken from the global options map:
+ acceptFileTypes: '@',
+ maxFileSize: '@',
+ minFileSize: '@',
+ maxNumberOfFiles: '@',
+ disabled: '@disableValidation'
+ }
+ );
+
+ // The File Upload Validation plugin extends the fileupload widget
+ // with file validation functionality:
+ $.widget('blueimp.fileupload', $.blueimp.fileupload, {
+
+ options: {
+ /*
+ // The regular expression for allowed file types, matches
+ // against either file type or file name:
+ acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
+ // The maximum allowed file size in bytes:
+ maxFileSize: 10000000, // 10 MB
+ // The minimum allowed file size in bytes:
+ minFileSize: undefined, // No minimal file size
+ // The limit of files to be uploaded:
+ maxNumberOfFiles: 10,
+ */
+
+ // Function returning the current number of files,
+ // has to be overriden for maxNumberOfFiles validation:
+ getNumberOfFiles: $.noop,
+
+ // Error and info messages:
+ messages: {
+ maxNumberOfFiles: 'Maximum number of files exceeded',
+ acceptFileTypes: 'File type not allowed',
+ maxFileSize: 'File is too large',
+ minFileSize: 'File is too small'
+ }
+ },
+
+ processActions: {
+
+ validate: function (data, options) {
+ if (options.disabled) {
+ return data;
+ }
+ var dfd = $.Deferred(),
+ settings = this.options,
+ file = data.files[data.index],
+ fileSize;
+ if (options.minFileSize || options.maxFileSize) {
+ fileSize = file.size;
+ }
+ 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 (fileSize > options.maxFileSize) {
+ file.error = settings.i18n('maxFileSize');
+ } else if ($.type(fileSize) === 'number' &&
+ fileSize < options.minFileSize) {
+ file.error = settings.i18n('minFileSize');
+ } else {
+ delete file.error;
+ }
+ if (file.error || data.files.error) {
+ data.files.error = true;
+ dfd.rejectWith(this, [data]);
+ } else {
+ dfd.resolveWith(this, [data]);
+ }
+ return dfd.promise();
+ }
+
+ }
+
+ });
+
+}));
diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js
index dbee297..0803592 100644
--- 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.28.4
+ * jQuery File Upload Plugin 5.40.1
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
@@ -9,8 +9,8 @@
* http://www.opensource.org/licenses/MIT
*/
-/*jslint nomen: true, unparam: true, regexp: true */
-/*global define, window, document, File, Blob, FormData, location */
+/* jshint nomen:false */
+/* global define, window, document, location, Blob, FormData */
(function (factory) {
'use strict';
@@ -27,12 +27,30 @@
}(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);
+ // as some Safari versions (5?) support XHR file uploads via the FormData API,
+ // but not non-multipart XHR file uploads.
+ // window.XMLHttpRequestUpload is not available on IE10, so we check for
+ // window.ProgressEvent instead to detect XHR2 file upload capability:
+ $.support.xhrFileUpload = !!(window.ProgressEvent && 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
@@ -72,6 +90,14 @@
// To limit the number of files uploaded with one XHR request,
// set the following option to an integer greater than 0:
limitMultiFileUploads: undefined,
+ // The following option limits the number of files uploaded with one
+ // XHR request to keep the request size under or equal to the defined
+ // limit in bytes:
+ limitMultiFileUploadSize: undefined,
+ // Multipart file uploads add a number of bytes to each uploaded file,
+ // therefore the following option adds an overhead for each file used
+ // in the limitMultiFileUploadSize configuration:
+ limitMultiFileUploadSizeOverhead: 512,
// Set the following option to true to issue all file upload requests
// in a sequential order:
sequentialUploads: false,
@@ -115,6 +141,23 @@
// By default, uploads are started automatically when adding files:
autoUpload: true,
+ // Error and info messages:
+ messages: {
+ uploadedBytes: 'Uploaded bytes exceed file size'
+ },
+
+ // Translation function, gets the message key to be translated
+ // and an object with context specific data as arguments:
+ i18n: function (message, context) {
+ message = this.messages[message] || message.toString();
+ if (context) {
+ $.each(context, function (key, value) {
+ message = message.replace('{' + key + '}', value);
+ });
+ }
+ return message;
+ },
+
// Additional form data to be sent along with the file uploads can be set
// using this option, which accepts an array of objects with name and
// value properties, a function returning such an array, a FormData
@@ -127,21 +170,28 @@
// 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);
add: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
if (data.autoUpload || (data.autoUpload !== false &&
- ($(this).data('blueimp-fileupload') ||
- $(this).data('fileupload')).options.autoUpload)) {
- data.submit();
+ $(this).fileupload('option', 'autoUpload'))) {
+ data.process().done(function () {
+ data.submit();
+ });
}
},
@@ -205,8 +255,9 @@
cache: false
},
- // A list of options that require a refresh after assigning a new value:
- _refreshOptionsList: [
+ // A list of options that require reinitializing event listeners and/or
+ // special initialization code:
+ _specialOptions: [
'fileInput',
'dropZone',
'pasteZone',
@@ -214,8 +265,13 @@
'forceIframeTransport'
],
+ _blobSlice: $.support.blobSlice && function () {
+ var slice = this.slice || this.webkitSlice || this.mozSlice;
+ return slice.apply(this, arguments);
+ },
+
_BitrateTimer: function () {
- this.timestamp = (new Date()).getTime();
+ this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());
this.loaded = 0;
this.bitrate = 0;
this.getBitrate = function (now, loaded, interval) {
@@ -237,7 +293,7 @@
_getFormData: function (options) {
var formData;
- if (typeof options.formData === 'function') {
+ if ($.type(options.formData) === 'function') {
return options.formData(options.form);
}
if ($.isArray(options.formData)) {
@@ -289,7 +345,7 @@
_onProgress: function (e, data) {
if (e.lengthComputable) {
- var now = (new Date()).getTime(),
+ var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
loaded;
if (data._time && data.progressInterval &&
(now - data._time < data.progressInterval) &&
@@ -317,10 +373,18 @@
// Trigger a custom progress event with a total data property set
// to the file size(s) of the current upload and a loaded data
// property calculated accordingly:
- this._trigger('progress', e, data);
+ this._trigger(
+ 'progress',
+ $.Event('progress', {delegatedEvent: e}),
+ data
+ );
// Trigger a global progress event for all current file uploads,
// including ajax calls queued for sequential file uploads:
- this._trigger('progressall', e, this._progress);
+ this._trigger(
+ 'progressall',
+ $.Event('progressall', {delegatedEvent: e}),
+ this._progress
+ );
}
},
@@ -344,20 +408,29 @@
}
},
+ _isInstanceOf: function (type, obj) {
+ // Cross-frame instanceof check
+ return Object.prototype.toString.call(obj) === '[object ' + type + ']';
+ },
+
_initXHRData: function (options) {
- var formData,
+ var that = this,
+ formData,
file = options.files[0],
// Ignore non-multipart setting if not supported:
multipart = options.multipart || !$.support.xhrFileUpload,
- paramName = options.paramName[0];
- options.headers = options.headers || {};
+ paramName = $.type(options.paramName) === 'array' ?
+ options.paramName[0] : options.paramName;
+ 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) + '"';
- options.contentType = file.type;
+ }
+ if (!multipart) {
+ options.contentType = file.type || 'application/octet-stream';
options.data = options.blob || file;
} else if ($.support.xhrFormDataFileUpload) {
if (options.postMessage) {
@@ -374,13 +447,14 @@
} else {
$.each(options.files, function (index, file) {
formData.push({
- name: options.paramName[index] || paramName,
+ name: ($.type(options.paramName) === 'array' &&
+ options.paramName[index]) || paramName,
value: file
});
});
}
} else {
- if (options.formData instanceof FormData) {
+ if (that._isInstanceOf('FormData', options.formData)) {
formData = options.formData;
} else {
formData = new FormData();
@@ -389,21 +463,18 @@
});
}
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) {
- // Files are also Blob instances, but some browsers
- // (Firefox 3.6) support the File API but not Blobs.
// This check allows the tests to run with
// dummy objects:
- if ((window.Blob && file instanceof Blob) ||
- (window.File && file instanceof File)) {
+ if (that._isInstanceOf('File', file) ||
+ that._isInstanceOf('Blob', file)) {
formData.append(
- options.paramName[index] || paramName,
+ ($.type(options.paramName) === 'array' &&
+ options.paramName[index]) || paramName,
file,
- file.name
+ file.uploadName || file.name
);
}
});
@@ -416,13 +487,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
@@ -444,7 +515,7 @@
options.dataType = 'postmessage ' + (options.dataType || '');
}
} else {
- this._initIframeSettings(options, 'iframe');
+ this._initIframeSettings(options);
}
},
@@ -487,8 +558,10 @@
options.url = options.form.prop('action') || location.href;
}
// The HTTP request method must be "POST" or "PUT":
- options.type = (options.type || options.form.prop('method') || '')
- .toUpperCase();
+ options.type = (options.type ||
+ ($.type(options.form.prop('method')) === 'string' &&
+ options.form.prop('method')) || ''
+ ).toUpperCase();
if (options.type !== 'POST' && options.type !== 'PUT' &&
options.type !== 'PATCH') {
options.type = 'POST';
@@ -544,14 +617,35 @@
return this._enhancePromise(promise);
},
- // Adds convenience methods to the callback arguments:
+ // Adds convenience methods to the data callback argument:
_addConvenienceMethods: function (e, data) {
- var that = this;
+ var that = this,
+ getPromise = function (args) {
+ return $.Deferred().resolveWith(that, args).promise();
+ };
+ data.process = function (resolveFunc, rejectFunc) {
+ if (resolveFunc || rejectFunc) {
+ data._processQueue = this._processQueue =
+ (this._processQueue || getPromise([this])).pipe(
+ function () {
+ if (data.errorThrown) {
+ return $.Deferred()
+ .rejectWith(that, [data]).promise();
+ }
+ return getPromise(arguments);
+ }
+ ).pipe(resolveFunc, rejectFunc);
+ }
+ return this._processQueue || getPromise([this]);
+ };
data.submit = function () {
if (this.state() !== 'pending') {
data.jqXHR = this.jqXHR =
- (that._trigger('submit', e, this) !== false) &&
- that._onSend(e, this);
+ (that._trigger(
+ 'submit',
+ $.Event('submit', {delegatedEvent: e}),
+ this
+ ) !== false) && that._onSend(e, this);
}
return this.jqXHR || that._getXHRPromise();
};
@@ -559,12 +653,21 @@
if (this.jqXHR) {
return this.jqXHR.abort();
}
- return that._getXHRPromise();
+ this.errorThrown = 'abort';
+ that._trigger('fail', null, this);
+ return that._getXHRPromise(false);
};
data.state = function () {
if (this.jqXHR) {
return that._getDeferredState(this.jqXHR);
}
+ if (this._processQueue) {
+ return that._getDeferredState(this._processQueue);
+ }
+ };
+ data.processing = function () {
+ return !this.jqXHR && this._processQueue && that
+ ._getDeferredState(this._processQueue) === 'pending';
};
data.progress = function () {
return this._progress;
@@ -590,12 +693,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,
@@ -608,7 +712,7 @@
return true;
}
if (ub >= fs) {
- file.error = 'Uploaded bytes exceed file size';
+ file.error = options.i18n('uploadedBytes');
return this._getXHRPromise(
false,
options.context,
@@ -644,7 +748,7 @@
// Create a progress event if no final progress event
// with loaded equaling total has been triggered
// for this chunk:
- if (o._progress.loaded === currentLoaded) {
+ if (currentLoaded + o.chunkSize - o._progress.loaded) {
that._onProgress($.Event('progress', {
lengthComputable: true,
loaded: ub - o.uploadedBytes,
@@ -767,7 +871,11 @@
// Set timer for bitrate progress calculation:
options._bitrateTimer = new that._BitrateTimer();
jqXHR = jqXHR || (
- ((aborted || that._trigger('send', e, options) === false) &&
+ ((aborted || that._trigger(
+ 'send',
+ $.Event('send', {delegatedEvent: e}),
+ options
+ ) === false) &&
that._getXHRPromise(false, options.context, aborted)) ||
that._chunkedUpload(options) || $.ajax(options)
).done(function (result, textStatus, jqXHR) {
@@ -813,7 +921,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,
@@ -837,39 +946,70 @@
var that = this,
result = true,
options = $.extend({}, this.options, data),
+ files = data.files,
+ filesLength = files.length,
limit = options.limitMultiFileUploads,
+ limitSize = options.limitMultiFileUploadSize,
+ overhead = options.limitMultiFileUploadSizeOverhead,
+ batchSize = 0,
paramName = this._getParamName(options),
paramNameSet,
paramNameSlice,
fileSet,
- i;
- if (!(options.singleFileUploads || limit) ||
+ i,
+ j = 0;
+ if (limitSize && (!filesLength || files[0].size === undefined)) {
+ limitSize = undefined;
+ }
+ if (!(options.singleFileUploads || limit || limitSize) ||
!this._isXHRUpload(options)) {
- fileSet = [data.files];
+ fileSet = [files];
paramNameSet = [paramName];
- } else if (!options.singleFileUploads && limit) {
+ } else if (!(options.singleFileUploads || limitSize) && limit) {
fileSet = [];
paramNameSet = [];
- for (i = 0; i < data.files.length; i += limit) {
- fileSet.push(data.files.slice(i, i + limit));
+ for (i = 0; i < filesLength; i += limit) {
+ fileSet.push(files.slice(i, i + limit));
paramNameSlice = paramName.slice(i, i + limit);
if (!paramNameSlice.length) {
paramNameSlice = paramName;
}
paramNameSet.push(paramNameSlice);
}
+ } else if (!options.singleFileUploads && limitSize) {
+ fileSet = [];
+ paramNameSet = [];
+ for (i = 0; i < filesLength; i = i + 1) {
+ batchSize += files[i].size + overhead;
+ if (i + 1 === filesLength ||
+ ((batchSize + files[i + 1].size + overhead) > limitSize) ||
+ (limit && i + 1 - j >= limit)) {
+ fileSet.push(files.slice(j, i + 1));
+ paramNameSlice = paramName.slice(j, i + 1);
+ if (!paramNameSlice.length) {
+ paramNameSlice = paramName;
+ }
+ paramNameSet.push(paramNameSlice);
+ j = i + 1;
+ batchSize = 0;
+ }
+ }
} else {
paramNameSet = paramName;
}
- data.originalFiles = data.files;
- $.each(fileSet || data.files, function (index, element) {
+ data.originalFiles = files;
+ $.each(fileSet || files, function (index, element) {
var newData = $.extend({}, data);
newData.files = fileSet ? element : [element];
newData.paramName = paramNameSet[index];
that._initResponseObject(newData);
that._initProgressObject(newData);
that._addConvenienceMethods(e, newData);
- result = that._trigger('add', e, newData);
+ result = that._trigger(
+ 'add',
+ $.Event('add', {delegatedEvent: e}),
+ newData
+ );
return result;
});
return result;
@@ -1038,51 +1178,67 @@
if (that.options.replaceFileInput) {
that._replaceFileInput(data.fileInput);
}
- if (that._trigger('change', e, data) !== false) {
+ if (that._trigger(
+ 'change',
+ $.Event('change', {delegatedEvent: e}),
+ data
+ ) !== false) {
that._onAdd(e, data);
}
});
},
_onPaste: function (e) {
- var cbd = e.originalEvent.clipboardData,
- items = (cbd && cbd.items) || [],
+ var items = e.originalEvent && e.originalEvent.clipboardData &&
+ e.originalEvent.clipboardData.items,
data = {files: []};
- $.each(items, function (index, item) {
- var file = item.getAsFile && item.getAsFile();
- if (file) {
- data.files.push(file);
+ if (items && items.length) {
+ $.each(items, function (index, item) {
+ var file = item.getAsFile && item.getAsFile();
+ if (file) {
+ data.files.push(file);
+ }
+ });
+ if (this._trigger(
+ 'paste',
+ $.Event('paste', {delegatedEvent: e}),
+ data
+ ) !== false) {
+ this._onAdd(e, data);
}
- });
- if (this._trigger('paste', e, data) === false ||
- this._onAdd(e, data) === false) {
- return false;
}
},
_onDrop: function (e) {
+ e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
var that = this,
- dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer,
+ dataTransfer = e.dataTransfer,
data = {};
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
e.preventDefault();
+ this._getDroppedFiles(dataTransfer).always(function (files) {
+ data.files = files;
+ if (that._trigger(
+ 'drop',
+ $.Event('drop', {delegatedEvent: e}),
+ data
+ ) !== false) {
+ that._onAdd(e, data);
+ }
+ });
}
- this._getDroppedFiles(dataTransfer).always(function (files) {
- data.files = files;
- if (that._trigger('drop', e, data) !== false) {
- that._onAdd(e, data);
- }
- });
},
_onDragOver: function (e) {
- var dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer;
- if (this._trigger('dragover', e) === false) {
- return false;
- }
- if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1) {
- dataTransfer.dropEffect = 'copy';
+ e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
+ var dataTransfer = e.dataTransfer;
+ if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&
+ this._trigger(
+ 'dragover',
+ $.Event('dragover', {delegatedEvent: e})
+ ) !== false) {
e.preventDefault();
+ dataTransfer.dropEffect = 'copy';
}
},
@@ -1096,9 +1252,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 () {
@@ -1108,12 +1266,12 @@
},
_setOption: function (key, value) {
- var refresh = $.inArray(key, this._refreshOptionsList) !== -1;
- if (refresh) {
+ var reinit = $.inArray(key, this._specialOptions) !== -1;
+ if (reinit) {
this._destroyEventHandlers();
}
this._super(key, value);
- if (refresh) {
+ if (reinit) {
this._initSpecialOptions();
this._initEventHandlers();
}
@@ -1135,10 +1293,41 @@
}
},
- _create: function () {
- var options = this.options;
+ _getRegExp: function (str) {
+ var parts = str.split('/'),
+ modifiers = parts.pop();
+ parts.shift();
+ return new RegExp(parts.join('/'), modifiers);
+ },
+
+ _isRegExpOption: function (key, value) {
+ return key !== 'url' && $.type(value) === 'string' &&
+ /^\/.*\/[igm]{0,3}$/.test(value);
+ },
+
+ _initDataAttributes: function () {
+ var that = this,
+ options = this.options,
+ clone = $(this.element[0].cloneNode(false));
// Initialize options set via HTML5 data-attributes:
- $.extend(options, $(this.element[0].cloneNode(false)).data());
+ $.each(
+ clone.data(),
+ function (key, value) {
+ var dataAttributeName = 'data-' +
+ // Convert camelCase to hyphen-ated key:
+ key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
+ if (clone.attr(dataAttributeName)) {
+ if (that._isRegExpOption(key, value)) {
+ value = that._getRegExp(value);
+ }
+ options[key] = value;
+ }
+ }
+ );
+ },
+
+ _create: function () {
+ this._initDataAttributes();
this._initSpecialOptions();
this._slots = [];
this._sequence = this._getXHRPromise(true);
@@ -1207,6 +1396,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 ed25895..8d64b59 100644
--- 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.1
+ * jQuery Iframe Transport Plugin 1.8.2
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
@@ -9,8 +9,7 @@
* http://www.opensource.org/licenses/MIT
*/
-/*jslint unparam: true, nomen: true */
-/*global define, window, document */
+/* global define, window, document */
(function (factory) {
'use strict';
@@ -27,7 +26,7 @@
// Helper variable to create unique names for the transport iframes:
var counter = 0;
- // The iframe transport accepts three additional options:
+ // The iframe transport accepts four additional options:
// options.fileInput: a jQuery collection of file input fields
// options.paramName: the parameter name for the file form data,
// overrides the name property of the file input field(s),
@@ -35,9 +34,16 @@
// options.formData: an array of objects with name and value properties,
// equivalent to the return data of .serializeArray(), e.g.:
// [{name: 'a', value: 1}, {name: 'b', value: 2}]
+ // options.initialIframeSrc: the URL of the initial iframe src,
+ // by default set to "javascript:false;"
$.ajaxTransport('iframe', function (options) {
if (options.async) {
- var form,
+ // javascript:false as initial iframe src
+ // prevents warning popups on HTTPS in IE6:
+ /*jshint scripturl: true */
+ var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
+ /*jshint scripturl: false */
+ form,
iframe,
addParamChar;
return {
@@ -56,14 +62,13 @@
options.url = options.url + addParamChar + '_method=PATCH';
options.type = 'POST';
}
- // javascript:false as initial iframe src
- // prevents warning popups on HTTPS in IE6.
// IE versions below IE8 cannot set the name property of
// elements that have already been added to the DOM,
// so we set the name along with the iframe HTML markup:
+ counter += 1;
iframe = $(
- ''
+ ''
).bind('load', function () {
var fileInputClones,
paramNames = $.isArray(options.paramName) ?
@@ -94,9 +99,14 @@
);
// Fix for IE endless progress bar activity bug
// (happens on form submits to iframe targets):
- $('')
+ $('')
.appendTo(form);
- form.remove();
+ window.setTimeout(function () {
+ // Removing the form in a setTimeout call
+ // allows Chrome's developer tools to display
+ // the response result
+ form.remove();
+ }, 0);
});
form
.prop('target', iframe.prop('name'))
@@ -132,6 +142,8 @@
.prop('enctype', 'multipart/form-data')
// enctype must be set as encoding for IE:
.prop('encoding', 'multipart/form-data');
+ // Remove the HTML5 form attribute from the input(s):
+ options.fileInput.removeAttr('form');
}
form.submit();
// Insert the file input fields at their original location
@@ -139,7 +151,10 @@
if (fileInputClones && fileInputClones.length) {
options.fileInput.each(function (index, input) {
var clone = $(fileInputClones[index]);
- $(input).prop('name', clone.prop('name'));
+ // Restore the original name and form properties:
+ $(input)
+ .prop('name', clone.prop('name'))
+ .attr('form', clone.attr('form'));
clone.replaceWith(input);
});
}
@@ -153,7 +168,7 @@
// concat is used to avoid the "Script URL" JSLint error:
iframe
.unbind('load')
- .prop('src', 'javascript'.concat(':false;'));
+ .prop('src', initialIframeSrc);
}
if (form) {
form.remove();
@@ -164,7 +179,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) {
@@ -176,6 +199,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/vendor/jquery.ui.widget.js b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js
index fd2948f..c430419 100644
--- a/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js
+++ b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js
@@ -1,8 +1,8 @@
-/*
- * jQuery UI Widget 1.10.1+amd
+/*!
+ * jQuery UI Widget 1.10.4+amd
* https://github.com/blueimp/jQuery-File-Upload
*
- * Copyright 2013 jQuery Foundation and other contributors
+ * Copyright 2014 jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*
@@ -115,7 +115,7 @@ $.widget = function( name, base, prototype ) {
// TODO: remove support for widgetEventPrefix
// always use the name + a colon as the prefix, e.g., draggable:start
// don't prefix for widgets that aren't DOM-based
- widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
+ widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
}, proxiedPrototype, {
constructor: constructor,
namespace: namespace,
@@ -324,12 +324,12 @@ $.Widget.prototype = {
curOption = curOption[ parts[ i ] ];
}
key = parts.pop();
- if ( value === undefined ) {
+ if ( arguments.length === 1 ) {
return curOption[ key ] === undefined ? null : curOption[ key ];
}
curOption[ key ] = value;
} else {
- if ( value === undefined ) {
+ if ( arguments.length === 1 ) {
return this.options[ key ] === undefined ? null : this.options[ key ];
}
options[ key ] = value;
diff --git a/vendor/assets/stylesheets/jquery.fileupload-ui.scss b/vendor/assets/stylesheets/jquery.fileupload-ui.scss
index 58a7315..c4ee8cf 100644
--- a/vendor/assets/stylesheets/jquery.fileupload-ui.scss
+++ b/vendor/assets/stylesheets/jquery.fileupload-ui.scss
@@ -1,6 +1,6 @@
-@charset 'UTF-8';
+@charset "UTF-8";
/*
- * jQuery File Upload UI Plugin CSS 6.3
+ * jQuery File Upload UI Plugin CSS 9.0.0
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
@@ -10,75 +10,48 @@
* http://www.opensource.org/licenses/MIT
*/
-.fileinput-button {
- position: relative;
- overflow: hidden;
- float: left;
- margin-right: 4px;
-}
-.fileinput-button input {
- position: absolute;
- top: 0;
- right: 0;
- margin: 0;
- border: solid transparent;
- border-width: 0 0 100px 200px;
- opacity: 0;
- filter: alpha(opacity=0);
- -moz-transform: translate(-300px, 0) scale(4);
- direction: ltr;
- cursor: pointer;
-}
.fileupload-buttonbar .btn,
.fileupload-buttonbar .toggle {
margin-bottom: 5px;
}
-.files .progress {
- width: 200px;
-}
+.progress-animated .progress-bar,
.progress-animated .bar {
- background: image-url('progressbar.gif') !important;
+ background: url("progressbar.gif") !important;
filter: none;
}
-.fileupload-loading {
- position: absolute;
- left: 50%;
- width: 128px;
- height: 128px;
- background: image-url('loading.gif') center no-repeat;
+.fileupload-process {
+ float: right;
display: none;
}
-.fileupload-processing .fileupload-loading {
+.fileupload-processing .fileupload-process,
+.files .processing .preview {
display: block;
+ width: 32px;
+ height: 32px;
+ background: url("loading.gif") center no-repeat;
+ background-size: contain;
}
-
-/* Fix for IE 6: */
-* html .fileinput-button {
- line-height: 22px;
- margin: 1px -3px 0 0;
+.files audio,
+.files video {
+ max-width: 300px;
}
-/* Fix for IE 7: */
-* + html .fileinput-button {
- margin: 1px 0 0 0;
-}
-
-@media (max-width: 480px) {
+@media (max-width: 767px) {
+ .fileupload-buttonbar .toggle,
+ .files .toggle,
.files .btn span {
display: none;
}
- .files .preview * {
- width: 40px;
- }
- .files .name * {
+ .files .name {
width: 80px;
- display: inline-block;
word-wrap: break-word;
}
- .files .progress {
- width: 20px;
+ .files audio,
+ .files video {
+ max-width: 80px;
}
- .files .delete {
- width: 60px;
+ .files img,
+ .files canvas {
+ max-width: 100%;
}
}
From 2dc1a7270f6ebf89a34981eea926dffb8d213363 Mon Sep 17 00:00:00 2001
From: Ciprian Florescu
Date: Sun, 23 Feb 2014 15:43:06 +0000
Subject: [PATCH 2/2] Use Exif - include all load-image features
---
lib/jquery/fileupload/rails/version.rb | 2 +-
.../javascripts/jquery-fileupload/index.js | 2 +
.../jquery.fileupload-image.js | 2 +-
.../jquery-fileupload/vendor/load-image.js | 229 +-----------------
4 files changed, 5 insertions(+), 230 deletions(-)
diff --git a/lib/jquery/fileupload/rails/version.rb b/lib/jquery/fileupload/rails/version.rb
index e325029..532d712 100644
--- a/lib/jquery/fileupload/rails/version.rb
+++ b/lib/jquery/fileupload/rails/version.rb
@@ -1,7 +1,7 @@
module JQuery
module FileUpload
module Rails
- VERSION = "0.4.2"
+ VERSION = "0.4.3"
end
end
end
diff --git a/vendor/assets/javascripts/jquery-fileupload/index.js b/vendor/assets/javascripts/jquery-fileupload/index.js
index 569a8d5..92bc4f1 100644
--- a/vendor/assets/javascripts/jquery-fileupload/index.js
+++ b/vendor/assets/javascripts/jquery-fileupload/index.js
@@ -1,5 +1,7 @@
//= require jquery-fileupload/vendor/jquery.ui.widget
//= require jquery-fileupload/vendor/load-image
+//= require jquery-fileupload/vendor/canvas-to-blob
+//= require jquery-fileupload/vendor/tmpl
//= require jquery-fileupload/jquery.iframe-transport
//= require jquery-fileupload/jquery.fileupload
//= require jquery-fileupload/jquery.fileupload-process
diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js
index f73c24e..9a46565 100644
--- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js
+++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js
@@ -259,7 +259,7 @@
}
var that = this,
dfd = $.Deferred();
- loadImage(data.files[data.index], function (result) {
+ loadImage.parseMetaData(data.files[data.index], function (result) {
$.extend(data, result);
dfd.resolveWith(that, [data]);
}, options);
diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js
index 0155d38..09f3873 100644
--- a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js
+++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js
@@ -1,228 +1 @@
-/*
- * JavaScript Load Image 1.3.1
- * https://github.com/blueimp/JavaScript-Load-Image
- *
- * Copyright 2011, Sebastian Tschan
- * https://blueimp.net
- *
- * iOS image scaling fixes based on
- * https://github.com/stomita/ios-imagefile-megapixel
- *
- * Licensed under the MIT license:
- * http://www.opensource.org/licenses/MIT
- */
-
-/*jslint nomen: true, bitwise: true */
-/*global window, document, URL, webkitURL, Blob, File, FileReader, define */
-
-(function ($) {
- 'use strict';
-
- // Loads an image for a given File object.
- // Invokes the callback with an img or optional canvas
- // element (if supported by the browser) as parameter:
- var loadImage = function (file, callback, options) {
- var img = document.createElement('img'),
- url,
- oUrl;
- img.onerror = callback;
- img.onload = function () {
- if (oUrl && !(options && options.noRevoke)) {
- loadImage.revokeObjectURL(oUrl);
- }
- callback(loadImage.scale(img, options));
- };
- if ((window.Blob && file instanceof Blob) ||
- // Files are also Blob instances, but some browsers
- // (Firefox 3.6) support the File API but not Blobs:
- (window.File && file instanceof File)) {
- url = oUrl = loadImage.createObjectURL(file);
- // Store the file type for resize processing:
- img._type = file.type;
- } else {
- url = file;
- }
- if (url) {
- img.src = url;
- return img;
- }
- return loadImage.readFile(file, function (e) {
- var target = e.target;
- if (target && target.result) {
- img.src = target.result;
- } else {
- callback(e);
- }
- });
- },
- // The check for URL.revokeObjectURL fixes an issue with Opera 12,
- // which provides URL.createObjectURL but doesn't properly implement it:
- urlAPI = (window.createObjectURL && window) ||
- (window.URL && URL.revokeObjectURL && URL) ||
- (window.webkitURL && webkitURL);
-
- // Detects subsampling in JPEG images:
- loadImage.detectSubsampling = function (img) {
- var iw = img.width,
- ih = img.height,
- canvas,
- ctx;
- if (iw * ih > 1024 * 1024) { // only consider mexapixel images
- canvas = document.createElement('canvas');
- canvas.width = canvas.height = 1;
- ctx = canvas.getContext('2d');
- ctx.drawImage(img, -iw + 1, 0);
- // subsampled image becomes half smaller in rendering size.
- // check alpha channel value to confirm image is covering edge pixel or not.
- // if alpha value is 0 image is not covering, hence subsampled.
- return ctx.getImageData(0, 0, 1, 1).data[3] === 0;
- }
- return false;
- };
-
- // Detects vertical squash in JPEG images:
- loadImage.detectVerticalSquash = function (img, ih) {
- var canvas = document.createElement('canvas'),
- ctx = canvas.getContext('2d'),
- data,
- sy,
- ey,
- py,
- alpha;
- canvas.width = 1;
- canvas.height = ih;
- ctx.drawImage(img, 0, 0);
- data = ctx.getImageData(0, 0, 1, ih).data;
- // search image edge pixel position in case it is squashed vertically:
- sy = 0;
- ey = ih;
- py = ih;
- while (py > sy) {
- alpha = data[(py - 1) * 4 + 3];
- if (alpha === 0) {
- ey = py;
- } else {
- sy = py;
- }
- py = (ey + sy) >> 1;
- }
- return (py / ih) || 1;
- };
-
- // Renders image to canvas while working around iOS image scaling bugs:
- // https://github.com/blueimp/JavaScript-Load-Image/issues/13
- loadImage.renderImageToCanvas = function (img, canvas, width, height) {
- var iw = img.width,
- ih = img.height,
- ctx = canvas.getContext('2d'),
- vertSquashRatio,
- d = 1024, // size of tiling canvas
- tmpCanvas = document.createElement('canvas'),
- tmpCtx,
- dw,
- dh,
- dx,
- dy,
- sx,
- sy;
- ctx.save();
- if (loadImage.detectSubsampling(img)) {
- iw /= 2;
- ih /= 2;
- }
- vertSquashRatio = loadImage.detectVerticalSquash(img, ih);
- tmpCanvas.width = tmpCanvas.height = d;
- tmpCtx = tmpCanvas.getContext('2d');
- dw = Math.ceil(d * width / iw);
- dh = Math.ceil(d * height / ih / vertSquashRatio);
- dy = 0;
- sy = 0;
- while (sy < ih) {
- dx = 0;
- sx = 0;
- while (sx < iw) {
- tmpCtx.clearRect(0, 0, d, d);
- tmpCtx.drawImage(img, -sx, -sy);
- ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh);
- sx += d;
- dx += dw;
- }
- sy += d;
- dy += dh;
- }
- ctx.restore();
- tmpCanvas = tmpCtx = null;
- };
-
- // Scales the given image (img or canvas HTML element)
- // using the given options.
- // Returns a canvas object if the browser supports canvas
- // and the canvas option is true or a canvas object is passed
- // as image, else the scaled image:
- loadImage.scale = function (img, options) {
- options = options || {};
- var canvas = document.createElement('canvas'),
- width = img.width,
- height = img.height,
- scale = Math.max(
- (options.minWidth || width) / width,
- (options.minHeight || height) / height
- );
- if (scale > 1) {
- width = Math.ceil(width * scale);
- height = Math.ceil(height * scale);
- }
- scale = Math.min(
- (options.maxWidth || width) / width,
- (options.maxHeight || height) / height
- );
- if (scale < 1) {
- width = Math.ceil(width * scale);
- height = Math.ceil(height * scale);
- }
- if (img.getContext || (options.canvas && canvas.getContext)) {
- canvas.width = width;
- canvas.height = height;
- if (img._type === 'image/jpeg') {
- loadImage
- .renderImageToCanvas(img, canvas, width, height);
- } else {
- canvas.getContext('2d')
- .drawImage(img, 0, 0, width, height);
- }
- return canvas;
- }
- img.width = width;
- img.height = height;
- return img;
- };
-
- loadImage.createObjectURL = function (file) {
- return urlAPI ? urlAPI.createObjectURL(file) : false;
- };
-
- loadImage.revokeObjectURL = function (url) {
- return urlAPI ? urlAPI.revokeObjectURL(url) : false;
- };
-
- // Loads a given File object via FileReader interface,
- // invokes the callback with the event object (load or error).
- // The result can be read via event.target.result:
- loadImage.readFile = function (file, callback) {
- if (window.FileReader && FileReader.prototype.readAsDataURL) {
- var fileReader = new FileReader();
- fileReader.onload = fileReader.onerror = callback;
- fileReader.readAsDataURL(file);
- return fileReader;
- }
- return false;
- };
-
- if (typeof define === 'function' && define.amd) {
- define(function () {
- return loadImage;
- });
- } else {
- $.loadImage = loadImage;
- }
-}(this));
+!function(a){"use strict";var b=function(a,c,d){var e,f,g=document.createElement("img");if(g.onerror=c,g.onload=function(){!f||d&&d.noRevoke||b.revokeObjectURL(f),c&&c(b.scale(g,d))},b.isInstanceOf("Blob",a)||b.isInstanceOf("File",a))e=f=b.createObjectURL(a),g._type=a.type;else{if("string"!=typeof a)return!1;e=a,d&&d.crossOrigin&&(g.crossOrigin=d.crossOrigin)}return e?(g.src=e,g):b.readFile(a,function(a){var b=a.target;b&&b.result?g.src=b.result:c&&c(a)})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.isInstanceOf=function(a,b){return Object.prototype.toString.call(b)==="[object "+a+"]"},b.transformCoordinates=function(){},b.getTransformedOptions=function(a){return a},b.renderImageToCanvas=function(a,b,c,d,e,f,g,h,i,j){return a.getContext("2d").drawImage(b,c,d,e,f,g,h,i,j),a},b.hasCanvasOption=function(a){return a.canvas||a.crop},b.scale=function(a,c){c=c||{};var d,e,f,g,h,i,j,k,l,m=document.createElement("canvas"),n=a.getContext||b.hasCanvasOption(c)&&m.getContext,o=a.naturalWidth||a.width,p=a.naturalHeight||a.height,q=o,r=p,s=function(){var a=Math.max((f||q)/q,(g||r)/r);a>1&&(q=Math.ceil(q*a),r=Math.ceil(r*a))},t=function(){var a=Math.min((d||q)/q,(e||r)/r);1>a&&(q=Math.ceil(q*a),r=Math.ceil(r*a))};return n&&(c=b.getTransformedOptions(c),j=c.left||0,k=c.top||0,c.sourceWidth?(h=c.sourceWidth,void 0!==c.right&&void 0===c.left&&(j=o-h-c.right)):h=o-j-(c.right||0),c.sourceHeight?(i=c.sourceHeight,void 0!==c.bottom&&void 0===c.top&&(k=p-i-c.bottom)):i=p-k-(c.bottom||0),q=h,r=i),d=c.maxWidth,e=c.maxHeight,f=c.minWidth,g=c.minHeight,n&&d&&e&&c.crop?(q=d,r=e,l=h/i-d/e,0>l?(i=e*h/d,void 0===c.top&&void 0===c.bottom&&(k=(p-i)/2)):l>0&&(h=d*i/e,void 0===c.left&&void 0===c.right&&(j=(o-h)/2))):((c.contain||c.cover)&&(f=d=d||f,g=e=e||g),c.cover?(t(),s()):(s(),t())),n?(m.width=q,m.height=r,b.transformCoordinates(m,c),b.renderImageToCanvas(m,a,j,k,h,i,0,0,q,r)):(a.width=q,a.height=r,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b,c){if(window.FileReader){var d=new FileReader;if(d.onload=d.onerror=b,c=c||"readAsDataURL",d[c])return d[c](a),d}return!1},"function"==typeof define&&define.amd?define(function(){return b}):a.loadImage=b}(this),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image"],a):a(window.loadImage)}(function(a){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var b=a.renderImageToCanvas;a.detectSubsampling=function(a){var b,c;return a.width*a.height>1048576?(b=document.createElement("canvas"),b.width=b.height=1,c=b.getContext("2d"),c.drawImage(a,-a.width+1,0),0===c.getImageData(0,0,1,1).data[3]):!1},a.detectVerticalSquash=function(a,b){var c,d,e,f,g,h=a.naturalHeight||a.height,i=document.createElement("canvas"),j=i.getContext("2d");for(b&&(h/=2),i.width=1,i.height=h,j.drawImage(a,0,0),c=j.getImageData(0,0,1,h).data,d=0,e=h,f=h;f>d;)g=c[4*(f-1)+3],0===g?e=f:d=f,f=e+d>>1;return f/h||1},a.renderImageToCanvas=function(c,d,e,f,g,h,i,j,k,l){if("image/jpeg"===d._type){var m,n,o,p,q=c.getContext("2d"),r=document.createElement("canvas"),s=1024,t=r.getContext("2d");if(r.width=s,r.height=s,q.save(),m=a.detectSubsampling(d),m&&(e/=2,f/=2,g/=2,h/=2),n=a.detectVerticalSquash(d,m),m||1!==n){for(f*=n,k=Math.ceil(s*k/g),l=Math.ceil(s*l/h/n),j=0,p=0;h>p;){for(i=0,o=0;g>o;)t.clearRect(0,0,s,s),t.drawImage(d,e,f,g,h,-o,-p,g,h),q.drawImage(r,0,0,s,s,i,j,k,l),o+=s,i+=k;p+=s,j+=l}return q.restore(),c}}return b(c,d,e,f,g,h,i,j,k,l)}}}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image"],a):a(window.loadImage)}(function(a){"use strict";var b=a.hasCanvasOption;a.hasCanvasOption=function(a){return b(a)||a.orientation},a.transformCoordinates=function(a,b){var c=a.getContext("2d"),d=a.width,e=a.height,f=b.orientation;if(f)switch(f>4&&(a.width=e,a.height=d),f){case 2:c.translate(d,0),c.scale(-1,1);break;case 3:c.translate(d,e),c.rotate(Math.PI);break;case 4:c.translate(0,e),c.scale(1,-1);break;case 5:c.rotate(.5*Math.PI),c.scale(1,-1);break;case 6:c.rotate(.5*Math.PI),c.translate(0,-e);break;case 7:c.rotate(.5*Math.PI),c.translate(d,-e),c.scale(-1,1);break;case 8:c.rotate(-.5*Math.PI),c.translate(-d,0)}},a.getTransformedOptions=function(a){if(!a.orientation||1===a.orientation)return a;var b,c={};for(b in a)a.hasOwnProperty(b)&&(c[b]=a[b]);switch(a.orientation){case 2:c.left=a.right,c.right=a.left;break;case 3:c.left=a.right,c.top=a.bottom,c.right=a.left,c.bottom=a.top;break;case 4:c.top=a.bottom,c.bottom=a.top;break;case 5:c.left=a.top,c.top=a.left,c.right=a.bottom,c.bottom=a.right;break;case 6:c.left=a.top,c.top=a.right,c.right=a.bottom,c.bottom=a.left;break;case 7:c.left=a.bottom,c.top=a.right,c.right=a.top,c.bottom=a.left;break;case 8:c.left=a.bottom,c.top=a.left,c.right=a.top,c.bottom=a.right}return a.orientation>4&&(c.maxWidth=a.maxHeight,c.maxHeight=a.maxWidth,c.minWidth=a.minHeight,c.minHeight=a.minWidth,c.sourceWidth=a.sourceHeight,c.sourceHeight=a.sourceWidth),c}}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image"],a):a(window.loadImage)}(function(a){"use strict";var b=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);a.blobSlice=b&&function(){var a=this.slice||this.webkitSlice||this.mozSlice;return a.apply(this,arguments)},a.metaDataParsers={jpeg:{65505:[]}},a.parseMetaData=function(b,c,d){d=d||{};var e=this,f=d.maxMetaDataSize||262144,g={},h=!(window.DataView&&b&&b.size>=12&&"image/jpeg"===b.type&&a.blobSlice);(h||!a.readFile(a.blobSlice.call(b,0,f),function(b){if(b.target.error)return console.log(b.target.error),c(g),void 0;var f,h,i,j,k=b.target.result,l=new DataView(k),m=2,n=l.byteLength-4,o=m;if(65496===l.getUint16(0)){for(;n>m&&(f=l.getUint16(m),f>=65504&&65519>=f||65534===f);){if(h=l.getUint16(m+2)+2,m+h>l.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(i=a.metaDataParsers.jpeg[f])for(j=0;j6&&(g.imageHead=k.slice?k.slice(0,o):new Uint8Array(k).subarray(0,o))}else console.log("Invalid JPEG file: Missing JPEG marker.");c(g)},"readAsArrayBuffer"))&&c(g)}}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],a):a(window.loadImage)}(function(a){"use strict";a.ExifMap=function(){return this},a.ExifMap.prototype.map={Orientation:274},a.ExifMap.prototype.get=function(a){return this[a]||this[this.map[a]]},a.getExifThumbnail=function(a,b,c){var d,e,f;if(!c||b+c>a.byteLength)return console.log("Invalid Exif data: Invalid thumbnail data."),void 0;for(d=[],e=0;c>e;e+=1)f=a.getUint8(b+e),d.push((16>f?"0":"")+f.toString(16));return"data:image/jpeg,%"+d.join("%")},a.exifTagTypes={1:{getValue:function(a,b){return a.getUint8(b)},size:1},2:{getValue:function(a,b){return String.fromCharCode(a.getUint8(b))},size:1,ascii:!0},3:{getValue:function(a,b,c){return a.getUint16(b,c)},size:2},4:{getValue:function(a,b,c){return a.getUint32(b,c)},size:4},5:{getValue:function(a,b,c){return a.getUint32(b,c)/a.getUint32(b+4,c)},size:8},9:{getValue:function(a,b,c){return a.getInt32(b,c)},size:4},10:{getValue:function(a,b,c){return a.getInt32(b,c)/a.getInt32(b+4,c)},size:8}},a.exifTagTypes[7]=a.exifTagTypes[1],a.getExifValue=function(b,c,d,e,f,g){var h,i,j,k,l,m,n=a.exifTagTypes[e];if(!n)return console.log("Invalid Exif data: Invalid tag type."),void 0;if(h=n.size*f,i=h>4?c+b.getUint32(d+8,g):d+8,i+h>b.byteLength)return console.log("Invalid Exif data: Invalid data offset."),void 0;if(1===f)return n.getValue(b,i,g);for(j=[],k=0;f>k;k+=1)j[k]=n.getValue(b,i+k*n.size,g);if(n.ascii){for(l="",k=0;ka.byteLength)return console.log("Invalid Exif data: Invalid directory offset."),void 0;if(f=a.getUint16(c,d),g=c+2+12*f,g+4>a.byteLength)return console.log("Invalid Exif data: Invalid directory size."),void 0;for(h=0;f>h;h+=1)this.parseExifTag(a,b,c+2+12*h,d,e);return a.getUint32(g,d)},a.parseExifData=function(b,c,d,e,f){if(!f.disableExif){var g,h,i,j=c+10;if(1165519206===b.getUint32(c+4)){if(j+8>b.byteLength)return console.log("Invalid Exif data: Invalid segment size."),void 0;if(0!==b.getUint16(c+8))return console.log("Invalid Exif data: Missing byte alignment offset."),void 0;switch(b.getUint16(j)){case 18761:g=!0;break;case 19789:g=!1;break;default:return console.log("Invalid Exif data: Invalid byte alignment marker."),void 0}if(42!==b.getUint16(j+2,g))return console.log("Invalid Exif data: Missing TIFF marker."),void 0;h=b.getUint32(j+4,g),e.exif=new a.ExifMap,h=a.parseExifTags(b,j,j+h,g,e),h&&!f.disableExifThumbnail&&(i={exif:{}},h=a.parseExifTags(b,j,j+h,g,i),i.exif[513]&&(e.exif.Thumbnail=a.getExifThumbnail(b,j+i.exif[513],i.exif[514]))),e.exif[34665]&&!f.disableExifSub&&a.parseExifTags(b,j,j+e.exif[34665],g,e),e.exif[34853]&&!f.disableExifGps&&a.parseExifTags(b,j,j+e.exif[34853],g,e)}}},a.metaDataParsers.jpeg[65505].push(a.parseExifData)}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],a):a(window.loadImage)}(function(a){"use strict";a.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",42240:"Gamma",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubSecTime",37521:"SubSecTimeOriginal",37522:"SubSecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"PhotographicSensitivity",34856:"OECF",34864:"SensitivityType",34865:"StandardOutputSensitivity",34866:"RecommendedExposureIndex",34867:"ISOSpeed",34868:"ISOSpeedLatitudeyyy",34869:"ISOSpeedLatitudezzz",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRatio",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",42032:"CameraOwnerName",42033:"BodySerialNumber",42034:"LensSpecification",42035:"LensMake",42036:"LensModel",42037:"LensSerialNumber",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential",31:"GPSHPositioningError"},a.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},a.ExifMap.prototype.getText=function(a){var b=this.get(a);switch(a){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[a][b];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(b[0],b[1],b[2],b[3]);case"ComponentsConfiguration":return this.stringValues[a][b[0]]+this.stringValues[a][b[1]]+this.stringValues[a][b[2]]+this.stringValues[a][b[3]];case"GPSVersionID":return b[0]+"."+b[1]+"."+b[2]+"."+b[3]}return String(b)},function(a){var b,c=a.tags,d=a.map;for(b in c)c.hasOwnProperty(b)&&(d[c[b]]=b)}(a.ExifMap.prototype),a.ExifMap.prototype.getAll=function(){var a,b,c={};for(a in this)this.hasOwnProperty(a)&&(b=this.tags[a],b&&(c[b]=this.getText(b)));return c}});
\ No newline at end of file