diff --git a/.gitignore b/.gitignore index 4040c6c..0bdef21 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.DS_Store *.gem .bundle Gemfile.lock diff --git a/Gemfile b/Gemfile old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 4207f35..9d6e596 --- a/README.md +++ b/README.md @@ -1,18 +1,17 @@ -# jQuery File Upload for Rails +# jQuery File Upload for Rails (updated at Feb'2016) [jQuery-File-Plugin](https://github.com/blueimp/jQuery-File-Upload) is a file upload plugin written by [Sebastian Tschan](https://github.com/blueimp). jQuery File Upload features multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. -jquery-fileupload-rails is a library that integrates jQuery File Upload for Rails 3.1 Asset Pipeline (Rails 3.2 supported). +jquery-fileupload-rails is a library that integrates jQuery File Upload for Rails 3.1> Asset Pipeline (Rails 3.2 and 4.0 supported). ## Plugin versions -* jQuery File Upload User Interface Plugin 6.11 -* jQuery File Upload Plugin 5.19.3 -* jQuery UI Widget 1.9.1+amd +* jQuery File Upload 9.12.1 +* Jcrop v0.9.12 (optional) ## Installing Gem - gem "jquery-fileupload-rails" + gem "jquery-fileupload-rails", :github => 'addagger/jquery-fileupload-rails' ## Using the javascripts @@ -23,15 +22,28 @@ Require jquery-fileupload in your app/assets/application.js file. The snippet above will add the following js files to the mainfest file. //= 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/vendor/tmpl.min + //= require jquery-fileupload/vendor/load-image.min + //= require jquery-fileupload/vendor/load-image-ios + //= require jquery-fileupload/vendor/load-image-orientation + //= require jquery-fileupload/vendor/load-image-meta + //= require jquery-fileupload/vendor/load-image-exif + //= require jquery-fileupload/vendor/load-image-exif-map + //= require jquery-fileupload/vendor/canvas-to-blob.min //= require jquery-fileupload/jquery.iframe-transport //= require jquery-fileupload/jquery.fileupload - //= require jquery-fileupload/jquery.fileupload-fp + //= require jquery-fileupload/jquery.fileupload-process + //= require jquery-fileupload/jquery.fileupload-image + //= require jquery-fileupload/jquery.fileupload-audio + //= require jquery-fileupload/jquery.fileupload-video + //= require jquery-fileupload/jquery.fileupload-validate //= require jquery-fileupload/jquery.fileupload-ui //= require jquery-fileupload/locale +To add [Jcrop](https://github.com/tapmodo/Jcrop) scripts: + + //= require jquery-fileupload/vendor/Jcrop.min + If you only need the basic files, just add the code below to your application.js file. [Basic setup guide](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin) //= require jquery-fileupload/basic @@ -48,14 +60,18 @@ Require the stylesheet file to app/assets/stylesheets/application.css *= require jquery.fileupload-ui +[Jcrop](https://github.com/tapmodo/Jcrop) stylesheet + + *= require vendor/Jcrop.min + ## Using the middleware The `jquery.iframe-transport` fallback transport has some special caveats regarding the response data type, http status, and character encodings. `jquery-fileupload-rails` includes a middleware that handles these inconsistencies seamlessly. If you decide to use it, create an initializer that adds the middleware to your application's middleware stack. Rails.application.config.middleware.use JQuery::FileUpload::Rails::Middleware -## [Example app](https://github.com/tors/jquery-fileupload-rails-paperclip-example) -This app uses paperclip and twitter-bootstrap-rails +## [Example app](https://github.com/addagger/jquery-fileupload-rails-example) +This app uses paperclip and [anjlab-bootstrap-rails](https://github.com/anjlab/bootstrap-rails) You can also check out Ryan Bate's RailsCast [jQuery File Upload episode](http://railscasts.com/episodes/381-jquery-file-upload). You will need a pro account to watch it though. diff --git a/Rakefile b/Rakefile old mode 100644 new mode 100755 diff --git a/jquery-fileupload-rails.gemspec b/jquery-fileupload-rails.gemspec old mode 100644 new mode 100755 index 78b5549..264a35e --- a/jquery-fileupload-rails.gemspec +++ b/jquery-fileupload-rails.gemspec @@ -8,8 +8,8 @@ Gem::Specification.new do |s| s.authors = ["Tors Dalid"] s.email = ["cletedalid@gmail.com"] s.homepage = "https://github.com/tors/jquery-fileupload-rails" - s.summary = %q{jQuery File Upload for Rails 3.1 Asset Pipeline} - s.description = %q{jQuery File Upload by Sebastian Tschan integrated for Rails 3.1 Asset Pipeline} + s.summary = %q{jQuery File Upload for Rails Asset Pipeline} + s.description = %q{jQuery File Upload by Sebastian Tschan integrated for Rails Asset Pipeline} s.rubyforge_project = "jquery-fileupload-rails" diff --git a/lib/jquery-fileupload-rails.rb b/lib/jquery-fileupload-rails.rb old mode 100644 new mode 100755 diff --git a/lib/jquery/fileupload/rails/engine.rb b/lib/jquery/fileupload/rails/engine.rb old mode 100644 new mode 100755 index b7791d9..2a5395d --- a/lib/jquery/fileupload/rails/engine.rb +++ b/lib/jquery/fileupload/rails/engine.rb @@ -2,6 +2,7 @@ module JQuery module FileUpload module Rails class Engine < ::Rails::Engine + config.assets.precompile += %w( progressbar.gif loading.gif Jcrop.gif ) end end end diff --git a/lib/jquery/fileupload/rails/middleware.rb b/lib/jquery/fileupload/rails/middleware.rb old mode 100644 new mode 100755 diff --git a/lib/jquery/fileupload/rails/upload.rb b/lib/jquery/fileupload/rails/upload.rb old mode 100644 new mode 100755 diff --git a/lib/jquery/fileupload/rails/version.rb b/lib/jquery/fileupload/rails/version.rb old mode 100644 new mode 100755 index 10fbdc9..ef101d0 --- 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 = "2.0.0" end end end diff --git a/public/cors/postmessage.html b/public/cors/postmessage.html new file mode 100755 index 0000000..fab9d60 --- /dev/null +++ b/public/cors/postmessage.html @@ -0,0 +1,75 @@ + + + + + +jQuery File Upload Plugin postMessage API + + + + + + diff --git a/public/cors/result.html b/public/cors/result.html new file mode 100755 index 0000000..c5f30f9 --- /dev/null +++ b/public/cors/result.html @@ -0,0 +1,24 @@ + + + + + +jQuery Iframe Transport Plugin Redirect Page + + + + + diff --git a/vendor/assets/images/Jcrop.gif b/vendor/assets/images/Jcrop.gif new file mode 100755 index 0000000..72ea7cc Binary files /dev/null and b/vendor/assets/images/Jcrop.gif differ diff --git a/vendor/assets/javascripts/jquery-fileupload/basic.js b/vendor/assets/javascripts/jquery-fileupload/basic.js old mode 100644 new mode 100755 index fa302cc..25d887a --- a/vendor/assets/javascripts/jquery-fileupload/basic.js +++ b/vendor/assets/javascripts/jquery-fileupload/basic.js @@ -1,4 +1,5 @@ -//=require jquery-fileupload/vendor/jquery.ui.widget -//=require jquery-fileupload/jquery.iframe-transport -//=require jquery-fileupload/jquery.fileupload +//= require jquery-fileupload/vendor/jquery.ui.widget +//= require jquery-fileupload/jquery.iframe-transport +//= require jquery-fileupload/jquery.fileupload +//= require jquery-fileupload/locale 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..4874a8c 100755 --- a/vendor/assets/javascripts/jquery-fileupload/cors/jquery.postmessage-transport.js +++ b/vendor/assets/javascripts/jquery-fileupload/cors/jquery.postmessage-transport.js @@ -1,5 +1,5 @@ /* - * jQuery postMessage Transport Plugin 1.1 + * jQuery postMessage Transport Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan @@ -9,14 +9,16 @@ * http://www.opensource.org/licenses/MIT */ -/*jslint unparam: true, nomen: true */ -/*global define, window, document */ +/* global define, require, window, document */ (function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory(require('jquery')); } else { // Browser globals: factory(window.jQuery); @@ -64,8 +66,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..5b9c6ca 100755 --- a/vendor/assets/javascripts/jquery-fileupload/cors/jquery.xdr-transport.js +++ b/vendor/assets/javascripts/jquery-fileupload/cors/jquery.xdr-transport.js @@ -1,5 +1,5 @@ /* - * jQuery XDomainRequest Transport Plugin 1.1.3 + * jQuery XDomainRequest Transport Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan @@ -12,14 +12,16 @@ * https://github.com/jaubourg/ajaxHooks/ */ -/*jslint unparam: true */ -/*global define, window, XDomainRequest */ +/* global define, require, window, XDomainRequest */ (function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory(require('jquery')); } else { // Browser globals: factory(window.jQuery); diff --git a/vendor/assets/javascripts/jquery-fileupload/index.js b/vendor/assets/javascripts/jquery-fileupload/index.js old mode 100644 new mode 100755 index 0cda385..b6badd6 --- a/vendor/assets/javascripts/jquery-fileupload/index.js +++ b/vendor/assets/javascripts/jquery-fileupload/index.js @@ -1,9 +1,13 @@ -//=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/tmpl.min +//= require jquery-fileupload/vendor/load-image.all.min +//= require jquery-fileupload/vendor/canvas-to-blob.min +//= require jquery-fileupload/jquery.iframe-transport +//= require jquery-fileupload/jquery.fileupload +//= require jquery-fileupload/jquery.fileupload-process +//= require jquery-fileupload/jquery.fileupload-image +//= require jquery-fileupload/jquery.fileupload-audio +//= require jquery-fileupload/jquery.fileupload-video +//= require jquery-fileupload/jquery.fileupload-validate +//= require jquery-fileupload/jquery.fileupload-ui +//= require jquery-fileupload/locale \ No newline at end of file diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js index e7ba784..f7ba07b 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-angular.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload AngularJS Plugin 1.0.1 + * jQuery File Upload AngularJS Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan @@ -9,28 +9,73 @@ * http://www.opensource.org/licenses/MIT */ -/*jslint nomen: true, unparam: true */ -/*global angular */ +/* jshint nomen:false */ +/* global define, angular */ -(function () { +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'angular', + './jquery.fileupload-image', + './jquery.fileupload-audio', + './jquery.fileupload-video', + './jquery.fileupload-validate' + ], factory); + } else { + factory(); + } +}(function () { 'use strict'; angular.module('blueimp.fileupload', []) + // The fileUpload service provides configuration options + // for the fileUpload directive and default handlers for + // File Upload events: .provider('fileUpload', function () { - var scopeApply = function () { + var scopeEvalAsync = function (expression) { var scope = angular.element(this) - .fileupload('option', 'scope')(); - if (!scope.$$phase) { - scope.$apply(); - } + .fileupload('option', 'scope'); + // Schedule a new $digest cycle if not already inside of one + // and evaluate the given expression: + scope.$evalAsync(expression); + }, + addFileMethods = function (scope, data) { + var files = data.files, + file = files[0]; + angular.forEach(files, function (file, index) { + file._index = index; + file.$state = function () { + return data.state(); + }; + file.$processing = function () { + return data.processing(); + }; + file.$progress = function () { + return data.progress(); + }; + file.$response = function () { + return data.response(); + }; + }); + file.$submit = function () { + if (!file.error) { + return data.submit(); + } + }; + file.$cancel = function () { + return data.abort(); + }; }, $config; $config = this.defaults = { handleResponse: function (e, data) { var files = data.result && data.result.files; if (files) { - data.scope().replace(data.files, files); + data.scope.replace(data.files, files); } else if (data.errorThrown || data.textStatus === 'error') { data.files[0].error = data.errorThrown || @@ -38,81 +83,66 @@ } }, add: function (e, data) { - var scope = data.scope(); + if (e.isDefaultPrevented()) { + return false; + } + var scope = data.scope, + filesCopy = []; + angular.forEach(data.files, function (file) { + filesCopy.push(file); + }); + scope.$parent.$applyAsync(function () { + addFileMethods(scope, data); + var method = scope.option('prependFiles') ? + 'unshift' : 'push'; + Array.prototype[method].apply(scope.queue, data.files); + }); data.process(function () { return scope.process(data); - }).always( - function () { - var file = data.files[0], - submit = function () { - return data.submit(); - }; - file.$cancel = function () { - scope.clear(data.files); - return data.abort(); - }; - file.$state = function () { - return data.state(); - }; - file.$progress = function () { - return data.progress(); - }; - file.$response = function () { - return data.response(); - }; - if (file.$state() === 'rejected') { - file._$submit = submit; - } else { - file.$submit = submit; - } - scope.$apply(function () { - var method = scope.option('prependFiles') ? - 'unshift' : 'push'; - Array.prototype[method].apply( - scope.queue, - data.files - ); - if (file.$submit && - (scope.option('autoUpload') || - data.autoUpload) && - data.autoUpload !== false) { - file.$submit(); - } - }); + }).always(function () { + scope.$parent.$applyAsync(function () { + addFileMethods(scope, data); + scope.replace(filesCopy, data.files); + }); + }).then(function () { + if ((scope.option('autoUpload') || + data.autoUpload) && + data.autoUpload !== false) { + data.submit(); } - ); - }, - progress: function (e, data) { - data.scope().$apply(); + }); }, done: function (e, data) { + if (e.isDefaultPrevented()) { + return false; + } var that = this; - data.scope().$apply(function () { + data.scope.$apply(function () { data.handleResponse.call(that, e, data); }); }, fail: function (e, data) { - var that = this; + if (e.isDefaultPrevented()) { + return false; + } + var that = this, + scope = data.scope; if (data.errorThrown === 'abort') { + scope.clear(data.files); return; } - if (data.dataType.indexOf('json') === data.dataType.length - 4) { - try { - data.result = angular.fromJson(data.jqXHR.responseText); - } catch (err) {} - } - data.scope().$apply(function () { + scope.$apply(function () { data.handleResponse.call(that, e, data); }); }, - stop: scopeApply, - processstart: scopeApply, - processstop: scopeApply, + stop: scopeEvalAsync, + processstart: scopeEvalAsync, + processstop: scopeEvalAsync, getNumberOfFiles: function () { - return this.scope().queue.length; + var scope = this.scope; + return scope.queue.length - scope.processing(); }, dataType: 'json', - prependFiles: true, autoUpload: false }; this.$get = [ @@ -124,8 +154,9 @@ ]; }) + // Format byte numbers to readable presentations: .provider('formatFileSizeFilter', function () { - var $config = this.defaults = { + var $config = { // Byte units following the IEC format // http://en.wikipedia.org/wiki/Kilobyte units: [ @@ -134,28 +165,61 @@ {size: 1000, suffix: ' KB'} ] }; + this.defaults = $config; this.$get = function () { return function (bytes) { if (!angular.isNumber(bytes)) { return ''; } var unit = true, - i = -1; + i = 0, + prefix, + suffix; while (unit) { - unit = $config.units[i += 1]; + unit = $config.units[i]; + prefix = unit.prefix || ''; + suffix = unit.suffix || ''; if (i === $config.units.length - 1 || bytes >= unit.size) { - return (bytes / unit.size).toFixed(2) + unit.suffix; + return prefix + (bytes / unit.size).toFixed(2) + suffix; } + i += 1; } }; }; }) + // The FileUploadController initializes the fileupload widget and + // provides scope methods to control the File Upload functionality: .controller('FileUploadController', [ - '$scope', '$element', '$attrs', 'fileUpload', - function ($scope, $element, $attrs, fileUpload) { - $scope.disabled = angular.element('') - .prop('disabled'); + '$scope', '$element', '$attrs', '$window', 'fileUpload', + function ($scope, $element, $attrs, $window, fileUpload) { + var uploadMethods = { + progress: function () { + return $element.fileupload('progress'); + }, + active: function () { + return $element.fileupload('active'); + }, + option: function (option, data) { + if (arguments.length === 1) { + return $element.fileupload('option', option); + } + $element.fileupload('option', option, data); + }, + add: function (data) { + return $element.fileupload('add', data); + }, + send: function (data) { + return $element.fileupload('send', data); + }, + process: function (data) { + return $element.fileupload('process', data); + }, + processing: function (data) { + return $element.fileupload('processing', data); + } + }; + $scope.disabled = !$window.jQuery.support.fileInput; $scope.queue = $scope.queue || []; $scope.clear = function (files) { var queue = this.queue, @@ -167,7 +231,8 @@ length = files.length; } while (i) { - if (queue[i -= 1] === file) { + i -= 1; + if (queue[i] === file) { return queue.splice(i, length); } } @@ -186,27 +251,6 @@ } } }; - $scope.progress = function () { - return $element.fileupload('progress'); - }; - $scope.active = function () { - return $element.fileupload('active'); - }; - $scope.option = function (option, data) { - return $element.fileupload('option', option, data); - }; - $scope.add = function (data) { - return $element.fileupload('add', data); - }; - $scope.send = function (data) { - return $element.fileupload('send', data); - }; - $scope.process = function (data) { - return $element.fileupload('process', data); - }; - $scope.processing = function (data) { - return $element.fileupload('processing', data); - }; $scope.applyOnQueue = function (method) { var list = this.queue.slice(0), i, @@ -224,16 +268,26 @@ $scope.cancel = function () { this.applyOnQueue('$cancel'); }; + // Add upload methods to the scope: + angular.extend($scope, uploadMethods); // The fileupload widget will initialize with // the options provided via "data-"-parameters, // as well as those given via options object: $element.fileupload(angular.extend( - {scope: function () { - return $scope; - }}, + {scope: $scope}, fileUpload.defaults )).on('fileuploadadd', function (e, data) { - data.scope = $scope.option('scope'); + data.scope = $scope; + }).on('fileuploadfail', function (e, data) { + if (data.errorThrown === 'abort') { + return; + } + if (data.dataType && + data.dataType.indexOf('json') === data.dataType.length - 4) { + try { + data.result = angular.fromJson(data.jqXHR.responseText); + } catch (ignore) {} + } }).on([ 'fileuploadadd', 'fileuploadsubmit', @@ -260,12 +314,25 @@ 'fileuploadprocessalways', 'fileuploadprocessstop' ].join(' '), function (e, data) { - $scope.$emit(e.type, data); + $scope.$parent.$applyAsync(function () { + if ($scope.$emit(e.type, data).defaultPrevented) { + e.preventDefault(); + } + }); + }).on('remove', function () { + // Remove upload methods from the scope, + // when the widget is removed: + var method; + for (method in uploadMethods) { + if (uploadMethods.hasOwnProperty(method)) { + delete $scope[method]; + } + } }); // Observe option changes: $scope.$watch( - $attrs.fileupload, - function (newOptions, oldOptions) { + $attrs.fileUpload, + function (newOptions) { if (newOptions) { $element.fileupload('option', newOptions); } @@ -274,10 +341,11 @@ } ]) + // Provide File Upload progress feedback: .controller('FileUploadProgressController', [ '$scope', '$attrs', '$parse', function ($scope, $attrs, $parse) { - var fn = $parse($attrs.progress), + var fn = $parse($attrs.fileUploadProgress), update = function () { var progress = fn($scope); if (!progress || !progress.total) { @@ -289,7 +357,7 @@ }; update(); $scope.$watch( - $attrs.progress + '.loaded', + $attrs.fileUploadProgress + '.loaded', function (newValue, oldValue) { if (newValue !== oldValue) { update(); @@ -299,37 +367,46 @@ } ]) + // Display File Upload previews: .controller('FileUploadPreviewController', [ - '$scope', '$element', '$attrs', '$parse', - function ($scope, $element, $attrs, $parse) { - var fn = $parse($attrs.preview), - file = fn($scope); - if (file.preview) { - $element.append(file.preview); - } + '$scope', '$element', '$attrs', + function ($scope, $element, $attrs) { + $scope.$watch( + $attrs.fileUploadPreview + '.preview', + function (preview) { + $element.empty(); + if (preview) { + $element.append(preview); + } + } + ); } ]) - .directive('fileupload', function () { + .directive('fileUpload', function () { return { - controller: 'FileUploadController' + controller: 'FileUploadController', + scope: true }; }) - .directive('progress', function () { + .directive('fileUploadProgress', function () { return { - controller: 'FileUploadProgressController' + controller: 'FileUploadProgressController', + scope: true }; }) - .directive('preview', function () { + .directive('fileUploadPreview', function () { return { controller: 'FileUploadPreviewController' }; }) + // Enhance the HTML5 download attribute to + // allow drag&drop of files to the desktop: .directive('download', function () { - return function (scope, elm, attrs) { + return function (scope, elm) { elm.on('dragstart', function (e) { try { e.originalEvent.dataTransfer.setData( @@ -340,9 +417,9 @@ elm.prop('href') ].join(':') ); - } catch (err) {} + } catch (ignore) {} }); }; }); -}()); +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-audio.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-audio.js new file mode 100755 index 0000000..1a746f9 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-audio.js @@ -0,0 +1,112 @@ +/* + * jQuery File Upload Audio Preview Plugin + * 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, require, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'load-image', + './jquery.fileupload-process' + ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory( + require('jquery'), + require('load-image') + ); + } else { + // Browser globals: + factory( + window.jQuery, + window.loadImage + ); + } +}(function ($, loadImage) { + 'use strict'; + + // Prepend to the default processQueue: + $.blueimp.fileupload.prototype.options.processQueue.unshift( + { + action: 'loadAudio', + // Use the action as prefix for the "@" options: + prefix: true, + fileTypes: '@', + maxFileSize: '@', + disabled: '@disableAudioPreview' + }, + { + action: 'setAudio', + name: '@audioPreviewName', + disabled: '@disableAudioPreview' + } + ); + + // The File Upload Audio Preview plugin extends the fileupload widget + // with audio preview functionality: + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + // The regular expression for the types of audio files to load, + // matched against the file type: + loadAudioFileTypes: /^audio\/.*$/ + }, + + _audioElement: document.createElement('audio'), + + processActions: { + + // Loads the audio file given via data.files and data.index + // as audio element if the browser supports playing it. + // Accepts the options fileTypes (regular expression) + // and maxFileSize (integer) to limit the files to load: + loadAudio: function (data, options) { + if (options.disabled) { + return data; + } + var file = data.files[data.index], + url, + audio; + if (this._audioElement.canPlayType && + this._audioElement.canPlayType(file.type) && + ($.type(options.maxFileSize) !== 'number' || + file.size <= options.maxFileSize) && + (!options.fileTypes || + options.fileTypes.test(file.type))) { + url = loadImage.createObjectURL(file); + if (url) { + audio = this._audioElement.cloneNode(false); + audio.src = url; + audio.controls = true; + data.audio = audio; + return data; + } + } + return data; + }, + + // Sets the audio element as a property of the file object: + setAudio: function (data, options) { + if (data.audio && !options.disabled) { + data.files[data.index][options.name || 'preview'] = data.audio; + } + return data; + } + + } + + }); + +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-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 100755 index 0000000..ffb02c2 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-image.js @@ -0,0 +1,324 @@ +/* + * jQuery File Upload Image Preview & Resize Plugin + * 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, require, window, Blob */ + +(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', + 'canvas-to-blob', + './jquery.fileupload-process' + ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory( + require('jquery'), + require('blueimp-load-image/js/load-image'), + require('blueimp-load-image/js/load-image-meta'), + require('blueimp-load-image/js/load-image-exif'), + require('blueimp-canvas-to-blob'), + require('./jquery.fileupload-process') + ); + } 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(); + } + } + // Prevent orienting the same image twice: + if (data.orientation) { + delete options.orientation; + } else { + data.orientation = options.orientation; + } + } + 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( + /\.\w+$/, + '.' + 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.parseMetaData(data.files[data.index], function (result) { + $.extend(data, result); + dfd.resolveWith(that, [data]); + }, options); + return dfd.promise(); + }, + + saveImageMetaData: function (data, options) { + if (!(data.imageHead && data.canvas && + data.canvas.toBlob && !options.disabled)) { + return data; + } + var file = data.files[data.index], + blob = new Blob([ + data.imageHead, + // Resized images always have a head size of 20 bytes, + // including the JPEG marker and a minimal JFIF header: + this._blobSlice.call(file, 20) + ], {type: file.type}); + blob.name = file.name; + data.files[data.index] = blob; + return data; + }, + + // Sets the resized version of the image as a property of the + // file object, must be called after "saveImage": + setImage: function (data, options) { + 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-jquery-ui.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-jquery-ui.js new file mode 100755 index 0000000..4f239fa --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-jquery-ui.js @@ -0,0 +1,155 @@ +/* + * jQuery File Upload jQuery UI Plugin + * 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, require, window */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery', './jquery.fileupload-ui'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory(require('jquery')); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + processdone: function (e, data) { + data.context.find('.start').button('enable'); + }, + progress: function (e, data) { + if (data.context) { + data.context.find('.progress').progressbar( + 'option', + 'value', + parseInt(data.loaded / data.total * 100, 10) + ); + } + }, + progressall: function (e, data) { + var $this = $(this); + $this.find('.fileupload-progress') + .find('.progress').progressbar( + 'option', + 'value', + parseInt(data.loaded / data.total * 100, 10) + ).end() + .find('.progress-extended').each(function () { + $(this).html( + ($this.data('blueimp-fileupload') || + $this.data('fileupload')) + ._renderExtendedProgress(data) + ); + }); + } + }, + + _renderUpload: function (func, files) { + var node = this._super(func, files), + showIconText = $(window).width() > 480; + node.find('.progress').empty().progressbar(); + node.find('.start').button({ + icons: {primary: 'ui-icon-circle-arrow-e'}, + text: showIconText + }); + node.find('.cancel').button({ + icons: {primary: 'ui-icon-cancel'}, + text: showIconText + }); + if (node.hasClass('fade')) { + node.hide(); + } + return node; + }, + + _renderDownload: function (func, files) { + var node = this._super(func, files), + showIconText = $(window).width() > 480; + node.find('.delete').button({ + icons: {primary: 'ui-icon-trash'}, + text: showIconText + }); + if (node.hasClass('fade')) { + node.hide(); + } + return node; + }, + + _startHandler: function (e) { + $(e.currentTarget).button('disable'); + this._super(e); + }, + + _transition: function (node) { + var deferred = $.Deferred(); + if (node.hasClass('fade')) { + node.fadeToggle( + this.options.transitionDuration, + this.options.transitionEasing, + function () { + deferred.resolveWith(node); + } + ); + } else { + deferred.resolveWith(node); + } + return deferred; + }, + + _create: function () { + this._super(); + this.element + .find('.fileupload-buttonbar') + .find('.fileinput-button').each(function () { + var input = $(this).find('input:file').detach(); + $(this) + .button({icons: {primary: 'ui-icon-plusthick'}}) + .append(input); + }) + .end().find('.start') + .button({icons: {primary: 'ui-icon-circle-arrow-e'}}) + .end().find('.cancel') + .button({icons: {primary: 'ui-icon-cancel'}}) + .end().find('.delete') + .button({icons: {primary: 'ui-icon-trash'}}) + .end().find('.progress').progressbar(); + }, + + _destroy: function () { + this.element + .find('.fileupload-buttonbar') + .find('.fileinput-button').each(function () { + var input = $(this).find('input:file').detach(); + $(this) + .button('destroy') + .append(input); + }) + .end().find('.start') + .button('destroy') + .end().find('.cancel') + .button('destroy') + .end().find('.delete') + .button('destroy') + .end().find('.progress').progressbar('destroy'); + this._super(); + } + + }); + +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js index 2f9eeed..ce914df 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-process.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload Processing Plugin 1.1 + * jQuery File Upload Processing Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2012, Sebastian Tschan @@ -9,8 +9,8 @@ * http://www.opensource.org/licenses/MIT */ -/*jslint nomen: true, unparam: true */ -/*global define, window */ +/* jshint nomen:false */ +/* global define, require, window */ (function (factory) { 'use strict'; @@ -20,6 +20,9 @@ 'jquery', './jquery.fileupload' ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory(require('jquery')); } else { // Browser globals: factory( @@ -64,13 +67,17 @@ */ }, - _processFile: function (data) { + _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, @@ -98,14 +105,20 @@ _transformProcessQueue: function (options) { var processQueue = []; $.each(options.processQueue, function () { - var settings = {}; + var settings = {}, + action = this.action, + prefix = this.prefix === true ? action : this.prefix; $.each(this, function (key, value) { if ($.type(value) === 'string' && value.charAt(0) === '@') { - settings[key] = options[value.slice(1)]; + settings[key] = options[ + value.slice(1) || (prefix ? prefix + + key.charAt(0).toUpperCase() + key.slice(1) : key) + ]; } else { settings[key] = value; } + }); processQueue.push(settings); }); @@ -127,10 +140,14 @@ if (this._processing === 0) { this._trigger('processstart'); } - $.each(data.files, function (index, file) { + $.each(data.files, function (index) { var opts = index ? $.extend({}, options) : options, func = function () { - return that._processFile(opts); + if (data.errorThrown) { + return $.Deferred() + .rejectWith(that, [data]).promise(); + } + return that._processFile(opts, data); }; opts.index = index; that._processing += 1; diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-resize.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-resize.js deleted file mode 100755 index ae5c5be..0000000 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-resize.js +++ /dev/null @@ -1,212 +0,0 @@ -/* - * jQuery File Upload Image Resize 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 - */ - -/*jslint nomen: true, unparam: true, regexp: true */ -/*global define, window */ - -(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-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: 'loadImage', - fileTypes: '@loadImageFileTypes', - maxFileSize: '@loadImageMaxFileSize', - noRevoke: '@loadImageNoRevoke', - disabled: '@disableImageLoad' - }, - { - action: 'resizeImage', - maxWidth: '@imageMaxWidth', - maxHeight: '@imageMaxHeight', - minWidth: '@imageMinWidth', - minHeight: '@imageMinHeight', - crop: '@imageCrop', - disabled: '@disableImageResize' - }, - { - action: 'saveImage', - disabled: '@disableImageResize' - }, - { - action: 'resizeImage', - maxWidth: '@previewMaxWidth', - maxHeight: '@previewMaxHeight', - minWidth: '@previewMinWidth', - minHeight: '@previewMinHeight', - crop: '@previewCrop', - canvas: '@previewAsCanvas', - disabled: '@disableImagePreview' - }, - { - action: 'setImage', - // The name of the property the resized image - // is saved as on the associated file object: - name: 'preview', - disabled: '@disableImagePreview' - } - ); - - // The File Upload Resize plugin extends the fileupload widget - // with image resize functionality: - $.widget('blueimp.fileupload', $.blueimp.fileupload, { - - options: { - // The regular expression for the types of images to load: - // matched against the file type: - loadImageFileTypes: /^image\/(gif|jpeg|png)$/, - // The maximum file size of images to load: - loadImageMaxFileSize: 5000000, // 5MB - // The maximum width of resized images: - imageMaxWidth: 1920, - // The maximum height of resized images: - imageMaxHeight: 1080, - // Define if resized images should be cropped or only scaled: - imageCrop: false, - // Disable the resize image functionality by default: - disableImageResize: true, - // The maximum width of the preview images: - previewMaxWidth: 80, - // The maximum height of the preview images: - previewMaxHeight: 80, - // Define if preview images should be cropped or only scaled: - previewCrop: false, - // Define if preview images should be resized as canvas elements: - previewAsCanvas: true - }, - - processActions: { - - // Loads the image given via data.files and data.index - // as img element if the browser supports canvas. - // Accepts the options fileTypes (regular expression) - // and maxFileSize (integer) to limit the files to load: - loadImage: function (data, options) { - if (options.disabled) { - return data; - } - var that = this, - file = data.files[data.index], - dfd = $.Deferred(); - if (($.type(options.maxFileSize) === 'number' && - file.size > options.maxFileSize) || - (options.fileTypes && - !options.fileTypes.test(file.type)) || - !loadImage( - file, - function (img) { - if (!img.src) { - return dfd.rejectWith(that, [data]); - } - data.img = img; - dfd.resolveWith(that, [data]); - }, - options - )) { - dfd.rejectWith(that, [data]); - } - return dfd.promise(); - }, - - // Resizes the image given as data.canvas or data.img - // and updates data.canvas or data.img with the resized image. - // Accepts the options maxWidth, maxHeight, minWidth, - // minHeight, canvas and crop: - resizeImage: function (data, options) { - options = $.extend({canvas: true}, options); - var img = (options.canvas && data.canvas) || data.img, - canvas; - if (img && !options.disabled) { - canvas = loadImage.scale(img, options); - if (canvas && (canvas.width !== img.width || - canvas.height !== img.height)) { - data[canvas.getContext ? 'canvas' : 'img'] = canvas; - } - } - return data; - }, - - // Saves the processed image given as data.canvas - // inplace at data.index of data.files: - saveImage: function (data, options) { - if (!data.canvas || options.disabled) { - return data; - } - var that = this, - file = data.files[data.index], - name = file.name, - dfd = $.Deferred(), - callback = function (blob) { - if (!blob.name) { - if (file.type === blob.type) { - blob.name = file.name; - } else if (file.name) { - blob.name = file.name.replace( - /\..+$/, - '.' + blob.type.substr(6) - ); - } - } - // Store the created blob at the position - // of the original file in the files list: - data.files[data.index] = blob; - dfd.resolveWith(that, [data]); - }; - // Use canvas.mozGetAsFile directly, to retain the filename, as - // Gecko doesn't support the filename option for FormData.append: - if (data.canvas.mozGetAsFile) { - callback(data.canvas.mozGetAsFile( - (/^image\/(jpeg|png)$/.test(file.type) && name) || - ((name && name.replace(/\..+$/, '')) || - 'blob') + '.png', - file.type - )); - } else if (data.canvas.toBlob) { - data.canvas.toBlob(callback, file.type); - } else { - return data; - } - return dfd.promise(); - }, - - // Sets the resized version of the image as a property of the - // file object, must be called after "saveImage": - setImage: function (data, options) { - var img = data.canvas || data.img; - if (img && !options.disabled) { - data.files[data.index][options.name] = img; - } - return data; - } - - } - - }); - -})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js index 5d22346..8154218 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-ui.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload User Interface Plugin 8.2.1 + * jQuery File Upload User Interface Plugin * 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, require, window */ (function (factory) { 'use strict'; @@ -19,9 +19,17 @@ define([ 'jquery', 'tmpl', - './jquery.fileupload-resize', + './jquery.fileupload-image', + './jquery.fileupload-audio', + './jquery.fileupload-video', './jquery.fileupload-validate' ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory( + require('jquery'), + require('tmpl') + ); } else { // Browser globals: factory( @@ -29,7 +37,7 @@ window.tmpl ); } -}(function ($, tmpl, loadImage) { +}(function ($, tmpl) { 'use strict'; $.blueimp.fileupload.prototype._specialOptions.push( @@ -61,10 +69,16 @@ // option of the $.ajax upload requests: dataType: 'json', + // Error and info messages: + messages: { + unknownError: 'Unknown error' + }, + // Function returning the current number of files, // used by the maxNumberOfFiles validation: getNumberOfFiles: function () { - return this.filesContainer.children().length; + return this.filesContainer.children() + .not('.processing').length; }, // Callback to retrieve the list of files from the server response: @@ -79,33 +93,53 @@ // 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 (e.isDefaultPrevented()) { + return false; + } var $this = $(this), that = $this.data('blueimp-fileupload') || $this.data('fileupload'), - options = that.options, - files = data.files; + 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 = that._renderUpload(files).data('data', data); + data.context.each(function (index) { + $(this).find('.size').text( + that._formatFileSize(data.files[index].size) + ); + }).removeClass('processing'); that._renderPreviews(data); - options.filesContainer[ - options.prependFiles ? 'prepend' : 'append' - ](data.context); - 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.files.error) { - 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.context && data.dataType && @@ -118,7 +152,7 @@ !$.support.transition && 'progress-animated' ) .attr('aria-valuenow', 100) - .find('.bar').css( + .children().first().css( 'width', '100%' ); @@ -127,6 +161,9 @@ }, // Callback for successful uploads: done: function (e, data) { + if (e.isDefaultPrevented()) { + return false; + } var that = $(this).data('blueimp-fileupload') || $(this).data('fileupload'), getFilesFromResponse = data.getFilesFromResponse || @@ -137,8 +174,8 @@ if (data.context) { data.context.each(function (index) { var file = files[index] || - {error: 'Empty file upload result'}, - deferred = that._addFinishedDeferreds(); + {error: 'Empty file upload result'}; + deferred = that._addFinishedDeferreds(); that._transition($(this)).done( function () { var node = $(this); @@ -157,8 +194,9 @@ ); }); } else { - template = that._renderDownload(files) - .appendTo(that.options.filesContainer); + template = that._renderDownload(files)[ + that.options.prependFiles ? 'prependTo' : 'appendTo' + ](that.options.filesContainer); that._forceReflow(template); deferred = that._addFinishedDeferreds(); that._transition(template).done( @@ -173,6 +211,9 @@ }, // 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, @@ -182,7 +223,7 @@ if (data.errorThrown !== 'abort') { var file = data.files[index]; file.error = file.error || data.errorThrown || - true; + data.i18n('unknownError'); deferred = that._addFinishedDeferreds(); that._transition($(this)).done( function () { @@ -213,8 +254,9 @@ } }); } else if (data.errorThrown !== 'abort') { - data.context = that._renderUpload(data.files) - .appendTo(that.options.filesContainer) + data.context = that._renderUpload(data.files)[ + that.options.prependFiles ? 'prependTo' : 'appendTo' + ](that.options.filesContainer) .data('data', data); that._forceReflow(data.context); deferred = that._addFinishedDeferreds(); @@ -234,18 +276,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'), @@ -260,13 +310,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(); @@ -278,6 +331,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(); @@ -289,31 +345,46 @@ 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 () { + processstart: function (e) { + if (e.isDefaultPrevented()) { + return false; + } $(this).addClass('fileupload-processing'); }, - processstop: function () { + 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'); - if (data.url) { - $.ajax(data).done(function () { + $(this).data('fileupload'), + removeNode = function () { that._transition(data.context).done( function () { $(this).remove(); that._trigger('destroyed', e, data); } ); + }; + if (data.url) { + data.dataType = data.dataType || that.options.dataType; + $.ajax(data).done(removeNode).fail(function () { + that._trigger('destroyfailed', e, data); }); + } else { + removeNode(); } } }, @@ -446,20 +517,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(); } }, @@ -606,6 +680,9 @@ _create: function () { this._super(); this._resetFinishedDeferreds(); + if (!$.support.fileInput) { + this._disableFileInputButton(); + } }, enable: function () { diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js index 2599da8..d6f754c 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-validate.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload Validation Plugin 1.0.2 + * jQuery File Upload Validation Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2013, Sebastian Tschan @@ -9,8 +9,7 @@ * http://www.opensource.org/licenses/MIT */ -/*jslint nomen: true, unparam: true, regexp: true */ -/*global define, window */ +/* global define, require, window */ (function (factory) { 'use strict'; @@ -20,6 +19,9 @@ 'jquery', './jquery.fileupload-process' ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory(require('jquery')); } else { // Browser globals: factory( @@ -34,13 +36,13 @@ { action: 'validate', // Always trigger this action, - // even if the previous action was rejected: + // even if the previous action was rejected: always: true, // Options taken from the global options map: - acceptFileTypes: '@acceptFileTypes', - maxFileSize: '@maxFileSize', - minFileSize: '@minFileSize', - maxNumberOfFiles: '@maxNumberOfFiles', + acceptFileTypes: '@', + maxFileSize: '@', + minFileSize: '@', + maxNumberOfFiles: '@', disabled: '@disableValidation' } ); @@ -84,18 +86,22 @@ var dfd = $.Deferred(), settings = this.options, file = data.files[data.index], - numberOfFiles = settings.getNumberOfFiles(); - if (numberOfFiles && $.type(options.maxNumberOfFiles) === 'number' && - numberOfFiles + data.files.length > options.maxNumberOfFiles) { + 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 (options.maxFileSize && file.size > options.maxFileSize) { + } else if (fileSize > options.maxFileSize) { file.error = settings.i18n('maxFileSize'); - } else if ($.type(file.size) === 'number' && - file.size < options.minFileSize) { + } else if ($.type(fileSize) === 'number' && + fileSize < options.minFileSize) { file.error = settings.i18n('minFileSize'); } else { delete file.error; diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-video.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-video.js new file mode 100755 index 0000000..8067ca1 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload-video.js @@ -0,0 +1,112 @@ +/* + * jQuery File Upload Video Preview Plugin + * 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, require, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'load-image', + './jquery.fileupload-process' + ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory( + require('jquery'), + require('load-image') + ); + } else { + // Browser globals: + factory( + window.jQuery, + window.loadImage + ); + } +}(function ($, loadImage) { + 'use strict'; + + // Prepend to the default processQueue: + $.blueimp.fileupload.prototype.options.processQueue.unshift( + { + action: 'loadVideo', + // Use the action as prefix for the "@" options: + prefix: true, + fileTypes: '@', + maxFileSize: '@', + disabled: '@disableVideoPreview' + }, + { + action: 'setVideo', + name: '@videoPreviewName', + disabled: '@disableVideoPreview' + } + ); + + // The File Upload Video Preview plugin extends the fileupload widget + // with video preview functionality: + $.widget('blueimp.fileupload', $.blueimp.fileupload, { + + options: { + // The regular expression for the types of video files to load, + // matched against the file type: + loadVideoFileTypes: /^video\/.*$/ + }, + + _videoElement: document.createElement('video'), + + processActions: { + + // Loads the video file given via data.files and data.index + // as video element if the browser supports playing it. + // Accepts the options fileTypes (regular expression) + // and maxFileSize (integer) to limit the files to load: + loadVideo: function (data, options) { + if (options.disabled) { + return data; + } + var file = data.files[data.index], + url, + video; + if (this._videoElement.canPlayType && + this._videoElement.canPlayType(file.type) && + ($.type(options.maxFileSize) !== 'number' || + file.size <= options.maxFileSize) && + (!options.fileTypes || + options.fileTypes.test(file.type))) { + url = loadImage.createObjectURL(file); + if (url) { + video = this._videoElement.cloneNode(false); + video.src = url; + video.controls = true; + data.video = video; + return data; + } + } + return data; + }, + + // Sets the video element as a property of the file object: + setVideo: function (data, options) { + if (data.video && !options.disabled) { + data.files[data.index][options.name || 'preview'] = data.video; + } + return data; + } + + } + + }); + +})); diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js index 03678f3..91b7254 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.fileupload.js @@ -1,5 +1,5 @@ /* - * jQuery File Upload Plugin 5.31.1 + * jQuery File Upload Plugin * 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, require, window, document, location, Blob, FormData */ (function (factory) { 'use strict'; @@ -20,6 +20,12 @@ 'jquery', 'jquery.ui.widget' ], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory( + require('jquery'), + require('./vendor/jquery.ui.widget') + ); } else { // Browser globals: factory(window.jQuery); @@ -27,12 +33,49 @@ }(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); + + // Helper function to create drag handlers for dragover/dragenter/dragleave: + function getDragHandler(type) { + var isDragOver = type === 'dragover'; + return function (e) { + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; + var dataTransfer = e.dataTransfer; + if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 && + this._trigger( + type, + $.Event(type, {delegatedEvent: e}) + ) !== false) { + e.preventDefault(); + if (isDragOver) { + dataTransfer.dropEffect = 'copy'; + } + } + }; + } + // 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 @@ -47,9 +90,9 @@ // The drop target element(s), by the default the complete document. // Set to null to disable drag & drop support: dropZone: $(document), - // The paste target element(s), by the default the complete document. - // Set to null to disable paste support: - pasteZone: $(document), + // The paste target element(s), by the default undefined. + // Set to a DOM node or jQuery object to enable file pasting: + pasteZone: undefined, // The file input field(s), that are listened to for change events. // If undefined, it is set to the file input fields inside // of the widget element on plugin initialization. @@ -72,6 +115,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, @@ -144,17 +195,23 @@ // 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).fileupload('option', 'autoUpload'))) { data.process().done(function () { @@ -220,7 +277,8 @@ // The following are jQuery ajax settings required for the file uploads: processData: false, contentType: false, - cache: false + cache: false, + timeout: 0 }, // A list of options that require reinitializing event listeners and/or @@ -233,6 +291,11 @@ 'forceIframeTransport' ], + _blobSlice: $.support.blobSlice && function () { + var slice = this.slice || this.webkitSlice || this.mozSlice; + return slice.apply(this, arguments); + }, + _BitrateTimer: function () { this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime()); this.loaded = 0; @@ -256,7 +319,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)) { @@ -336,10 +399,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 + ); } }, @@ -374,15 +445,18 @@ 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) { @@ -399,7 +473,8 @@ } 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 }); }); @@ -414,8 +489,6 @@ }); } if (options.blob) { - options.headers['Content-Disposition'] = 'attachment; filename="' + - encodeURI(file.name) + '"'; formData.append(paramName, options.blob, file.name); } else { $.each(options.files, function (index, file) { @@ -424,9 +497,10 @@ 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 ); } }); @@ -439,13 +513,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 @@ -510,8 +584,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'; @@ -570,22 +646,32 @@ // Adds convenience methods to the data callback argument: _addConvenienceMethods: function (e, data) { var that = this, - getPromise = function (data) { - return $.Deferred().resolveWith(that, [data]).promise(); + 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(resolveFunc, rejectFunc); + (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); + 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(); }; @@ -593,7 +679,9 @@ 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) { @@ -603,6 +691,10 @@ return that._getDeferredState(this._processQueue); } }; + data.processing = function () { + return !this.jqXHR && this._processQueue && that + ._getDeferredState(this._processQueue) === 'pending'; + }; data.progress = function () { return this._progress; }; @@ -627,12 +719,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, @@ -804,7 +897,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) { @@ -850,7 +947,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, @@ -874,50 +972,93 @@ 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 (!filesLength) { + return false; + } + if (limitSize && 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; }, - _replaceFileInput: function (input) { - var inputClone = input.clone(true); + _replaceFileInput: function (data) { + var input = data.fileInput, + inputClone = input.clone(true), + restoreFocus = input.is(document.activeElement); + // Add a reference for the new cloned file input to the data argument: + data.fileInputClone = inputClone; $('
').append(inputClone)[0].reset(); // Detaching allows to insert the fileInput on another form // without loosing the file input value: input.after(inputClone).detach(); + // If the fileInput had focus before it was detached, + // restore focus to the inputClone. + if (restoreFocus) { + inputClone.focus(); + } // Avoid memory leaks with the detached file input: $.cleanData(input.unbind('remove')); // Replace the original file input element in the fileInput @@ -949,7 +1090,25 @@ // to be returned together in one set: dfd.resolve([e]); }, - dirReader; + successHandler = function (entries) { + that._handleFileTreeEntries( + entries, + path + entry.name + '/' + ).done(function (files) { + dfd.resolve(files); + }).fail(errorHandler); + }, + readEntries = function () { + dirReader.readEntries(function (results) { + if (!results.length) { + successHandler(entries); + } else { + entries = entries.concat(results); + readEntries(); + } + }, errorHandler); + }, + dirReader, entries = []; path = path || ''; if (entry.isFile) { if (entry._file) { @@ -964,14 +1123,7 @@ } } else if (entry.isDirectory) { dirReader = entry.createReader(); - dirReader.readEntries(function (entries) { - that._handleFileTreeEntries( - entries, - path + entry.name + '/' - ).done(function (files) { - dfd.resolve(files); - }).fail(errorHandler); - }, errorHandler); + readEntries(); } else { // Return an empy list for file system items // other than files or directories: @@ -1073,9 +1225,13 @@ this._getFileInputFiles(data.fileInput).always(function (files) { data.files = files; if (that.options.replaceFileInput) { - that._replaceFileInput(data.fileInput); + that._replaceFileInput(data); } - if (that._trigger('change', e, data) !== false) { + if (that._trigger( + 'change', + $.Event('change', {delegatedEvent: e}), + data + ) !== false) { that._onAdd(e, data); } }); @@ -1092,60 +1248,65 @@ data.files.push(file); } }); - if (this._trigger('paste', e, data) === false || - this._onAdd(e, data) === false) { - return false; + if (this._trigger( + 'paste', + $.Event('paste', {delegatedEvent: e}), + data + ) !== false) { + this._onAdd(e, data); } } }, _onDrop: function (e) { + e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer; var that = this, - dataTransfer = e.dataTransfer = e.originalEvent && - e.originalEvent.dataTransfer, + dataTransfer = e.dataTransfer, data = {}; if (dataTransfer && dataTransfer.files && dataTransfer.files.length) { e.preventDefault(); this._getDroppedFiles(dataTransfer).always(function (files) { data.files = files; - if (that._trigger('drop', e, data) !== false) { + if (that._trigger( + 'drop', + $.Event('drop', {delegatedEvent: e}), + data + ) !== false) { that._onAdd(e, data); } }); } }, - _onDragOver: function (e) { - var dataTransfer = e.dataTransfer = e.originalEvent && - e.originalEvent.dataTransfer; - if (dataTransfer) { - if (this._trigger('dragover', e) === false) { - return false; - } - if ($.inArray('Files', dataTransfer.types) !== -1) { - dataTransfer.dropEffect = 'copy'; - e.preventDefault(); - } - } - }, + _onDragOver: getDragHandler('dragover'), + + _onDragEnter: getDragHandler('dragenter'), + + _onDragLeave: getDragHandler('dragleave'), _initEventHandlers: function () { if (this._isXHRUpload(this.options)) { this._on(this.options.dropZone, { dragover: this._onDragOver, - drop: this._onDrop + drop: this._onDrop, + // event.preventDefault() on dragenter is required for IE10+: + dragenter: this._onDragEnter, + // dragleave is not required, but added for completeness: + dragleave: this._onDragLeave }); this._on(this.options.pasteZone, { paste: this._onPaste }); } - this._on(this.options.fileInput, { - change: this._onChange - }); + if ($.support.fileInput) { + this._on(this.options.fileInput, { + change: this._onChange + }); + } }, _destroyEventHandlers: function () { - this._off(this.options.dropZone, 'dragover drop'); + this._off(this.options.dropZone, 'dragenter dragleave dragover drop'); this._off(this.options.pasteZone, 'paste'); this._off(this.options.fileInput, 'change'); }, @@ -1192,15 +1353,25 @@ _initDataAttributes: function () { var that = this, - options = this.options; + options = this.options, + data = this.element.data(); // Initialize options set via HTML5 data-attributes: $.each( - $(this.element[0].cloneNode(false)).data(), - function (key, value) { - if (that._isRegExpOption(key, value)) { - value = that._getRegExp(value); + this.element[0].attributes, + function (index, attr) { + var key = attr.name.toLowerCase(), + value; + if (/^data-/.test(key)) { + // Convert hyphen-ated key to camelCase: + key = key.slice(5).replace(/-[a-z]/g, function (str) { + return str.charAt(1).toUpperCase(); + }); + value = data[key]; + if (that._isRegExpOption(key, value)) { + value = that._getRegExp(value); + } + options[key] = value; } - options[key] = value; } ); }, @@ -1275,8 +1446,13 @@ if (aborted) { return; } + if (!files.length) { + dfd.reject(); + return; + } data.files = files; - jqXHR = that._onSend(null, data).then( + jqXHR = that._onSend(null, data); + jqXHR.then( function (result, textStatus, jqXHR) { dfd.resolve(result, textStatus, jqXHR); }, diff --git a/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js b/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js index e04e7a0..a7d34e0 100755 --- a/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js +++ b/vendor/assets/javascripts/jquery-fileupload/jquery.iframe-transport.js @@ -1,5 +1,5 @@ /* - * jQuery Iframe Transport Plugin 1.6.2 + * jQuery Iframe Transport Plugin * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2011, Sebastian Tschan @@ -9,14 +9,16 @@ * http://www.opensource.org/licenses/MIT */ -/*jslint unparam: true, nomen: true */ -/*global define, window, document */ +/* global define, require, window, document */ (function (factory) { 'use strict'; if (typeof define === 'function' && define.amd) { // Register as an anonymous AMD module: define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS: + factory(require('jquery')); } else { // Browser globals: factory(window.jQuery); @@ -27,7 +29,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 +37,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,15 +65,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) ? @@ -95,7 +102,7 @@ ); // Fix for IE endless progress bar activity bug // (happens on form submits to iframe targets): - $('') + $('') .appendTo(form); window.setTimeout(function () { // Removing the form in a setTimeout call @@ -138,6 +145,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 @@ -145,7 +154,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); }); } @@ -159,7 +171,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(); @@ -170,7 +182,15 @@ }); // The iframe transport returns the iframe content document as response. - // The following adds converters from iframe to text, json, html, and script: + // The following adds converters from iframe to text, json, html, xml + // and script. + // Please note that the Content-Type for JSON responses has to be text/plain + // or text/html, if the browser doesn't include application/json in the + // Accept header, else IE will show a download dialog. + // The Content-Type for XML responses on the other hand has to be always + // application/xml or text/xml, so IE properly parses the XML response. + // See also + // https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation $.ajaxSetup({ converters: { 'iframe text': function (iframe) { @@ -182,6 +202,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/locale.js b/vendor/assets/javascripts/jquery-fileupload/locale.js old mode 100644 new mode 100755 diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/canvas-to-blob.js b/vendor/assets/javascripts/jquery-fileupload/vendor/canvas-to-blob.js deleted file mode 100644 index fcef339..0000000 --- a/vendor/assets/javascripts/jquery-fileupload/vendor/canvas-to-blob.js +++ /dev/null @@ -1,95 +0,0 @@ -/* - * JavaScript Canvas to Blob 2.0.5 - * https://github.com/blueimp/JavaScript-Canvas-to-Blob - * - * Copyright 2012, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT - * - * Based on stackoverflow user Stoive's code snippet: - * http://stackoverflow.com/q/4998908 - */ - -/*jslint nomen: true, regexp: true */ -/*global window, atob, Blob, ArrayBuffer, Uint8Array, define */ - -(function (window) { - 'use strict'; - var CanvasPrototype = window.HTMLCanvasElement && - window.HTMLCanvasElement.prototype, - hasBlobConstructor = window.Blob && (function () { - try { - return Boolean(new Blob()); - } catch (e) { - return false; - } - }()), - hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && - (function () { - try { - return new Blob([new Uint8Array(100)]).size === 100; - } catch (e) { - return false; - } - }()), - BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || - window.MozBlobBuilder || window.MSBlobBuilder, - dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob && - window.ArrayBuffer && window.Uint8Array && function (dataURI) { - var byteString, - arrayBuffer, - intArray, - i, - mimeString, - bb; - if (dataURI.split(',')[0].indexOf('base64') >= 0) { - // Convert base64 to raw binary data held in a string: - byteString = atob(dataURI.split(',')[1]); - } else { - // Convert base64/URLEncoded data component to raw binary data: - byteString = decodeURIComponent(dataURI.split(',')[1]); - } - // Write the bytes of the string to an ArrayBuffer: - arrayBuffer = new ArrayBuffer(byteString.length); - intArray = new Uint8Array(arrayBuffer); - for (i = 0; i < byteString.length; i += 1) { - intArray[i] = byteString.charCodeAt(i); - } - // Separate out the mime component: - mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; - // Write the ArrayBuffer (or ArrayBufferView) to a blob: - if (hasBlobConstructor) { - return new Blob( - [hasArrayBufferViewSupport ? intArray : arrayBuffer], - {type: mimeString} - ); - } - bb = new BlobBuilder(); - bb.append(arrayBuffer); - return bb.getBlob(mimeString); - }; - if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) { - if (CanvasPrototype.mozGetAsFile) { - CanvasPrototype.toBlob = function (callback, type, quality) { - if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) { - callback(dataURLtoBlob(this.toDataURL(type, quality))); - } else { - callback(this.mozGetAsFile('blob', type)); - } - }; - } else if (CanvasPrototype.toDataURL && dataURLtoBlob) { - CanvasPrototype.toBlob = function (callback, type, quality) { - callback(dataURLtoBlob(this.toDataURL(type, quality))); - }; - } - } - if (typeof define === 'function' && define.amd) { - define(function () { - return dataURLtoBlob; - }); - } else { - window.dataURLtoBlob = dataURLtoBlob; - } -}(this)); diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/canvas-to-blob.min.js b/vendor/assets/javascripts/jquery-fileupload/vendor/canvas-to-blob.min.js new file mode 100755 index 0000000..1c82bba --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/canvas-to-blob.min.js @@ -0,0 +1,2 @@ +!function(t){"use strict";var e=t.HTMLCanvasElement&&t.HTMLCanvasElement.prototype,o=t.Blob&&function(){try{return Boolean(new Blob)}catch(t){return!1}}(),n=o&&t.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(t){return!1}}(),r=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||t.MSBlobBuilder,a=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,i=(o||r)&&t.atob&&t.ArrayBuffer&&t.Uint8Array&&function(t){var e,i,l,u,b,c,d,B,f;if(e=t.match(a),!e)throw new Error("invalid data URI");for(i=e[2]?e[1]:"text/plain"+(e[3]||";charset=US-ASCII"),l=!!e[4],u=t.slice(e[0].length),b=l?atob(u):decodeURIComponent(u),c=new ArrayBuffer(b.length),d=new Uint8Array(c),B=0;B + * http://github.com/tapmodo/Jcrop + * Copyright (c) 2008-2013 Tapmodo Interactive LLC {{{ + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * }}} + */ + +(function ($) { + + $.Jcrop = function (obj, opt) { + var options = $.extend({}, $.Jcrop.defaults), + docOffset, + _ua = navigator.userAgent.toLowerCase(), + is_msie = /msie/.test(_ua), + ie6mode = /msie [1-6]\./.test(_ua); + + // Internal Methods {{{ + function px(n) { + return Math.round(n) + 'px'; + } + function cssClass(cl) { + return options.baseClass + '-' + cl; + } + function supportsColorFade() { + return $.fx.step.hasOwnProperty('backgroundColor'); + } + function getPos(obj) //{{{ + { + var pos = $(obj).offset(); + return [pos.left, pos.top]; + } + //}}} + function mouseAbs(e) //{{{ + { + return [(e.pageX - docOffset[0]), (e.pageY - docOffset[1])]; + } + //}}} + function setOptions(opt) //{{{ + { + if (typeof(opt) !== 'object') opt = {}; + options = $.extend(options, opt); + + $.each(['onChange','onSelect','onRelease','onDblClick'],function(i,e) { + if (typeof(options[e]) !== 'function') options[e] = function () {}; + }); + } + //}}} + function startDragMode(mode, pos, touch) //{{{ + { + docOffset = getPos($img); + Tracker.setCursor(mode === 'move' ? mode : mode + '-resize'); + + if (mode === 'move') { + return Tracker.activateHandlers(createMover(pos), doneSelect, touch); + } + + var fc = Coords.getFixed(); + var opp = oppLockCorner(mode); + var opc = Coords.getCorner(oppLockCorner(opp)); + + Coords.setPressed(Coords.getCorner(opp)); + Coords.setCurrent(opc); + + Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch); + } + //}}} + function dragmodeHandler(mode, f) //{{{ + { + return function (pos) { + if (!options.aspectRatio) { + switch (mode) { + case 'e': + pos[1] = f.y2; + break; + case 'w': + pos[1] = f.y2; + break; + case 'n': + pos[0] = f.x2; + break; + case 's': + pos[0] = f.x2; + break; + } + } else { + switch (mode) { + case 'e': + pos[1] = f.y + 1; + break; + case 'w': + pos[1] = f.y + 1; + break; + case 'n': + pos[0] = f.x + 1; + break; + case 's': + pos[0] = f.x + 1; + break; + } + } + Coords.setCurrent(pos); + Selection.update(); + }; + } + //}}} + function createMover(pos) //{{{ + { + var lloc = pos; + KeyManager.watchKeys(); + + return function (pos) { + Coords.moveOffset([pos[0] - lloc[0], pos[1] - lloc[1]]); + lloc = pos; + + Selection.update(); + }; + } + //}}} + function oppLockCorner(ord) //{{{ + { + switch (ord) { + case 'n': + return 'sw'; + case 's': + return 'nw'; + case 'e': + return 'nw'; + case 'w': + return 'ne'; + case 'ne': + return 'sw'; + case 'nw': + return 'se'; + case 'se': + return 'nw'; + case 'sw': + return 'ne'; + } + } + //}}} + function createDragger(ord) //{{{ + { + return function (e) { + if (options.disabled) { + return false; + } + if ((ord === 'move') && !options.allowMove) { + return false; + } + + // Fix position of crop area when dragged the very first time. + // Necessary when crop image is in a hidden element when page is loaded. + docOffset = getPos($img); + + btndown = true; + startDragMode(ord, mouseAbs(e)); + e.stopPropagation(); + e.preventDefault(); + return false; + }; + } + //}}} + function presize($obj, w, h) //{{{ + { + var nw = $obj.width(), + nh = $obj.height(); + if ((nw > w) && w > 0) { + nw = w; + nh = (w / $obj.width()) * $obj.height(); + } + if ((nh > h) && h > 0) { + nh = h; + nw = (h / $obj.height()) * $obj.width(); + } + xscale = $obj.width() / nw; + yscale = $obj.height() / nh; + $obj.width(nw).height(nh); + } + //}}} + function unscale(c) //{{{ + { + return { + x: c.x * xscale, + y: c.y * yscale, + x2: c.x2 * xscale, + y2: c.y2 * yscale, + w: c.w * xscale, + h: c.h * yscale + }; + } + //}}} + function doneSelect(pos) //{{{ + { + var c = Coords.getFixed(); + if ((c.w > options.minSelect[0]) && (c.h > options.minSelect[1])) { + Selection.enableHandles(); + Selection.done(); + } else { + Selection.release(); + } + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + } + //}}} + function newSelection(e) //{{{ + { + if (options.disabled) { + return false; + } + if (!options.allowSelect) { + return false; + } + btndown = true; + docOffset = getPos($img); + Selection.disableHandles(); + Tracker.setCursor('crosshair'); + var pos = mouseAbs(e); + Coords.setPressed(pos); + Selection.update(); + Tracker.activateHandlers(selectDrag, doneSelect, e.type.substring(0,5)==='touch'); + KeyManager.watchKeys(); + + e.stopPropagation(); + e.preventDefault(); + return false; + } + //}}} + function selectDrag(pos) //{{{ + { + Coords.setCurrent(pos); + Selection.update(); + } + //}}} + function newTracker() //{{{ + { + var trk = $('
').addClass(cssClass('tracker')); + if (is_msie) { + trk.css({ + opacity: 0, + backgroundColor: 'white' + }); + } + return trk; + } + //}}} + + // }}} + // Initialization {{{ + // Sanitize some options {{{ + if (typeof(obj) !== 'object') { + obj = $(obj)[0]; + } + if (typeof(opt) !== 'object') { + opt = {}; + } + // }}} + setOptions(opt); + // Initialize some jQuery objects {{{ + // The values are SET on the image(s) for the interface + // If the original image has any of these set, they will be reset + // However, if you destroy() the Jcrop instance the original image's + // character in the DOM will be as you left it. + var img_css = { + border: 'none', + visibility: 'visible', + margin: 0, + padding: 0, + position: 'absolute', + top: 0, + left: 0 + }; + + var $origimg = $(obj), + img_mode = true; + + if (obj.tagName == 'IMG') { + // Fix size of crop image. + // Necessary when crop image is within a hidden element when page is loaded. + if ($origimg[0].width != 0 && $origimg[0].height != 0) { + // Obtain dimensions from contained img element. + $origimg.width($origimg[0].width); + $origimg.height($origimg[0].height); + } else { + // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0). + var tempImage = new Image(); + tempImage.src = $origimg[0].src; + $origimg.width(tempImage.width); + $origimg.height(tempImage.height); + } + + var $img = $origimg.clone().removeAttr('id').css(img_css).show(); + + $img.width($origimg.width()); + $img.height($origimg.height()); + $origimg.after($img).hide(); + + } else { + $img = $origimg.css(img_css).show(); + img_mode = false; + if (options.shade === null) { options.shade = true; } + } + + presize($img, options.boxWidth, options.boxHeight); + + var boundx = $img.width(), + boundy = $img.height(), + + + $div = $('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({ + position: 'relative', + backgroundColor: options.bgColor + }).insertAfter($origimg).append($img); + + if (options.addClass) { + $div.addClass(options.addClass); + } + + var $img2 = $('
'), + + $img_holder = $('
') + .width('100%').height('100%').css({ + zIndex: 310, + position: 'absolute', + overflow: 'hidden' + }), + + $hdl_holder = $('
') + .width('100%').height('100%').css('zIndex', 320), + + $sel = $('
') + .css({ + position: 'absolute', + zIndex: 600 + }).dblclick(function(){ + var c = Coords.getFixed(); + options.onDblClick.call(api,c); + }).insertBefore($img).append($img_holder, $hdl_holder); + + if (img_mode) { + + $img2 = $('') + .attr('src', $img.attr('src')).css(img_css).width(boundx).height(boundy), + + $img_holder.append($img2); + + } + + if (ie6mode) { + $sel.css({ + overflowY: 'hidden' + }); + } + + var bound = options.boundary; + var $trk = newTracker().width(boundx + (bound * 2)).height(boundy + (bound * 2)).css({ + position: 'absolute', + top: px(-bound), + left: px(-bound), + zIndex: 290 + }).mousedown(newSelection); + + /* }}} */ + // Set more variables {{{ + var bgcolor = options.bgColor, + bgopacity = options.bgOpacity, + xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true, + btndown, animating, shift_down; + + docOffset = getPos($img); + // }}} + // }}} + // Internal Modules {{{ + // Touch Module {{{ + var Touch = (function () { + // Touch support detection function adapted (under MIT License) + // from code by Jeffrey Sambells - http://github.com/iamamused/ + function hasTouchSupport() { + var support = {}, events = ['touchstart', 'touchmove', 'touchend'], + el = document.createElement('div'), i; + + try { + for(i=0; i x1 + ox) { + ox -= ox + x1; + } + if (0 > y1 + oy) { + oy -= oy + y1; + } + + if (boundy < y2 + oy) { + oy += boundy - (y2 + oy); + } + if (boundx < x2 + ox) { + ox += boundx - (x2 + ox); + } + + x1 += ox; + x2 += ox; + y1 += oy; + y2 += oy; + } + //}}} + function getCorner(ord) //{{{ + { + var c = getFixed(); + switch (ord) { + case 'ne': + return [c.x2, c.y]; + case 'nw': + return [c.x, c.y]; + case 'se': + return [c.x2, c.y2]; + case 'sw': + return [c.x, c.y2]; + } + } + //}}} + function getFixed() //{{{ + { + if (!options.aspectRatio) { + return getRect(); + } + // This function could use some optimization I think... + var aspect = options.aspectRatio, + min_x = options.minSize[0] / xscale, + + + //min_y = options.minSize[1]/yscale, + max_x = options.maxSize[0] / xscale, + max_y = options.maxSize[1] / yscale, + rw = x2 - x1, + rh = y2 - y1, + rwa = Math.abs(rw), + rha = Math.abs(rh), + real_ratio = rwa / rha, + xx, yy, w, h; + + if (max_x === 0) { + max_x = boundx * 10; + } + if (max_y === 0) { + max_y = boundy * 10; + } + if (real_ratio < aspect) { + yy = y2; + w = rha * aspect; + xx = rw < 0 ? x1 - w : w + x1; + + if (xx < 0) { + xx = 0; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } else if (xx > boundx) { + xx = boundx; + h = Math.abs((xx - x1) / aspect); + yy = rh < 0 ? y1 - h : h + y1; + } + } else { + xx = x2; + h = rwa / aspect; + yy = rh < 0 ? y1 - h : y1 + h; + if (yy < 0) { + yy = 0; + w = Math.abs((yy - y1) * aspect); + xx = rw < 0 ? x1 - w : w + x1; + } else if (yy > boundy) { + yy = boundy; + w = Math.abs(yy - y1) * aspect; + xx = rw < 0 ? x1 - w : w + x1; + } + } + + // Magic %-) + if (xx > x1) { // right side + if (xx - x1 < min_x) { + xx = x1 + min_x; + } else if (xx - x1 > max_x) { + xx = x1 + max_x; + } + if (yy > y1) { + yy = y1 + (xx - x1) / aspect; + } else { + yy = y1 - (xx - x1) / aspect; + } + } else if (xx < x1) { // left side + if (x1 - xx < min_x) { + xx = x1 - min_x; + } else if (x1 - xx > max_x) { + xx = x1 - max_x; + } + if (yy > y1) { + yy = y1 + (x1 - xx) / aspect; + } else { + yy = y1 - (x1 - xx) / aspect; + } + } + + if (xx < 0) { + x1 -= xx; + xx = 0; + } else if (xx > boundx) { + x1 -= xx - boundx; + xx = boundx; + } + + if (yy < 0) { + y1 -= yy; + yy = 0; + } else if (yy > boundy) { + y1 -= yy - boundy; + yy = boundy; + } + + return makeObj(flipCoords(x1, y1, xx, yy)); + } + //}}} + function rebound(p) //{{{ + { + if (p[0] < 0) p[0] = 0; + if (p[1] < 0) p[1] = 0; + + if (p[0] > boundx) p[0] = boundx; + if (p[1] > boundy) p[1] = boundy; + + return [Math.round(p[0]), Math.round(p[1])]; + } + //}}} + function flipCoords(x1, y1, x2, y2) //{{{ + { + var xa = x1, + xb = x2, + ya = y1, + yb = y2; + if (x2 < x1) { + xa = x2; + xb = x1; + } + if (y2 < y1) { + ya = y2; + yb = y1; + } + return [xa, ya, xb, yb]; + } + //}}} + function getRect() //{{{ + { + var xsize = x2 - x1, + ysize = y2 - y1, + delta; + + if (xlimit && (Math.abs(xsize) > xlimit)) { + x2 = (xsize > 0) ? (x1 + xlimit) : (x1 - xlimit); + } + if (ylimit && (Math.abs(ysize) > ylimit)) { + y2 = (ysize > 0) ? (y1 + ylimit) : (y1 - ylimit); + } + + if (ymin / yscale && (Math.abs(ysize) < ymin / yscale)) { + y2 = (ysize > 0) ? (y1 + ymin / yscale) : (y1 - ymin / yscale); + } + if (xmin / xscale && (Math.abs(xsize) < xmin / xscale)) { + x2 = (xsize > 0) ? (x1 + xmin / xscale) : (x1 - xmin / xscale); + } + + if (x1 < 0) { + x2 -= x1; + x1 -= x1; + } + if (y1 < 0) { + y2 -= y1; + y1 -= y1; + } + if (x2 < 0) { + x1 -= x2; + x2 -= x2; + } + if (y2 < 0) { + y1 -= y2; + y2 -= y2; + } + if (x2 > boundx) { + delta = x2 - boundx; + x1 -= delta; + x2 -= delta; + } + if (y2 > boundy) { + delta = y2 - boundy; + y1 -= delta; + y2 -= delta; + } + if (x1 > boundx) { + delta = x1 - boundy; + y2 -= delta; + y1 -= delta; + } + if (y1 > boundy) { + delta = y1 - boundy; + y2 -= delta; + y1 -= delta; + } + + return makeObj(flipCoords(x1, y1, x2, y2)); + } + //}}} + function makeObj(a) //{{{ + { + return { + x: a[0], + y: a[1], + x2: a[2], + y2: a[3], + w: a[2] - a[0], + h: a[3] - a[1] + }; + } + //}}} + + return { + flipCoords: flipCoords, + setPressed: setPressed, + setCurrent: setCurrent, + getOffset: getOffset, + moveOffset: moveOffset, + getCorner: getCorner, + getFixed: getFixed + }; + }()); + + //}}} + // Shade Module {{{ + var Shade = (function() { + var enabled = false, + holder = $('
').css({ + position: 'absolute', + zIndex: 240, + opacity: 0 + }), + shades = { + top: createShade(), + left: createShade().height(boundy), + right: createShade().height(boundy), + bottom: createShade() + }; + + function resizeShades(w,h) { + shades.left.css({ height: px(h) }); + shades.right.css({ height: px(h) }); + } + function updateAuto() + { + return updateShade(Coords.getFixed()); + } + function updateShade(c) + { + shades.top.css({ + left: px(c.x), + width: px(c.w), + height: px(c.y) + }); + shades.bottom.css({ + top: px(c.y2), + left: px(c.x), + width: px(c.w), + height: px(boundy-c.y2) + }); + shades.right.css({ + left: px(c.x2), + width: px(boundx-c.x2) + }); + shades.left.css({ + width: px(c.x) + }); + } + function createShade() { + return $('
').css({ + position: 'absolute', + backgroundColor: options.shadeColor||options.bgColor + }).appendTo(holder); + } + function enableShade() { + if (!enabled) { + enabled = true; + holder.insertBefore($img); + updateAuto(); + Selection.setBgOpacity(1,0,1); + $img2.hide(); + + setBgColor(options.shadeColor||options.bgColor,1); + if (Selection.isAwake()) + { + setOpacity(options.bgOpacity,1); + } + else setOpacity(1,1); + } + } + function setBgColor(color,now) { + colorChangeMacro(getShades(),color,now); + } + function disableShade() { + if (enabled) { + holder.remove(); + $img2.show(); + enabled = false; + if (Selection.isAwake()) { + Selection.setBgOpacity(options.bgOpacity,1,1); + } else { + Selection.setBgOpacity(1,1,1); + Selection.disableHandles(); + } + colorChangeMacro($div,0,1); + } + } + function setOpacity(opacity,now) { + if (enabled) { + if (options.bgFade && !now) { + holder.animate({ + opacity: 1-opacity + },{ + queue: false, + duration: options.fadeTime + }); + } + else holder.css({opacity:1-opacity}); + } + } + function refreshAll() { + options.shade ? enableShade() : disableShade(); + if (Selection.isAwake()) setOpacity(options.bgOpacity); + } + function getShades() { + return holder.children(); + } + + return { + update: updateAuto, + updateRaw: updateShade, + getShades: getShades, + setBgColor: setBgColor, + enable: enableShade, + disable: disableShade, + resize: resizeShades, + refresh: refreshAll, + opacity: setOpacity + }; + }()); + // }}} + // Selection Module {{{ + var Selection = (function () { + var awake, + hdep = 370, + borders = {}, + handle = {}, + dragbar = {}, + seehandles = false; + + // Private Methods + function insertBorder(type) //{{{ + { + var jq = $('
').css({ + position: 'absolute', + opacity: options.borderOpacity + }).addClass(cssClass(type)); + $img_holder.append(jq); + return jq; + } + //}}} + function dragDiv(ord, zi) //{{{ + { + var jq = $('
').mousedown(createDragger(ord)).css({ + cursor: ord + '-resize', + position: 'absolute', + zIndex: zi + }).addClass('ord-'+ord); + + if (Touch.support) { + jq.bind('touchstart.jcrop', Touch.createDragger(ord)); + } + + $hdl_holder.append(jq); + return jq; + } + //}}} + function insertHandle(ord) //{{{ + { + var hs = options.handleSize, + + div = dragDiv(ord, hdep++).css({ + opacity: options.handleOpacity + }).addClass(cssClass('handle')); + + if (hs) { div.width(hs).height(hs); } + + return div; + } + //}}} + function insertDragbar(ord) //{{{ + { + return dragDiv(ord, hdep++).addClass('jcrop-dragbar'); + } + //}}} + function createDragbars(li) //{{{ + { + var i; + for (i = 0; i < li.length; i++) { + dragbar[li[i]] = insertDragbar(li[i]); + } + } + //}}} + function createBorders(li) //{{{ + { + var cl,i; + for (i = 0; i < li.length; i++) { + switch(li[i]){ + case'n': cl='hline'; break; + case's': cl='hline bottom'; break; + case'e': cl='vline right'; break; + case'w': cl='vline'; break; + } + borders[li[i]] = insertBorder(cl); + } + } + //}}} + function createHandles(li) //{{{ + { + var i; + for (i = 0; i < li.length; i++) { + handle[li[i]] = insertHandle(li[i]); + } + } + //}}} + function moveto(x, y) //{{{ + { + if (!options.shade) { + $img2.css({ + top: px(-y), + left: px(-x) + }); + } + $sel.css({ + top: px(y), + left: px(x) + }); + } + //}}} + function resize(w, h) //{{{ + { + $sel.width(Math.round(w)).height(Math.round(h)); + } + //}}} + function refresh() //{{{ + { + var c = Coords.getFixed(); + + Coords.setPressed([c.x, c.y]); + Coords.setCurrent([c.x2, c.y2]); + + updateVisible(); + } + //}}} + + // Internal Methods + function updateVisible(select) //{{{ + { + if (awake) { + return update(select); + } + } + //}}} + function update(select) //{{{ + { + var c = Coords.getFixed(); + + resize(c.w, c.h); + moveto(c.x, c.y); + if (options.shade) Shade.updateRaw(c); + + awake || show(); + + if (select) { + options.onSelect.call(api, unscale(c)); + } else { + options.onChange.call(api, unscale(c)); + } + } + //}}} + function setBgOpacity(opacity,force,now) //{{{ + { + if (!awake && !force) return; + if (options.bgFade && !now) { + $img.animate({ + opacity: opacity + },{ + queue: false, + duration: options.fadeTime + }); + } else { + $img.css('opacity', opacity); + } + } + //}}} + function show() //{{{ + { + $sel.show(); + + if (options.shade) Shade.opacity(bgopacity); + else setBgOpacity(bgopacity,true); + + awake = true; + } + //}}} + function release() //{{{ + { + disableHandles(); + $sel.hide(); + + if (options.shade) Shade.opacity(1); + else setBgOpacity(1); + + awake = false; + options.onRelease.call(api); + } + //}}} + function showHandles() //{{{ + { + if (seehandles) { + $hdl_holder.show(); + } + } + //}}} + function enableHandles() //{{{ + { + seehandles = true; + if (options.allowResize) { + $hdl_holder.show(); + return true; + } + } + //}}} + function disableHandles() //{{{ + { + seehandles = false; + $hdl_holder.hide(); + } + //}}} + function animMode(v) //{{{ + { + if (v) { + animating = true; + disableHandles(); + } else { + animating = false; + enableHandles(); + } + } + //}}} + function done() //{{{ + { + animMode(false); + refresh(); + } + //}}} + // Insert draggable elements {{{ + // Insert border divs for outline + + if (options.dragEdges && $.isArray(options.createDragbars)) + createDragbars(options.createDragbars); + + if ($.isArray(options.createHandles)) + createHandles(options.createHandles); + + if (options.drawBorders && $.isArray(options.createBorders)) + createBorders(options.createBorders); + + //}}} + + // This is a hack for iOS5 to support drag/move touch functionality + $(document).bind('touchstart.jcrop-ios',function(e) { + if ($(e.currentTarget).hasClass('jcrop-tracker')) e.stopPropagation(); + }); + + var $track = newTracker().mousedown(createDragger('move')).css({ + cursor: 'move', + position: 'absolute', + zIndex: 360 + }); + + if (Touch.support) { + $track.bind('touchstart.jcrop', Touch.createDragger('move')); + } + + $img_holder.append($track); + disableHandles(); + + return { + updateVisible: updateVisible, + update: update, + release: release, + refresh: refresh, + isAwake: function () { + return awake; + }, + setCursor: function (cursor) { + $track.css('cursor', cursor); + }, + enableHandles: enableHandles, + enableOnly: function () { + seehandles = true; + }, + showHandles: showHandles, + disableHandles: disableHandles, + animMode: animMode, + setBgOpacity: setBgOpacity, + done: done + }; + }()); + + //}}} + // Tracker Module {{{ + var Tracker = (function () { + var onMove = function () {}, + onDone = function () {}, + trackDoc = options.trackDocument; + + function toFront(touch) //{{{ + { + $trk.css({ + zIndex: 450 + }); + + if (touch) + $(document) + .bind('touchmove.jcrop', trackTouchMove) + .bind('touchend.jcrop', trackTouchEnd); + + else if (trackDoc) + $(document) + .bind('mousemove.jcrop',trackMove) + .bind('mouseup.jcrop',trackUp); + } + //}}} + function toBack() //{{{ + { + $trk.css({ + zIndex: 290 + }); + $(document).unbind('.jcrop'); + } + //}}} + function trackMove(e) //{{{ + { + onMove(mouseAbs(e)); + return false; + } + //}}} + function trackUp(e) //{{{ + { + e.preventDefault(); + e.stopPropagation(); + + if (btndown) { + btndown = false; + + onDone(mouseAbs(e)); + + if (Selection.isAwake()) { + options.onSelect.call(api, unscale(Coords.getFixed())); + } + + toBack(); + onMove = function () {}; + onDone = function () {}; + } + + return false; + } + //}}} + function activateHandlers(move, done, touch) //{{{ + { + btndown = true; + onMove = move; + onDone = done; + toFront(touch); + return false; + } + //}}} + function trackTouchMove(e) //{{{ + { + onMove(mouseAbs(Touch.cfilter(e))); + return false; + } + //}}} + function trackTouchEnd(e) //{{{ + { + return trackUp(Touch.cfilter(e)); + } + //}}} + function setCursor(t) //{{{ + { + $trk.css('cursor', t); + } + //}}} + + if (!trackDoc) { + $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp); + } + + $img.before($trk); + return { + activateHandlers: activateHandlers, + setCursor: setCursor + }; + }()); + //}}} + // KeyManager Module {{{ + var KeyManager = (function () { + var $keymgr = $('').css({ + position: 'fixed', + left: '-120px', + width: '12px' + }).addClass('jcrop-keymgr'), + + $keywrap = $('
').css({ + position: 'absolute', + overflow: 'hidden' + }).append($keymgr); + + function watchKeys() //{{{ + { + if (options.keySupport) { + $keymgr.show(); + $keymgr.focus(); + } + } + //}}} + function onBlur(e) //{{{ + { + $keymgr.hide(); + } + //}}} + function doNudge(e, x, y) //{{{ + { + if (options.allowMove) { + Coords.moveOffset([x, y]); + Selection.updateVisible(true); + } + e.preventDefault(); + e.stopPropagation(); + } + //}}} + function parseKey(e) //{{{ + { + if (e.ctrlKey || e.metaKey) { + return true; + } + shift_down = e.shiftKey ? true : false; + var nudge = shift_down ? 10 : 1; + + switch (e.keyCode) { + case 37: + doNudge(e, -nudge, 0); + break; + case 39: + doNudge(e, nudge, 0); + break; + case 38: + doNudge(e, 0, -nudge); + break; + case 40: + doNudge(e, 0, nudge); + break; + case 27: + if (options.allowSelect) Selection.release(); + break; + case 9: + return true; + } + + return false; + } + //}}} + + if (options.keySupport) { + $keymgr.keydown(parseKey).blur(onBlur); + if (ie6mode || !options.fixedSupport) { + $keymgr.css({ + position: 'absolute', + left: '-20px' + }); + $keywrap.append($keymgr).insertBefore($img); + } else { + $keymgr.insertBefore($img); + } + } + + + return { + watchKeys: watchKeys + }; + }()); + //}}} + // }}} + // API methods {{{ + function setClass(cname) //{{{ + { + $div.removeClass().addClass(cssClass('holder')).addClass(cname); + } + //}}} + function animateTo(a, callback) //{{{ + { + var x1 = a[0] / xscale, + y1 = a[1] / yscale, + x2 = a[2] / xscale, + y2 = a[3] / yscale; + + if (animating) { + return; + } + + var animto = Coords.flipCoords(x1, y1, x2, y2), + c = Coords.getFixed(), + initcr = [c.x, c.y, c.x2, c.y2], + animat = initcr, + interv = options.animationDelay, + ix1 = animto[0] - initcr[0], + iy1 = animto[1] - initcr[1], + ix2 = animto[2] - initcr[2], + iy2 = animto[3] - initcr[3], + pcent = 0, + velocity = options.swingSpeed; + + x1 = animat[0]; + y1 = animat[1]; + x2 = animat[2]; + y2 = animat[3]; + + Selection.animMode(true); + var anim_timer; + + function queueAnimator() { + window.setTimeout(animator, interv); + } + var animator = (function () { + return function () { + pcent += (100 - pcent) / velocity; + + animat[0] = Math.round(x1 + ((pcent / 100) * ix1)); + animat[1] = Math.round(y1 + ((pcent / 100) * iy1)); + animat[2] = Math.round(x2 + ((pcent / 100) * ix2)); + animat[3] = Math.round(y2 + ((pcent / 100) * iy2)); + + if (pcent >= 99.8) { + pcent = 100; + } + if (pcent < 100) { + setSelectRaw(animat); + queueAnimator(); + } else { + Selection.done(); + Selection.animMode(false); + if (typeof(callback) === 'function') { + callback.call(api); + } + } + }; + }()); + queueAnimator(); + } + //}}} + function setSelect(rect) //{{{ + { + setSelectRaw([rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale]); + options.onSelect.call(api, unscale(Coords.getFixed())); + Selection.enableHandles(); + } + //}}} + function setSelectRaw(l) //{{{ + { + Coords.setPressed([l[0], l[1]]); + Coords.setCurrent([l[2], l[3]]); + Selection.update(); + } + //}}} + function tellSelect() //{{{ + { + return unscale(Coords.getFixed()); + } + //}}} + function tellScaled() //{{{ + { + return Coords.getFixed(); + } + //}}} + function setOptionsNew(opt) //{{{ + { + setOptions(opt); + interfaceUpdate(); + } + //}}} + function disableCrop() //{{{ + { + options.disabled = true; + Selection.disableHandles(); + Selection.setCursor('default'); + Tracker.setCursor('default'); + } + //}}} + function enableCrop() //{{{ + { + options.disabled = false; + interfaceUpdate(); + } + //}}} + function cancelCrop() //{{{ + { + Selection.done(); + Tracker.activateHandlers(null, null); + } + //}}} + function destroy() //{{{ + { + $div.remove(); + $origimg.show(); + $origimg.css('visibility','visible'); + $(obj).removeData('Jcrop'); + } + //}}} + function setImage(src, callback) //{{{ + { + Selection.release(); + disableCrop(); + var img = new Image(); + img.onload = function () { + var iw = img.width; + var ih = img.height; + var bw = options.boxWidth; + var bh = options.boxHeight; + $img.width(iw).height(ih); + $img.attr('src', src); + $img2.attr('src', src); + presize($img, bw, bh); + boundx = $img.width(); + boundy = $img.height(); + $img2.width(boundx).height(boundy); + $trk.width(boundx + (bound * 2)).height(boundy + (bound * 2)); + $div.width(boundx).height(boundy); + Shade.resize(boundx,boundy); + enableCrop(); + + if (typeof(callback) === 'function') { + callback.call(api); + } + }; + img.src = src; + } + //}}} + function colorChangeMacro($obj,color,now) { + var mycolor = color || options.bgColor; + if (options.bgFade && supportsColorFade() && options.fadeTime && !now) { + $obj.animate({ + backgroundColor: mycolor + }, { + queue: false, + duration: options.fadeTime + }); + } else { + $obj.css('backgroundColor', mycolor); + } + } + function interfaceUpdate(alt) //{{{ + // This method tweaks the interface based on options object. + // Called when options are changed and at end of initialization. + { + if (options.allowResize) { + if (alt) { + Selection.enableOnly(); + } else { + Selection.enableHandles(); + } + } else { + Selection.disableHandles(); + } + + Tracker.setCursor(options.allowSelect ? 'crosshair' : 'default'); + Selection.setCursor(options.allowMove ? 'move' : 'default'); + + if (options.hasOwnProperty('trueSize')) { + xscale = options.trueSize[0] / boundx; + yscale = options.trueSize[1] / boundy; + } + + if (options.hasOwnProperty('setSelect')) { + setSelect(options.setSelect); + Selection.done(); + delete(options.setSelect); + } + + Shade.refresh(); + + if (options.bgColor != bgcolor) { + colorChangeMacro( + options.shade? Shade.getShades(): $div, + options.shade? + (options.shadeColor || options.bgColor): + options.bgColor + ); + bgcolor = options.bgColor; + } + + if (bgopacity != options.bgOpacity) { + bgopacity = options.bgOpacity; + if (options.shade) Shade.refresh(); + else Selection.setBgOpacity(bgopacity); + } + + xlimit = options.maxSize[0] || 0; + ylimit = options.maxSize[1] || 0; + xmin = options.minSize[0] || 0; + ymin = options.minSize[1] || 0; + + if (options.hasOwnProperty('outerImage')) { + $img.attr('src', options.outerImage); + delete(options.outerImage); + } + + Selection.refresh(); + } + //}}} + //}}} + + if (Touch.support) $trk.bind('touchstart.jcrop', Touch.newSelection); + + $hdl_holder.hide(); + interfaceUpdate(true); + + var api = { + setImage: setImage, + animateTo: animateTo, + setSelect: setSelect, + setOptions: setOptionsNew, + tellSelect: tellSelect, + tellScaled: tellScaled, + setClass: setClass, + + disable: disableCrop, + enable: enableCrop, + cancel: cancelCrop, + release: Selection.release, + destroy: destroy, + + focus: KeyManager.watchKeys, + + getBounds: function () { + return [boundx * xscale, boundy * yscale]; + }, + getWidgetSize: function () { + return [boundx, boundy]; + }, + getScaleFactor: function () { + return [xscale, yscale]; + }, + getOptions: function() { + // careful: internal values are returned + return options; + }, + + ui: { + holder: $div, + selection: $sel + } + }; + + if (is_msie) $div.bind('selectstart', function () { return false; }); + + $origimg.data('Jcrop', api); + return api; + }; + $.fn.Jcrop = function (options, callback) //{{{ + { + var api; + // Iterate over each object, attach Jcrop + this.each(function () { + // If we've already attached to this object + if ($(this).data('Jcrop')) { + // The API can be requested this way (undocumented) + if (options === 'api') return $(this).data('Jcrop'); + // Otherwise, we just reset the options... + else $(this).data('Jcrop').setOptions(options); + } + // If we haven't been attached, preload and attach + else { + if (this.tagName == 'IMG') + $.Jcrop.Loader(this,function(){ + $(this).css({display:'block',visibility:'hidden'}); + api = $.Jcrop(this, options); + if ($.isFunction(callback)) callback.call(api); + }); + else { + $(this).css({display:'block',visibility:'hidden'}); + api = $.Jcrop(this, options); + if ($.isFunction(callback)) callback.call(api); + } + } + }); + + // Return "this" so the object is chainable (jQuery-style) + return this; + }; + //}}} + // $.Jcrop.Loader - basic image loader {{{ + + $.Jcrop.Loader = function(imgobj,success,error){ + var $img = $(imgobj), img = $img[0]; + + function completeCheck(){ + if (img.complete) { + $img.unbind('.jcloader'); + if ($.isFunction(success)) success.call(img); + } + else window.setTimeout(completeCheck,50); + } + + $img + .bind('load.jcloader',completeCheck) + .bind('error.jcloader',function(e){ + $img.unbind('.jcloader'); + if ($.isFunction(error)) error.call(img); + }); + + if (img.complete && $.isFunction(success)){ + $img.unbind('.jcloader'); + success.call(img); + } + }; + + //}}} + // Global Defaults {{{ + $.Jcrop.defaults = { + + // Basic Settings + allowSelect: true, + allowMove: true, + allowResize: true, + + trackDocument: true, + + // Styling Options + baseClass: 'jcrop', + addClass: null, + bgColor: 'black', + bgOpacity: 0.6, + bgFade: false, + borderOpacity: 0.4, + handleOpacity: 0.5, + handleSize: null, + + aspectRatio: 0, + keySupport: true, + createHandles: ['n','s','e','w','nw','ne','se','sw'], + createDragbars: ['n','s','e','w'], + createBorders: ['n','s','e','w'], + drawBorders: true, + dragEdges: true, + fixedSupport: true, + touchSupport: null, + + shade: null, + + boxWidth: 0, + boxHeight: 0, + boundary: 2, + fadeTime: 400, + animationDelay: 20, + swingSpeed: 3, + + minSelect: [0, 0], + maxSize: [0, 0], + minSize: [0, 0], + + // Callbacks / Event Handlers + onChange: function () {}, + onSelect: function () {}, + onDblClick: function () {}, + onRelease: function () {} + }; + + // }}} +}(jQuery)); diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.Jcrop.min.js b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.Jcrop.min.js new file mode 100755 index 0000000..4c9c7ad --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.Jcrop.min.js @@ -0,0 +1,22 @@ +/** + * jquery.Jcrop.min.js v0.9.12 (build:20130202) + * jQuery Image Cropping Plugin - released under MIT License + * Copyright (c) 2008-2013 Tapmodo Interactive LLC + * https://github.com/tapmodo/Jcrop + */ +(function(a){a.Jcrop=function(b,c){function i(a){return Math.round(a)+"px"}function j(a){return d.baseClass+"-"+a}function k(){return a.fx.step.hasOwnProperty("backgroundColor")}function l(b){var c=a(b).offset();return[c.left,c.top]}function m(a){return[a.pageX-e[0],a.pageY-e[1]]}function n(b){typeof b!="object"&&(b={}),d=a.extend(d,b),a.each(["onChange","onSelect","onRelease","onDblClick"],function(a,b){typeof d[b]!="function"&&(d[b]=function(){})})}function o(a,b,c){e=l(D),bc.setCursor(a==="move"?a:a+"-resize");if(a==="move")return bc.activateHandlers(q(b),v,c);var d=_.getFixed(),f=r(a),g=_.getCorner(r(f));_.setPressed(_.getCorner(f)),_.setCurrent(g),bc.activateHandlers(p(a,d),v,c)}function p(a,b){return function(c){if(!d.aspectRatio)switch(a){case"e":c[1]=b.y2;break;case"w":c[1]=b.y2;break;case"n":c[0]=b.x2;break;case"s":c[0]=b.x2}else switch(a){case"e":c[1]=b.y+1;break;case"w":c[1]=b.y+1;break;case"n":c[0]=b.x+1;break;case"s":c[0]=b.x+1}_.setCurrent(c),bb.update()}}function q(a){var b=a;return bd.watchKeys +(),function(a){_.moveOffset([a[0]-b[0],a[1]-b[1]]),b=a,bb.update()}}function r(a){switch(a){case"n":return"sw";case"s":return"nw";case"e":return"nw";case"w":return"ne";case"ne":return"sw";case"nw":return"se";case"se":return"nw";case"sw":return"ne"}}function s(a){return function(b){return d.disabled?!1:a==="move"&&!d.allowMove?!1:(e=l(D),W=!0,o(a,m(b)),b.stopPropagation(),b.preventDefault(),!1)}}function t(a,b,c){var d=a.width(),e=a.height();d>b&&b>0&&(d=b,e=b/a.width()*a.height()),e>c&&c>0&&(e=c,d=c/a.height()*a.width()),T=a.width()/d,U=a.height()/e,a.width(d).height(e)}function u(a){return{x:a.x*T,y:a.y*U,x2:a.x2*T,y2:a.y2*U,w:a.w*T,h:a.h*U}}function v(a){var b=_.getFixed();b.w>d.minSelect[0]&&b.h>d.minSelect[1]?(bb.enableHandles(),bb.done()):bb.release(),bc.setCursor(d.allowSelect?"crosshair":"default")}function w(a){if(d.disabled)return!1;if(!d.allowSelect)return!1;W=!0,e=l(D),bb.disableHandles(),bc.setCursor("crosshair");var b=m(a);return _.setPressed(b),bb.update(),bc.activateHandlers(x,v,a.type.substring +(0,5)==="touch"),bd.watchKeys(),a.stopPropagation(),a.preventDefault(),!1}function x(a){_.setCurrent(a),bb.update()}function y(){var b=a("
").addClass(j("tracker"));return g&&b.css({opacity:0,backgroundColor:"white"}),b}function be(a){G.removeClass().addClass(j("holder")).addClass(a)}function bf(a,b){function t(){window.setTimeout(u,l)}var c=a[0]/T,e=a[1]/U,f=a[2]/T,g=a[3]/U;if(X)return;var h=_.flipCoords(c,e,f,g),i=_.getFixed(),j=[i.x,i.y,i.x2,i.y2],k=j,l=d.animationDelay,m=h[0]-j[0],n=h[1]-j[1],o=h[2]-j[2],p=h[3]-j[3],q=0,r=d.swingSpeed;c=k[0],e=k[1],f=k[2],g=k[3],bb.animMode(!0);var s,u=function(){return function(){q+=(100-q)/r,k[0]=Math.round(c+q/100*m),k[1]=Math.round(e+q/100*n),k[2]=Math.round(f+q/100*o),k[3]=Math.round(g+q/100*p),q>=99.8&&(q=100),q<100?(bh(k),t()):(bb.done(),bb.animMode(!1),typeof b=="function"&&b.call(bs))}}();t()}function bg(a){bh([a[0]/T,a[1]/U,a[2]/T,a[3]/U]),d.onSelect.call(bs,u(_.getFixed())),bb.enableHandles()}function bh(a){_.setPressed([a[0],a[1]]),_.setCurrent([a[2], +a[3]]),bb.update()}function bi(){return u(_.getFixed())}function bj(){return _.getFixed()}function bk(a){n(a),br()}function bl(){d.disabled=!0,bb.disableHandles(),bb.setCursor("default"),bc.setCursor("default")}function bm(){d.disabled=!1,br()}function bn(){bb.done(),bc.activateHandlers(null,null)}function bo(){G.remove(),A.show(),A.css("visibility","visible"),a(b).removeData("Jcrop")}function bp(a,b){bb.release(),bl();var c=new Image;c.onload=function(){var e=c.width,f=c.height,g=d.boxWidth,h=d.boxHeight;D.width(e).height(f),D.attr("src",a),H.attr("src",a),t(D,g,h),E=D.width(),F=D.height(),H.width(E).height(F),M.width(E+L*2).height(F+L*2),G.width(E).height(F),ba.resize(E,F),bm(),typeof b=="function"&&b.call(bs)},c.src=a}function bq(a,b,c){var e=b||d.bgColor;d.bgFade&&k()&&d.fadeTime&&!c?a.animate({backgroundColor:e},{queue:!1,duration:d.fadeTime}):a.css("backgroundColor",e)}function br(a){d.allowResize?a?bb.enableOnly():bb.enableHandles():bb.disableHandles(),bc.setCursor(d.allowSelect?"crosshair":"default"),bb +.setCursor(d.allowMove?"move":"default"),d.hasOwnProperty("trueSize")&&(T=d.trueSize[0]/E,U=d.trueSize[1]/F),d.hasOwnProperty("setSelect")&&(bg(d.setSelect),bb.done(),delete d.setSelect),ba.refresh(),d.bgColor!=N&&(bq(d.shade?ba.getShades():G,d.shade?d.shadeColor||d.bgColor:d.bgColor),N=d.bgColor),O!=d.bgOpacity&&(O=d.bgOpacity,d.shade?ba.refresh():bb.setBgOpacity(O)),P=d.maxSize[0]||0,Q=d.maxSize[1]||0,R=d.minSize[0]||0,S=d.minSize[1]||0,d.hasOwnProperty("outerImage")&&(D.attr("src",d.outerImage),delete d.outerImage),bb.refresh()}var d=a.extend({},a.Jcrop.defaults),e,f=navigator.userAgent.toLowerCase(),g=/msie/.test(f),h=/msie [1-6]\./.test(f);typeof b!="object"&&(b=a(b)[0]),typeof c!="object"&&(c={}),n(c);var z={border:"none",visibility:"visible",margin:0,padding:0,position:"absolute",top:0,left:0},A=a(b),B=!0;if(b.tagName=="IMG"){if(A[0].width!=0&&A[0].height!=0)A.width(A[0].width),A.height(A[0].height);else{var C=new Image;C.src=A[0].src,A.width(C.width),A.height(C.height)}var D=A.clone().removeAttr("id"). +css(z).show();D.width(A.width()),D.height(A.height()),A.after(D).hide()}else D=A.css(z).show(),B=!1,d.shade===null&&(d.shade=!0);t(D,d.boxWidth,d.boxHeight);var E=D.width(),F=D.height(),G=a("
").width(E).height(F).addClass(j("holder")).css({position:"relative",backgroundColor:d.bgColor}).insertAfter(A).append(D);d.addClass&&G.addClass(d.addClass);var H=a("
"),I=a("
").width("100%").height("100%").css({zIndex:310,position:"absolute",overflow:"hidden"}),J=a("
").width("100%").height("100%").css("zIndex",320),K=a("
").css({position:"absolute",zIndex:600}).dblclick(function(){var a=_.getFixed();d.onDblClick.call(bs,a)}).insertBefore(D).append(I,J);B&&(H=a("").attr("src",D.attr("src")).css(z).width(E).height(F),I.append(H)),h&&K.css({overflowY:"hidden"});var L=d.boundary,M=y().width(E+L*2).height(F+L*2).css({position:"absolute",top:i(-L),left:i(-L),zIndex:290}).mousedown(w),N=d.bgColor,O=d.bgOpacity,P,Q,R,S,T,U,V=!0,W,X,Y;e=l(D);var Z=function(){function a(){var a={},b=["touchstart" +,"touchmove","touchend"],c=document.createElement("div"),d;try{for(d=0;da+f&&(f-=f+a),0>b+g&&(g-=g+b),FE&&(r=E,u=Math.abs((r-a)/f),s=k<0?b-u:u+b)):(r=c,u=l/f,s=k<0?b-u:b+u,s<0?(s=0,t=Math.abs((s-b)*f),r=j<0?a-t:t+a):s>F&&(s=F,t=Math.abs(s-b)*f,r=j<0?a-t:t+a)),r>a?(r-ah&&(r=a+h),s>b?s=b+(r-a)/f:s=b-(r-a)/f):rh&&(r=a-h),s>b?s=b+(a-r)/f:s=b-(a-r)/f),r<0?(a-=r,r=0):r>E&&(a-=r-E,r=E),s<0?(b-=s,s=0):s>F&&(b-=s-F,s=F),q(o(a,b,r,s))}function n(a){return a[0]<0&&(a[0]=0),a[1]<0&&(a[1]=0),a[0]>E&&(a[0]=E),a[1]>F&&(a[1]=F),[Math.round(a[0]),Math.round(a[1])]}function o(a,b,c,d){var e=a,f=c,g=b,h=d;return cP&&(c=d>0?a+P:a-P),Q&&Math.abs +(f)>Q&&(e=f>0?b+Q:b-Q),S/U&&Math.abs(f)0?b+S/U:b-S/U),R/T&&Math.abs(d)0?a+R/T:a-R/T),a<0&&(c-=a,a-=a),b<0&&(e-=b,b-=b),c<0&&(a-=c,c-=c),e<0&&(b-=e,e-=e),c>E&&(g=c-E,a-=g,c-=g),e>F&&(g=e-F,b-=g,e-=g),a>E&&(g=a-F,e-=g,b-=g),b>F&&(g=b-F,e-=g,b-=g),q(o(a,b,c,e))}function q(a){return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]}}var a=0,b=0,c=0,e=0,f,g;return{flipCoords:o,setPressed:h,setCurrent:i,getOffset:j,moveOffset:k,getCorner:l,getFixed:m}}(),ba=function(){function f(a,b){e.left.css({height:i(b)}),e.right.css({height:i(b)})}function g(){return h(_.getFixed())}function h(a){e.top.css({left:i(a.x),width:i(a.w),height:i(a.y)}),e.bottom.css({top:i(a.y2),left:i(a.x),width:i(a.w),height:i(F-a.y2)}),e.right.css({left:i(a.x2),width:i(E-a.x2)}),e.left.css({width:i(a.x)})}function j(){return a("
").css({position:"absolute",backgroundColor:d.shadeColor||d.bgColor}).appendTo(c)}function k(){b||(b=!0,c.insertBefore(D),g(),bb.setBgOpacity(1,0,1),H.hide(),l(d.shadeColor||d.bgColor,1),bb. +isAwake()?n(d.bgOpacity,1):n(1,1))}function l(a,b){bq(p(),a,b)}function m(){b&&(c.remove(),H.show(),b=!1,bb.isAwake()?bb.setBgOpacity(d.bgOpacity,1,1):(bb.setBgOpacity(1,1,1),bb.disableHandles()),bq(G,0,1))}function n(a,e){b&&(d.bgFade&&!e?c.animate({opacity:1-a},{queue:!1,duration:d.fadeTime}):c.css({opacity:1-a}))}function o(){d.shade?k():m(),bb.isAwake()&&n(d.bgOpacity)}function p(){return c.children()}var b=!1,c=a("
").css({position:"absolute",zIndex:240,opacity:0}),e={top:j(),left:j().height(F),right:j().height(F),bottom:j()};return{update:g,updateRaw:h,getShades:p,setBgColor:l,enable:k,disable:m,resize:f,refresh:o,opacity:n}}(),bb=function(){function k(b){var c=a("
").css({position:"absolute",opacity:d.borderOpacity}).addClass(j(b));return I.append(c),c}function l(b,c){var d=a("
").mousedown(s(b)).css({cursor:b+"-resize",position:"absolute",zIndex:c}).addClass("ord-"+b);return Z.support&&d.bind("touchstart.jcrop",Z.createDragger(b)),J.append(d),d}function m(a){var b=d.handleSize,e=l(a,c++ +).css({opacity:d.handleOpacity}).addClass(j("handle"));return b&&e.width(b).height(b),e}function n(a){return l(a,c++).addClass("jcrop-dragbar")}function o(a){var b;for(b=0;b').css({position:"fixed",left:"-120px",width:"12px"}).addClass("jcrop-keymgr"),c=a("
").css({position:"absolute",overflow:"hidden"}).append(b);return d.keySupport&&(b.keydown(i).blur(f),h||!d.fixedSupport?(b.css({position:"absolute",left:"-20px"}),c.append(b).insertBefore(D)):b.insertBefore(D)),{watchKeys:e}}();Z.support&&M.bind("touchstart.jcrop",Z.newSelection),J.hide(),br(!0);var bs={setImage:bp,animateTo:bf,setSelect:bg,setOptions:bk,tellSelect:bi,tellScaled:bj,setClass:be,disable:bl,enable:bm,cancel:bn,release:bb.release,destroy:bo,focus:bd.watchKeys,getBounds:function(){return[E*T,F*U]},getWidgetSize:function(){return[E,F]},getScaleFactor:function(){return[T,U]},getOptions:function(){return d},ui:{holder:G,selection:K}};return g&&G.bind("selectstart",function(){return!1}),A.data("Jcrop",bs),bs},a.fn.Jcrop=function(b,c){var d;return this.each(function(){if(a(this).data("Jcrop")){if( +b==="api")return a(this).data("Jcrop");a(this).data("Jcrop").setOptions(b)}else this.tagName=="IMG"?a.Jcrop.Loader(this,function(){a(this).css({display:"block",visibility:"hidden"}),d=a.Jcrop(this,b),a.isFunction(c)&&c.call(d)}):(a(this).css({display:"block",visibility:"hidden"}),d=a.Jcrop(this,b),a.isFunction(c)&&c.call(d))}),this},a.Jcrop.Loader=function(b,c,d){function g(){f.complete?(e.unbind(".jcloader"),a.isFunction(c)&&c.call(f)):window.setTimeout(g,50)}var e=a(b),f=e[0];e.bind("load.jcloader",g).bind("error.jcloader",function(b){e.unbind(".jcloader"),a.isFunction(d)&&d.call(f)}),f.complete&&a.isFunction(c)&&(e.unbind(".jcloader"),c.call(f))},a.Jcrop.defaults={allowSelect:!0,allowMove:!0,allowResize:!0,trackDocument:!0,baseClass:"jcrop",addClass:null,bgColor:"black",bgOpacity:.6,bgFade:!1,borderOpacity:.4,handleOpacity:.5,handleSize:null,aspectRatio:0,keySupport:!0,createHandles:["n","s","e","w","nw","ne","se","sw"],createDragbars:["n","s","e","w"],createBorders:["n","s","e","w"],drawBorders:!0,dragEdges +:!0,fixedSupport:!0,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}}})(jQuery); \ No newline at end of file diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.color.js b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.color.js new file mode 100755 index 0000000..3ca61fb --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.color.js @@ -0,0 +1,661 @@ +/*! + * jQuery Color Animations v2.0pre + * http://jquery.org/ + * + * Copyright 2011 John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + */ + +(function( jQuery, undefined ){ + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color outlineColor".split(" "), + + // plusequals test for += 100 -= 100 + rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, + // a set of RE's that can match strings and generate color tuples. + stringParsers = [{ + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ], + execResult[ 3 ], + execResult[ 4 ] + ]; + } + }, { + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + 2.55 * execResult[1], + 2.55 * execResult[2], + 2.55 * execResult[3], + execResult[ 4 ] + ]; + } + }, { + re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ], 16 ) + ]; + } + }, { + re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) + ]; + } + }, { + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + space: "hsla", + parse: function( execResult ) { + return [ + execResult[1], + execResult[2] / 100, + execResult[3] / 100, + execResult[4] + ]; + } + }], + + // jQuery.Color( ) + color = jQuery.Color = function( color, green, blue, alpha ) { + return new jQuery.Color.fn.parse( color, green, blue, alpha ); + }, + spaces = { + rgba: { + cache: "_rgba", + props: { + red: { + idx: 0, + type: "byte", + empty: true + }, + green: { + idx: 1, + type: "byte", + empty: true + }, + blue: { + idx: 2, + type: "byte", + empty: true + }, + alpha: { + idx: 3, + type: "percent", + def: 1 + } + } + }, + hsla: { + cache: "_hsla", + props: { + hue: { + idx: 0, + type: "degrees", + empty: true + }, + saturation: { + idx: 1, + type: "percent", + empty: true + }, + lightness: { + idx: 2, + type: "percent", + empty: true + } + } + } + }, + propTypes = { + "byte": { + floor: true, + min: 0, + max: 255 + }, + "percent": { + min: 0, + max: 1 + }, + "degrees": { + mod: 360, + floor: true + } + }, + rgbaspace = spaces.rgba.props, + support = color.support = {}, + + // colors = jQuery.Color.names + colors, + + // local aliases of functions called often + each = jQuery.each; + + spaces.hsla.props.alpha = rgbaspace.alpha; + + function clamp( value, prop, alwaysAllowEmpty ) { + var type = propTypes[ prop.type ] || {}, + allowEmpty = prop.empty || alwaysAllowEmpty; + + if ( allowEmpty && value == null ) { + return null; + } + if ( prop.def && value == null ) { + return prop.def; + } + if ( type.floor ) { + value = ~~value; + } else { + value = parseFloat( value ); + } + if ( value == null || isNaN( value ) ) { + return prop.def; + } + if ( type.mod ) { + value = value % type.mod; + // -10 -> 350 + return value < 0 ? type.mod + value : value; + } + + // for now all property types without mod have min and max + return type.min > value ? type.min : type.max < value ? type.max : value; + } + + function stringParse( string ) { + var inst = color(), + rgba = inst._rgba = []; + + string = string.toLowerCase(); + + each( stringParsers, function( i, parser ) { + var match = parser.re.exec( string ), + values = match && parser.parse( match ), + parsed, + spaceName = parser.space || "rgba", + cache = spaces[ spaceName ].cache; + + + if ( values ) { + parsed = inst[ spaceName ]( values ); + + // if this was an rgba parse the assignment might happen twice + // oh well.... + inst[ cache ] = parsed[ cache ]; + rgba = inst._rgba = parsed._rgba; + + // exit each( stringParsers ) here because we matched + return false; + } + }); + + // Found a stringParser that handled it + if ( rgba.length !== 0 ) { + + // if this came from a parsed string, force "transparent" when alpha is 0 + // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) + if ( Math.max.apply( Math, rgba ) === 0 ) { + jQuery.extend( rgba, colors.transparent ); + } + return inst; + } + + // named colors / default - filter back through parse function + if ( string = colors[ string ] ) { + return string; + } + } + + color.fn = color.prototype = { + constructor: color, + parse: function( red, green, blue, alpha ) { + if ( red === undefined ) { + this._rgba = [ null, null, null, null ]; + return this; + } + if ( red instanceof jQuery || red.nodeType ) { + red = red instanceof jQuery ? red.css( green ) : jQuery( red ).css( green ); + green = undefined; + } + + var inst = this, + type = jQuery.type( red ), + rgba = this._rgba = [], + source; + + // more than 1 argument specified - assume ( red, green, blue, alpha ) + if ( green !== undefined ) { + red = [ red, green, blue, alpha ]; + type = "array"; + } + + if ( type === "string" ) { + return this.parse( stringParse( red ) || colors._default ); + } + + if ( type === "array" ) { + each( rgbaspace, function( key, prop ) { + rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); + }); + return this; + } + + if ( type === "object" ) { + if ( red instanceof color ) { + each( spaces, function( spaceName, space ) { + if ( red[ space.cache ] ) { + inst[ space.cache ] = red[ space.cache ].slice(); + } + }); + } else { + each( spaces, function( spaceName, space ) { + each( space.props, function( key, prop ) { + var cache = space.cache; + + // if the cache doesn't exist, and we know how to convert + if ( !inst[ cache ] && space.to ) { + + // if the value was null, we don't need to copy it + // if the key was alpha, we don't need to copy it either + if ( red[ key ] == null || key === "alpha") { + return; + } + inst[ cache ] = space.to( inst._rgba ); + } + + // this is the only case where we allow nulls for ALL properties. + // call clamp with alwaysAllowEmpty + inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); + }); + }); + } + return this; + } + }, + is: function( compare ) { + var is = color( compare ), + same = true, + myself = this; + + each( spaces, function( _, space ) { + var isCache = is[ space.cache ], + localCache; + if (isCache) { + localCache = myself[ space.cache ] || space.to && space.to( myself._rgba ) || []; + each( space.props, function( _, prop ) { + if ( isCache[ prop.idx ] != null ) { + same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); + return same; + } + }); + } + return same; + }); + return same; + }, + _space: function() { + var used = [], + inst = this; + each( spaces, function( spaceName, space ) { + if ( inst[ space.cache ] ) { + used.push( spaceName ); + } + }); + return used.pop(); + }, + transition: function( other, distance ) { + var end = color( other ), + spaceName = end._space(), + space = spaces[ spaceName ], + start = this[ space.cache ] || space.to( this._rgba ), + result = start.slice(); + + end = end[ space.cache ]; + each( space.props, function( key, prop ) { + var index = prop.idx, + startValue = start[ index ], + endValue = end[ index ], + type = propTypes[ prop.type ] || {}; + + // if null, don't override start value + if ( endValue === null ) { + return; + } + // if null - use end + if ( startValue === null ) { + result[ index ] = endValue; + } else { + if ( type.mod ) { + if ( endValue - startValue > type.mod / 2 ) { + startValue += type.mod; + } else if ( startValue - endValue > type.mod / 2 ) { + startValue -= type.mod; + } + } + result[ prop.idx ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); + } + }); + return this[ spaceName ]( result ); + }, + blend: function( opaque ) { + // if we are already opaque - return ourself + if ( this._rgba[ 3 ] === 1 ) { + return this; + } + + var rgb = this._rgba.slice(), + a = rgb.pop(), + blend = color( opaque )._rgba; + + return color( jQuery.map( rgb, function( v, i ) { + return ( 1 - a ) * blend[ i ] + a * v; + })); + }, + toRgbaString: function() { + var prefix = "rgba(", + rgba = jQuery.map( this._rgba, function( v, i ) { + return v == null ? ( i > 2 ? 1 : 0 ) : v; + }); + + if ( rgba[ 3 ] === 1 ) { + rgba.pop(); + prefix = "rgb("; + } + + return prefix + rgba.join(",") + ")"; + }, + toHslaString: function() { + var prefix = "hsla(", + hsla = jQuery.map( this.hsla(), function( v, i ) { + if ( v == null ) { + v = i > 2 ? 1 : 0; + } + + // catch 1 and 2 + if ( i && i < 3 ) { + v = Math.round( v * 100 ) + "%"; + } + return v; + }); + + if ( hsla[ 3 ] === 1 ) { + hsla.pop(); + prefix = "hsl("; + } + return prefix + hsla.join(",") + ")"; + }, + toHexString: function( includeAlpha ) { + var rgba = this._rgba.slice(), + alpha = rgba.pop(); + + if ( includeAlpha ) { + rgba.push( ~~( alpha * 255 ) ); + } + + return "#" + jQuery.map( rgba, function( v, i ) { + + // default to 0 when nulls exist + v = ( v || 0 ).toString( 16 ); + return v.length === 1 ? "0" + v : v; + }).join(""); + }, + toString: function() { + return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + } + }; + color.fn.parse.prototype = color.fn; + + // hsla conversions adapted from: + // http://www.google.com/codesearch/p#OAMlx_jo-ck/src/third_party/WebKit/Source/WebCore/inspector/front-end/Color.js&d=7&l=193 + + function hue2rgb( p, q, h ) { + h = ( h + 1 ) % 1; + if ( h * 6 < 1 ) { + return p + (q - p) * 6 * h; + } + if ( h * 2 < 1) { + return q; + } + if ( h * 3 < 2 ) { + return p + (q - p) * ((2/3) - h) * 6; + } + return p; + } + + spaces.hsla.to = function ( rgba ) { + if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { + return [ null, null, null, rgba[ 3 ] ]; + } + var r = rgba[ 0 ] / 255, + g = rgba[ 1 ] / 255, + b = rgba[ 2 ] / 255, + a = rgba[ 3 ], + max = Math.max( r, g, b ), + min = Math.min( r, g, b ), + diff = max - min, + add = max + min, + l = add * 0.5, + h, s; + + if ( min === max ) { + h = 0; + } else if ( r === max ) { + h = ( 60 * ( g - b ) / diff ) + 360; + } else if ( g === max ) { + h = ( 60 * ( b - r ) / diff ) + 120; + } else { + h = ( 60 * ( r - g ) / diff ) + 240; + } + + if ( l === 0 || l === 1 ) { + s = l; + } else if ( l <= 0.5 ) { + s = diff / add; + } else { + s = diff / ( 2 - add ); + } + return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; + }; + + spaces.hsla.from = function ( hsla ) { + if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { + return [ null, null, null, hsla[ 3 ] ]; + } + var h = hsla[ 0 ] / 360, + s = hsla[ 1 ], + l = hsla[ 2 ], + a = hsla[ 3 ], + q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, + p = 2 * l - q, + r, g, b; + + return [ + Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), + Math.round( hue2rgb( p, q, h ) * 255 ), + Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), + a + ]; + }; + + + each( spaces, function( spaceName, space ) { + var props = space.props, + cache = space.cache, + to = space.to, + from = space.from; + + // makes rgba() and hsla() + color.fn[ spaceName ] = function( value ) { + + // generate a cache for this space if it doesn't exist + if ( to && !this[ cache ] ) { + this[ cache ] = to( this._rgba ); + } + if ( value === undefined ) { + return this[ cache ].slice(); + } + + var type = jQuery.type( value ), + arr = ( type === "array" || type === "object" ) ? value : arguments, + local = this[ cache ].slice(), + ret; + + each( props, function( key, prop ) { + var val = arr[ type === "object" ? key : prop.idx ]; + if ( val == null ) { + val = local[ prop.idx ]; + } + local[ prop.idx ] = clamp( val, prop ); + }); + + if ( from ) { + ret = color( from( local ) ); + ret[ cache ] = local; + return ret; + } else { + return color( local ); + } + }; + + // makes red() green() blue() alpha() hue() saturation() lightness() + each( props, function( key, prop ) { + // alpha is included in more than one space + if ( color.fn[ key ] ) { + return; + } + color.fn[ key ] = function( value ) { + var vtype = jQuery.type( value ), + fn = ( key === 'alpha' ? ( this._hsla ? 'hsla' : 'rgba' ) : spaceName ), + local = this[ fn ](), + cur = local[ prop.idx ], + match; + + if ( vtype === "undefined" ) { + return cur; + } + + if ( vtype === "function" ) { + value = value.call( this, cur ); + vtype = jQuery.type( value ); + } + if ( value == null && prop.empty ) { + return this; + } + if ( vtype === "string" ) { + match = rplusequals.exec( value ); + if ( match ) { + value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); + } + } + local[ prop.idx ] = value; + return this[ fn ]( local ); + }; + }); + }); + + // add .fx.step functions + each( stepHooks, function( i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, backgroundColor, curElem; + + if ( jQuery.type( value ) !== 'string' || ( parsed = stringParse( value ) ) ) + { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + do { + backgroundColor = jQuery.curCSS( curElem, "backgroundColor" ); + } while ( + ( backgroundColor === "" || backgroundColor === "transparent" ) && + ( curElem = curElem.parentNode ) && + curElem.style + ); + + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); + } + + value = value.toRgbaString(); + } + elem.style[ hook ] = value; + } + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; + } + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; + }); + + // detect rgba support + jQuery(function() { + var div = document.createElement( "div" ), + div_style = div.style; + + div_style.cssText = "background-color:rgba(1,1,1,.5)"; + support.rgba = div_style.backgroundColor.indexOf( "rgba" ) > -1; + }); + + // Some named colors to work with + // From Interface by Stefan Petre + // http://interface.eyecon.ro/ + colors = jQuery.Color.names = { + aqua: "#00ffff", + azure: "#f0ffff", + beige: "#f5f5dc", + black: "#000000", + blue: "#0000ff", + brown: "#a52a2a", + cyan: "#00ffff", + darkblue: "#00008b", + darkcyan: "#008b8b", + darkgrey: "#a9a9a9", + darkgreen: "#006400", + darkkhaki: "#bdb76b", + darkmagenta: "#8b008b", + darkolivegreen: "#556b2f", + darkorange: "#ff8c00", + darkorchid: "#9932cc", + darkred: "#8b0000", + darksalmon: "#e9967a", + darkviolet: "#9400d3", + fuchsia: "#ff00ff", + gold: "#ffd700", + green: "#008000", + indigo: "#4b0082", + khaki: "#f0e68c", + lightblue: "#add8e6", + lightcyan: "#e0ffff", + lightgreen: "#90ee90", + lightgrey: "#d3d3d3", + lightpink: "#ffb6c1", + lightyellow: "#ffffe0", + lime: "#00ff00", + magenta: "#ff00ff", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + orange: "#ffa500", + pink: "#ffc0cb", + purple: "#800080", + violet: "#800080", + red: "#ff0000", + silver: "#c0c0c0", + white: "#ffffff", + yellow: "#ffff00", + transparent: [ null, null, null, 0 ], + _default: "#ffffff" + }; +})( jQuery ); diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js old mode 100644 new mode 100755 index fd2948f..e08df3f --- a/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/jquery.ui.widget.js @@ -1,36 +1,58 @@ -/* - * jQuery UI Widget 1.10.1+amd - * https://github.com/blueimp/jQuery-File-Upload +/*! jQuery UI - v1.11.4+CommonJS - 2015-08-28 +* http://jqueryui.com +* Includes: widget.js +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define([ "jquery" ], factory ); + + } else if ( typeof exports === "object" ) { + + // Node/CommonJS + factory( require( "jquery" ) ); + + } else { + + // Browser globals + factory( jQuery ); + } +}(function( $ ) { +/*! + * jQuery UI Widget 1.11.4 + * http://jqueryui.com * - * Copyright 2013 jQuery Foundation and other contributors + * Copyright jQuery Foundation and other contributors * Released under the MIT license. * http://jquery.org/license * * http://api.jqueryui.com/jQuery.widget/ */ -(function (factory) { - if (typeof define === "function" && define.amd) { - // Register as an anonymous AMD module: - define(["jquery"], factory); - } else { - // Browser globals: - factory(jQuery); - } -}(function( $, undefined ) { - -var uuid = 0, - slice = Array.prototype.slice, - _cleanData = $.cleanData; -$.cleanData = function( elems ) { - for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { - try { - $( elem ).triggerHandler( "remove" ); - // http://bugs.jquery.com/ticket/8235 - } catch( e ) {} - } - _cleanData( elems ); -}; + +var widget_uuid = 0, + widget_slice = Array.prototype.slice; + +$.cleanData = (function( orig ) { + return function( elems ) { + var events, elem, i; + for ( i = 0; (elem = elems[i]) != null; i++ ) { + try { + + // Only trigger remove when necessary to save time + events = $._data( elem, "events" ); + if ( events && events.remove ) { + $( elem ).triggerHandler( "remove" ); + } + + // http://bugs.jquery.com/ticket/8235 + } catch ( e ) {} + } + orig( elems ); + }; +})( $.cleanData ); $.widget = function( name, base, prototype ) { var fullName, existingConstructor, constructor, basePrototype, @@ -115,7 +137,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, @@ -143,10 +165,12 @@ $.widget = function( name, base, prototype ) { } $.widget.bridge( name, constructor ); + + return constructor; }; $.widget.extend = function( target ) { - var input = slice.call( arguments, 1 ), + var input = widget_slice.call( arguments, 1 ), inputIndex = 0, inputLength = input.length, key, @@ -175,18 +199,17 @@ $.widget.bridge = function( name, object ) { var fullName = object.prototype.widgetFullName || name; $.fn[ name ] = function( options ) { var isMethodCall = typeof options === "string", - args = slice.call( arguments, 1 ), + args = widget_slice.call( arguments, 1 ), returnValue = this; - // allow multiple hashes to be passed on init - options = !isMethodCall && args.length ? - $.widget.extend.apply( null, [ options ].concat(args) ) : - options; - if ( isMethodCall ) { this.each(function() { var methodValue, instance = $.data( this, fullName ); + if ( options === "instance" ) { + returnValue = instance; + return false; + } if ( !instance ) { return $.error( "cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'" ); @@ -203,10 +226,19 @@ $.widget.bridge = function( name, object ) { } }); } else { + + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat(args) ); + } + this.each(function() { var instance = $.data( this, fullName ); if ( instance ) { - instance.option( options || {} )._init(); + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } } else { $.data( this, fullName, new object( options, this ) ); } @@ -233,12 +265,8 @@ $.Widget.prototype = { _createWidget: function( options, element ) { element = $( element || this.defaultElement || this )[ 0 ]; this.element = $( element ); - this.uuid = uuid++; + this.uuid = widget_uuid++; this.eventNamespace = "." + this.widgetName + this.uuid; - this.options = $.widget.extend( {}, - this.options, - this._getCreateOptions(), - options ); this.bindings = $(); this.hoverable = $(); @@ -261,6 +289,11 @@ $.Widget.prototype = { this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); } + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + this._create(); this._trigger( "create", null, this._getCreateEventData() ); this._init(); @@ -276,9 +309,6 @@ $.Widget.prototype = { // all event bindings should go through this._on() this.element .unbind( this.eventNamespace ) - // 1.9 BC for #7810 - // TODO remove dual storage - .removeData( this.widgetName ) .removeData( this.widgetFullName ) // support: jquery <1.6.3 // http://bugs.jquery.com/ticket/9413 @@ -324,12 +354,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; @@ -354,20 +384,23 @@ $.Widget.prototype = { if ( key === "disabled" ) { this.widget() - .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) - .attr( "aria-disabled", value ); - this.hoverable.removeClass( "ui-state-hover" ); - this.focusable.removeClass( "ui-state-focus" ); + .toggleClass( this.widgetFullName + "-disabled", !!value ); + + // If the widget is becoming disabled, then nothing is interactive + if ( value ) { + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + } } return this; }, enable: function() { - return this._setOption( "disabled", false ); + return this._setOptions({ disabled: false }); }, disable: function() { - return this._setOption( "disabled", true ); + return this._setOptions({ disabled: true }); }, _on: function( suppressDisabledCheck, element, handlers ) { @@ -387,7 +420,6 @@ $.Widget.prototype = { element = this.element; delegateElement = this.widget(); } else { - // accept selectors, DOM elements element = delegateElement = $( element ); this.bindings = this.bindings.add( element ); } @@ -412,7 +444,7 @@ $.Widget.prototype = { handler.guid || handlerProxy.guid || $.guid++; } - var match = event.match( /^(\w+)\s*(.*)$/ ), + var match = event.match( /^([\w:-]*)\s*(.*)$/ ), eventName = match[1] + instance.eventNamespace, selector = match[2]; if ( selector ) { @@ -424,8 +456,14 @@ $.Widget.prototype = { }, _off: function( element, eventName ) { - eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + + this.eventNamespace; element.unbind( eventName ).undelegate( eventName ); + + // Clear the stack to avoid memory leaks (#10056) + this.bindings = $( this.bindings.not( element ).get() ); + this.focusable = $( this.focusable.not( element ).get() ); + this.hoverable = $( this.hoverable.not( element ).get() ); }, _delay: function( handler, delay ) { @@ -527,4 +565,8 @@ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { }; }); +var widget = $.widget; + + + })); diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-exif-map.js b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-exif-map.js new file mode 100755 index 0000000..96182e5 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-exif-map.js @@ -0,0 +1,384 @@ +/* + * JavaScript Load Image Exif Map + * https://github.com/blueimp/JavaScript-Load-Image + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Exif tags mapping based on + * https://github.com/jseidelin/exif-js + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*global define, module, require, window */ + +;(function (factory) { + 'use strict' + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['./load-image', './load-image-exif'], factory) + } else if (typeof module === 'object' && module.exports) { + factory(require('./load-image'), require('./load-image-exif')) + } else { + // Browser globals: + factory(window.loadImage) + } +}(function (loadImage) { + 'use strict' + + loadImage.ExifMap.prototype.tags = { + // ================= + // TIFF tags (IFD0): + // ================= + 0x0100: 'ImageWidth', + 0x0101: 'ImageHeight', + 0x8769: 'ExifIFDPointer', + 0x8825: 'GPSInfoIFDPointer', + 0xA005: 'InteroperabilityIFDPointer', + 0x0102: 'BitsPerSample', + 0x0103: 'Compression', + 0x0106: 'PhotometricInterpretation', + 0x0112: 'Orientation', + 0x0115: 'SamplesPerPixel', + 0x011C: 'PlanarConfiguration', + 0x0212: 'YCbCrSubSampling', + 0x0213: 'YCbCrPositioning', + 0x011A: 'XResolution', + 0x011B: 'YResolution', + 0x0128: 'ResolutionUnit', + 0x0111: 'StripOffsets', + 0x0116: 'RowsPerStrip', + 0x0117: 'StripByteCounts', + 0x0201: 'JPEGInterchangeFormat', + 0x0202: 'JPEGInterchangeFormatLength', + 0x012D: 'TransferFunction', + 0x013E: 'WhitePoint', + 0x013F: 'PrimaryChromaticities', + 0x0211: 'YCbCrCoefficients', + 0x0214: 'ReferenceBlackWhite', + 0x0132: 'DateTime', + 0x010E: 'ImageDescription', + 0x010F: 'Make', + 0x0110: 'Model', + 0x0131: 'Software', + 0x013B: 'Artist', + 0x8298: 'Copyright', + // ================== + // Exif Sub IFD tags: + // ================== + 0x9000: 'ExifVersion', // EXIF version + 0xA000: 'FlashpixVersion', // Flashpix format version + 0xA001: 'ColorSpace', // Color space information tag + 0xA002: 'PixelXDimension', // Valid width of meaningful image + 0xA003: 'PixelYDimension', // Valid height of meaningful image + 0xA500: 'Gamma', + 0x9101: 'ComponentsConfiguration', // Information about channels + 0x9102: 'CompressedBitsPerPixel', // Compressed bits per pixel + 0x927C: 'MakerNote', // Any desired information written by the manufacturer + 0x9286: 'UserComment', // Comments by user + 0xA004: 'RelatedSoundFile', // Name of related sound file + 0x9003: 'DateTimeOriginal', // Date and time when the original image was generated + 0x9004: 'DateTimeDigitized', // Date and time when the image was stored digitally + 0x9290: 'SubSecTime', // Fractions of seconds for DateTime + 0x9291: 'SubSecTimeOriginal', // Fractions of seconds for DateTimeOriginal + 0x9292: 'SubSecTimeDigitized', // Fractions of seconds for DateTimeDigitized + 0x829A: 'ExposureTime', // Exposure time (in seconds) + 0x829D: 'FNumber', + 0x8822: 'ExposureProgram', // Exposure program + 0x8824: 'SpectralSensitivity', // Spectral sensitivity + 0x8827: 'PhotographicSensitivity', // EXIF 2.3, ISOSpeedRatings in EXIF 2.2 + 0x8828: 'OECF', // Optoelectric conversion factor + 0x8830: 'SensitivityType', + 0x8831: 'StandardOutputSensitivity', + 0x8832: 'RecommendedExposureIndex', + 0x8833: 'ISOSpeed', + 0x8834: 'ISOSpeedLatitudeyyy', + 0x8835: 'ISOSpeedLatitudezzz', + 0x9201: 'ShutterSpeedValue', // Shutter speed + 0x9202: 'ApertureValue', // Lens aperture + 0x9203: 'BrightnessValue', // Value of brightness + 0x9204: 'ExposureBias', // Exposure bias + 0x9205: 'MaxApertureValue', // Smallest F number of lens + 0x9206: 'SubjectDistance', // Distance to subject in meters + 0x9207: 'MeteringMode', // Metering mode + 0x9208: 'LightSource', // Kind of light source + 0x9209: 'Flash', // Flash status + 0x9214: 'SubjectArea', // Location and area of main subject + 0x920A: 'FocalLength', // Focal length of the lens in mm + 0xA20B: 'FlashEnergy', // Strobe energy in BCPS + 0xA20C: 'SpatialFrequencyResponse', + 0xA20E: 'FocalPlaneXResolution', // Number of pixels in width direction per FPRUnit + 0xA20F: 'FocalPlaneYResolution', // Number of pixels in height direction per FPRUnit + 0xA210: 'FocalPlaneResolutionUnit', // Unit for measuring the focal plane resolution + 0xA214: 'SubjectLocation', // Location of subject in image + 0xA215: 'ExposureIndex', // Exposure index selected on camera + 0xA217: 'SensingMethod', // Image sensor type + 0xA300: 'FileSource', // Image source (3 == DSC) + 0xA301: 'SceneType', // Scene type (1 == directly photographed) + 0xA302: 'CFAPattern', // Color filter array geometric pattern + 0xA401: 'CustomRendered', // Special processing + 0xA402: 'ExposureMode', // Exposure mode + 0xA403: 'WhiteBalance', // 1 = auto white balance, 2 = manual + 0xA404: 'DigitalZoomRatio', // Digital zoom ratio + 0xA405: 'FocalLengthIn35mmFilm', + 0xA406: 'SceneCaptureType', // Type of scene + 0xA407: 'GainControl', // Degree of overall image gain adjustment + 0xA408: 'Contrast', // Direction of contrast processing applied by camera + 0xA409: 'Saturation', // Direction of saturation processing applied by camera + 0xA40A: 'Sharpness', // Direction of sharpness processing applied by camera + 0xA40B: 'DeviceSettingDescription', + 0xA40C: 'SubjectDistanceRange', // Distance to subject + 0xA420: 'ImageUniqueID', // Identifier assigned uniquely to each image + 0xA430: 'CameraOwnerName', + 0xA431: 'BodySerialNumber', + 0xA432: 'LensSpecification', + 0xA433: 'LensMake', + 0xA434: 'LensModel', + 0xA435: 'LensSerialNumber', + // ============== + // GPS Info tags: + // ============== + 0x0000: 'GPSVersionID', + 0x0001: 'GPSLatitudeRef', + 0x0002: 'GPSLatitude', + 0x0003: 'GPSLongitudeRef', + 0x0004: 'GPSLongitude', + 0x0005: 'GPSAltitudeRef', + 0x0006: 'GPSAltitude', + 0x0007: 'GPSTimeStamp', + 0x0008: 'GPSSatellites', + 0x0009: 'GPSStatus', + 0x000A: 'GPSMeasureMode', + 0x000B: 'GPSDOP', + 0x000C: 'GPSSpeedRef', + 0x000D: 'GPSSpeed', + 0x000E: 'GPSTrackRef', + 0x000F: 'GPSTrack', + 0x0010: 'GPSImgDirectionRef', + 0x0011: 'GPSImgDirection', + 0x0012: 'GPSMapDatum', + 0x0013: 'GPSDestLatitudeRef', + 0x0014: 'GPSDestLatitude', + 0x0015: 'GPSDestLongitudeRef', + 0x0016: 'GPSDestLongitude', + 0x0017: 'GPSDestBearingRef', + 0x0018: 'GPSDestBearing', + 0x0019: 'GPSDestDistanceRef', + 0x001A: 'GPSDestDistance', + 0x001B: 'GPSProcessingMethod', + 0x001C: 'GPSAreaInformation', + 0x001D: 'GPSDateStamp', + 0x001E: 'GPSDifferential', + 0x001F: 'GPSHPositioningError' + } + + loadImage.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: { + 0x0000: 'Flash did not fire', + 0x0001: 'Flash fired', + 0x0005: 'Strobe return light not detected', + 0x0007: 'Strobe return light detected', + 0x0009: 'Flash fired, compulsory flash mode', + 0x000D: 'Flash fired, compulsory flash mode, return light not detected', + 0x000F: 'Flash fired, compulsory flash mode, return light detected', + 0x0010: 'Flash did not fire, compulsory flash mode', + 0x0018: 'Flash did not fire, auto mode', + 0x0019: 'Flash fired, auto mode', + 0x001D: 'Flash fired, auto mode, return light not detected', + 0x001F: 'Flash fired, auto mode, return light detected', + 0x0020: 'No flash function', + 0x0041: 'Flash fired, red-eye reduction mode', + 0x0045: 'Flash fired, red-eye reduction mode, return light not detected', + 0x0047: 'Flash fired, red-eye reduction mode, return light detected', + 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode', + 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected', + 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected', + 0x0059: 'Flash fired, auto mode, red-eye reduction mode', + 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode', + 0x005F: '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' + } + } + + loadImage.ExifMap.prototype.getText = function (id) { + var value = this.get(id) + switch (id) { + 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[id][value] + case 'ExifVersion': + case 'FlashpixVersion': + return String.fromCharCode(value[0], value[1], value[2], value[3]) + case 'ComponentsConfiguration': + return this.stringValues[id][value[0]] + + this.stringValues[id][value[1]] + + this.stringValues[id][value[2]] + + this.stringValues[id][value[3]] + case 'GPSVersionID': + return value[0] + '.' + value[1] + '.' + value[2] + '.' + value[3] + } + return String(value) + } + + ;(function (exifMapPrototype) { + var tags = exifMapPrototype.tags + var map = exifMapPrototype.map + var prop + // Map the tag names to tags: + for (prop in tags) { + if (tags.hasOwnProperty(prop)) { + map[tags[prop]] = prop + } + } + }(loadImage.ExifMap.prototype)) + + loadImage.ExifMap.prototype.getAll = function () { + var map = {} + var prop + var id + for (prop in this) { + if (this.hasOwnProperty(prop)) { + id = this.tags[prop] + if (id) { + map[id] = this.getText(id) + } + } + } + return map + } +})) diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-exif.js b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-exif.js new file mode 100755 index 0000000..96f9824 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-exif.js @@ -0,0 +1,300 @@ +/* + * JavaScript Load Image Exif Parser + * https://github.com/blueimp/JavaScript-Load-Image + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*global define, module, require, window, console */ + +;(function (factory) { + 'use strict' + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['./load-image', './load-image-meta'], factory) + } else if (typeof module === 'object' && module.exports) { + factory(require('./load-image'), require('./load-image-meta')) + } else { + // Browser globals: + factory(window.loadImage) + } +}(function (loadImage) { + 'use strict' + + loadImage.ExifMap = function () { + return this + } + + loadImage.ExifMap.prototype.map = { + 'Orientation': 0x0112 + } + + loadImage.ExifMap.prototype.get = function (id) { + return this[id] || this[this.map[id]] + } + + loadImage.getExifThumbnail = function (dataView, offset, length) { + var hexData, + i, + b + if (!length || offset + length > dataView.byteLength) { + console.log('Invalid Exif data: Invalid thumbnail data.') + return + } + hexData = [] + for (i = 0; i < length; i += 1) { + b = dataView.getUint8(offset + i) + hexData.push((b < 16 ? '0' : '') + b.toString(16)) + } + return 'data:image/jpeg,%' + hexData.join('%') + } + + loadImage.exifTagTypes = { + // byte, 8-bit unsigned int: + 1: { + getValue: function (dataView, dataOffset) { + return dataView.getUint8(dataOffset) + }, + size: 1 + }, + // ascii, 8-bit byte: + 2: { + getValue: function (dataView, dataOffset) { + return String.fromCharCode(dataView.getUint8(dataOffset)) + }, + size: 1, + ascii: true + }, + // short, 16 bit int: + 3: { + getValue: function (dataView, dataOffset, littleEndian) { + return dataView.getUint16(dataOffset, littleEndian) + }, + size: 2 + }, + // long, 32 bit int: + 4: { + getValue: function (dataView, dataOffset, littleEndian) { + return dataView.getUint32(dataOffset, littleEndian) + }, + size: 4 + }, + // rational = two long values, first is numerator, second is denominator: + 5: { + getValue: function (dataView, dataOffset, littleEndian) { + return dataView.getUint32(dataOffset, littleEndian) / + dataView.getUint32(dataOffset + 4, littleEndian) + }, + size: 8 + }, + // slong, 32 bit signed int: + 9: { + getValue: function (dataView, dataOffset, littleEndian) { + return dataView.getInt32(dataOffset, littleEndian) + }, + size: 4 + }, + // srational, two slongs, first is numerator, second is denominator: + 10: { + getValue: function (dataView, dataOffset, littleEndian) { + return dataView.getInt32(dataOffset, littleEndian) / + dataView.getInt32(dataOffset + 4, littleEndian) + }, + size: 8 + } + } + // undefined, 8-bit byte, value depending on field: + loadImage.exifTagTypes[7] = loadImage.exifTagTypes[1] + + loadImage.getExifValue = function (dataView, tiffOffset, offset, type, length, littleEndian) { + var tagType = loadImage.exifTagTypes[type] + var tagSize + var dataOffset + var values + var i + var str + var c + if (!tagType) { + console.log('Invalid Exif data: Invalid tag type.') + return + } + tagSize = tagType.size * length + // Determine if the value is contained in the dataOffset bytes, + // or if the value at the dataOffset is a pointer to the actual data: + dataOffset = tagSize > 4 + ? tiffOffset + dataView.getUint32(offset + 8, littleEndian) + : (offset + 8) + if (dataOffset + tagSize > dataView.byteLength) { + console.log('Invalid Exif data: Invalid data offset.') + return + } + if (length === 1) { + return tagType.getValue(dataView, dataOffset, littleEndian) + } + values = [] + for (i = 0; i < length; i += 1) { + values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian) + } + if (tagType.ascii) { + str = '' + // Concatenate the chars: + for (i = 0; i < values.length; i += 1) { + c = values[i] + // Ignore the terminating NULL byte(s): + if (c === '\u0000') { + break + } + str += c + } + return str + } + return values + } + + loadImage.parseExifTag = function (dataView, tiffOffset, offset, littleEndian, data) { + var tag = dataView.getUint16(offset, littleEndian) + data.exif[tag] = loadImage.getExifValue( + dataView, + tiffOffset, + offset, + dataView.getUint16(offset + 2, littleEndian), // tag type + dataView.getUint32(offset + 4, littleEndian), // tag length + littleEndian + ) + } + + loadImage.parseExifTags = function (dataView, tiffOffset, dirOffset, littleEndian, data) { + var tagsNumber, + dirEndOffset, + i + if (dirOffset + 6 > dataView.byteLength) { + console.log('Invalid Exif data: Invalid directory offset.') + return + } + tagsNumber = dataView.getUint16(dirOffset, littleEndian) + dirEndOffset = dirOffset + 2 + 12 * tagsNumber + if (dirEndOffset + 4 > dataView.byteLength) { + console.log('Invalid Exif data: Invalid directory size.') + return + } + for (i = 0; i < tagsNumber; i += 1) { + this.parseExifTag( + dataView, + tiffOffset, + dirOffset + 2 + 12 * i, // tag offset + littleEndian, + data + ) + } + // Return the offset to the next directory: + return dataView.getUint32(dirEndOffset, littleEndian) + } + + loadImage.parseExifData = function (dataView, offset, length, data, options) { + if (options.disableExif) { + return + } + var tiffOffset = offset + 10 + var littleEndian + var dirOffset + var thumbnailData + // Check for the ASCII code for "Exif" (0x45786966): + if (dataView.getUint32(offset + 4) !== 0x45786966) { + // No Exif data, might be XMP data instead + return + } + if (tiffOffset + 8 > dataView.byteLength) { + console.log('Invalid Exif data: Invalid segment size.') + return + } + // Check for the two null bytes: + if (dataView.getUint16(offset + 8) !== 0x0000) { + console.log('Invalid Exif data: Missing byte alignment offset.') + return + } + // Check the byte alignment: + switch (dataView.getUint16(tiffOffset)) { + case 0x4949: + littleEndian = true + break + case 0x4D4D: + littleEndian = false + break + default: + console.log('Invalid Exif data: Invalid byte alignment marker.') + return + } + // Check for the TIFF tag marker (0x002A): + if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) { + console.log('Invalid Exif data: Missing TIFF marker.') + return + } + // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal: + dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian) + // Create the exif object to store the tags: + data.exif = new loadImage.ExifMap() + // Parse the tags of the main image directory and retrieve the + // offset to the next directory, usually the thumbnail directory: + dirOffset = loadImage.parseExifTags( + dataView, + tiffOffset, + tiffOffset + dirOffset, + littleEndian, + data + ) + if (dirOffset && !options.disableExifThumbnail) { + thumbnailData = {exif: {}} + dirOffset = loadImage.parseExifTags( + dataView, + tiffOffset, + tiffOffset + dirOffset, + littleEndian, + thumbnailData + ) + // Check for JPEG Thumbnail offset: + if (thumbnailData.exif[0x0201]) { + data.exif.Thumbnail = loadImage.getExifThumbnail( + dataView, + tiffOffset + thumbnailData.exif[0x0201], + thumbnailData.exif[0x0202] // Thumbnail data length + ) + } + } + // Check for Exif Sub IFD Pointer: + if (data.exif[0x8769] && !options.disableExifSub) { + loadImage.parseExifTags( + dataView, + tiffOffset, + tiffOffset + data.exif[0x8769], // directory offset + littleEndian, + data + ) + } + // Check for GPS Info IFD Pointer: + if (data.exif[0x8825] && !options.disableExifGps) { + loadImage.parseExifTags( + dataView, + tiffOffset, + tiffOffset + data.exif[0x8825], // directory offset + littleEndian, + data + ) + } + } + + // Registers the Exif parser for the APP1 JPEG meta data segment: + loadImage.metaDataParsers.jpeg[0xffe1].push(loadImage.parseExifData) + + // Adds the following properties to the parseMetaData callback data: + // * exif: The exif tags, parsed by the parseExifData method + + // Adds the following options to the parseMetaData method: + // * disableExif: Disables Exif parsing. + // * disableExifThumbnail: Disables parsing of the Exif Thumbnail. + // * disableExifSub: Disables parsing of the Exif Sub IFD. + // * disableExifGps: Disables parsing of the Exif GPS Info IFD. +})) diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-meta.js b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-meta.js new file mode 100755 index 0000000..994cf9d --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-meta.js @@ -0,0 +1,143 @@ +/* + * JavaScript Load Image Meta + * https://github.com/blueimp/JavaScript-Load-Image + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Image meta data handling implementation + * based on the help and contribution of + * Achim Stöhr. + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*global define, module, require, window, DataView, Blob, Uint8Array, console */ + +;(function (factory) { + 'use strict' + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['./load-image'], factory) + } else if (typeof module === 'object' && module.exports) { + factory(require('./load-image')) + } else { + // Browser globals: + factory(window.loadImage) + } +}(function (loadImage) { + 'use strict' + + var hasblobSlice = window.Blob && (Blob.prototype.slice || + Blob.prototype.webkitSlice || Blob.prototype.mozSlice) + + loadImage.blobSlice = hasblobSlice && function () { + var slice = this.slice || this.webkitSlice || this.mozSlice + return slice.apply(this, arguments) + } + + loadImage.metaDataParsers = { + jpeg: { + 0xffe1: [] // APP1 marker + } + } + + // Parses image meta data and calls the callback with an object argument + // with the following properties: + // * imageHead: The complete image head as ArrayBuffer (Uint8Array for IE10) + // The options arguments accepts an object and supports the following properties: + // * maxMetaDataSize: Defines the maximum number of bytes to parse. + // * disableImageHead: Disables creating the imageHead property. + loadImage.parseMetaData = function (file, callback, options) { + options = options || {} + var that = this + // 256 KiB should contain all EXIF/ICC/IPTC segments: + var maxMetaDataSize = options.maxMetaDataSize || 262144 + var data = {} + var noMetaData = !(window.DataView && file && file.size >= 12 && + file.type === 'image/jpeg' && loadImage.blobSlice) + if (noMetaData || !loadImage.readFile( + loadImage.blobSlice.call(file, 0, maxMetaDataSize), + function (e) { + if (e.target.error) { + // FileReader error + console.log(e.target.error) + callback(data) + return + } + // Note on endianness: + // Since the marker and length bytes in JPEG files are always + // stored in big endian order, we can leave the endian parameter + // of the DataView methods undefined, defaulting to big endian. + var buffer = e.target.result + var dataView = new DataView(buffer) + var offset = 2 + var maxOffset = dataView.byteLength - 4 + var headLength = offset + var markerBytes + var markerLength + var parsers + var i + // Check for the JPEG marker (0xffd8): + if (dataView.getUint16(0) === 0xffd8) { + while (offset < maxOffset) { + markerBytes = dataView.getUint16(offset) + // Search for APPn (0xffeN) and COM (0xfffe) markers, + // which contain application-specific meta-data like + // Exif, ICC and IPTC data and text comments: + if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) || + markerBytes === 0xfffe) { + // The marker bytes (2) are always followed by + // the length bytes (2), indicating the length of the + // marker segment, which includes the length bytes, + // but not the marker bytes, so we add 2: + markerLength = dataView.getUint16(offset + 2) + 2 + if (offset + markerLength > dataView.byteLength) { + console.log('Invalid meta data: Invalid segment size.') + break + } + parsers = loadImage.metaDataParsers.jpeg[markerBytes] + if (parsers) { + for (i = 0; i < parsers.length; i += 1) { + parsers[i].call( + that, + dataView, + offset, + markerLength, + data, + options + ) + } + } + offset += markerLength + headLength = offset + } else { + // Not an APPn or COM marker, probably safe to + // assume that this is the end of the meta data + break + } + } + // Meta length must be longer than JPEG marker (2) + // plus APPn marker (2), followed by length bytes (2): + if (!options.disableImageHead && headLength > 6) { + if (buffer.slice) { + data.imageHead = buffer.slice(0, headLength) + } else { + // Workaround for IE10, which does not yet + // support ArrayBuffer.slice: + data.imageHead = new Uint8Array(buffer) + .subarray(0, headLength) + } + } + } else { + console.log('Invalid JPEG file: Missing JPEG marker.') + } + callback(data) + }, + 'readAsArrayBuffer' + )) { + callback(data) + } + } +})) diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-orientation.js b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-orientation.js new file mode 100755 index 0000000..a321b4b --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image-orientation.js @@ -0,0 +1,171 @@ +/* + * JavaScript Load Image Orientation + * https://github.com/blueimp/JavaScript-Load-Image + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*global define, module, require, window */ + +;(function (factory) { + 'use strict' + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['./load-image'], factory) + } else if (typeof module === 'object' && module.exports) { + factory(require('./load-image')) + } else { + // Browser globals: + factory(window.loadImage) + } +}(function (loadImage) { + 'use strict' + + var originalHasCanvasOption = loadImage.hasCanvasOption + var originalTransformCoordinates = loadImage.transformCoordinates + var originalGetTransformedOptions = loadImage.getTransformedOptions + + // This method is used to determine if the target image + // should be a canvas element: + loadImage.hasCanvasOption = function (options) { + return !!options.orientation || + originalHasCanvasOption.call(loadImage, options) + } + + // Transform image orientation based on + // the given EXIF orientation option: + loadImage.transformCoordinates = function (canvas, options) { + originalTransformCoordinates.call(loadImage, canvas, options) + var ctx = canvas.getContext('2d') + var width = canvas.width + var height = canvas.height + var styleWidth = canvas.style.width + var styleHeight = canvas.style.height + var orientation = options.orientation + if (!orientation || orientation > 8) { + return + } + if (orientation > 4) { + canvas.width = height + canvas.height = width + canvas.style.width = styleHeight + canvas.style.height = styleWidth + } + switch (orientation) { + case 2: + // horizontal flip + ctx.translate(width, 0) + ctx.scale(-1, 1) + break + case 3: + // 180° rotate left + ctx.translate(width, height) + ctx.rotate(Math.PI) + break + case 4: + // vertical flip + ctx.translate(0, height) + ctx.scale(1, -1) + break + case 5: + // vertical flip + 90 rotate right + ctx.rotate(0.5 * Math.PI) + ctx.scale(1, -1) + break + case 6: + // 90° rotate right + ctx.rotate(0.5 * Math.PI) + ctx.translate(0, -height) + break + case 7: + // horizontal flip + 90 rotate right + ctx.rotate(0.5 * Math.PI) + ctx.translate(width, -height) + ctx.scale(-1, 1) + break + case 8: + // 90° rotate left + ctx.rotate(-0.5 * Math.PI) + ctx.translate(-width, 0) + break + } + } + + // Transforms coordinate and dimension options + // based on the given orientation option: + loadImage.getTransformedOptions = function (img, opts) { + var options = originalGetTransformedOptions.call(loadImage, img, opts) + var orientation = options.orientation + var newOptions + var i + if (!orientation || orientation > 8 || orientation === 1) { + return options + } + newOptions = {} + for (i in options) { + if (options.hasOwnProperty(i)) { + newOptions[i] = options[i] + } + } + switch (options.orientation) { + case 2: + // horizontal flip + newOptions.left = options.right + newOptions.right = options.left + break + case 3: + // 180° rotate left + newOptions.left = options.right + newOptions.top = options.bottom + newOptions.right = options.left + newOptions.bottom = options.top + break + case 4: + // vertical flip + newOptions.top = options.bottom + newOptions.bottom = options.top + break + case 5: + // vertical flip + 90 rotate right + newOptions.left = options.top + newOptions.top = options.left + newOptions.right = options.bottom + newOptions.bottom = options.right + break + case 6: + // 90° rotate right + newOptions.left = options.top + newOptions.top = options.right + newOptions.right = options.bottom + newOptions.bottom = options.left + break + case 7: + // horizontal flip + 90 rotate right + newOptions.left = options.bottom + newOptions.top = options.right + newOptions.right = options.top + newOptions.bottom = options.left + break + case 8: + // 90° rotate left + newOptions.left = options.bottom + newOptions.top = options.left + newOptions.right = options.top + newOptions.bottom = options.right + break + } + if (options.orientation > 4) { + newOptions.maxWidth = options.maxHeight + newOptions.maxHeight = options.maxWidth + newOptions.minWidth = options.minHeight + newOptions.minHeight = options.minWidth + newOptions.sourceWidth = options.sourceHeight + newOptions.sourceHeight = options.sourceWidth + } + return newOptions + } +})) diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.all.min.js b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.all.min.js new file mode 100755 index 0000000..2ec3313 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.all.min.js @@ -0,0 +1,2 @@ +!function(e){"use strict";var t=function(e,i,a){var o,r,n=document.createElement("img");if(n.onerror=i,n.onload=function(){!r||a&&a.noRevoke||t.revokeObjectURL(r),i&&i(t.scale(n,a))},t.isInstanceOf("Blob",e)||t.isInstanceOf("File",e))o=r=t.createObjectURL(e),n._type=e.type;else{if("string"!=typeof e)return!1;o=e,a&&a.crossOrigin&&(n.crossOrigin=a.crossOrigin)}return o?(n.src=o,n):t.readFile(e,function(e){var t=e.target;t&&t.result?n.src=t.result:i&&i(e)})},i=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;t.isInstanceOf=function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},t.transformCoordinates=function(){},t.getTransformedOptions=function(e,t){var i,a,o,r,n=t.aspectRatio;if(!n)return t;i={};for(a in t)t.hasOwnProperty(a)&&(i[a]=t[a]);return i.crop=!0,o=e.naturalWidth||e.width,r=e.naturalHeight||e.height,o/r>n?(i.maxWidth=r*n,i.maxHeight=r):(i.maxWidth=o,i.maxHeight=o/n),i},t.renderImageToCanvas=function(e,t,i,a,o,r,n,s,l,d){return e.getContext("2d").drawImage(t,i,a,o,r,n,s,l,d),e},t.hasCanvasOption=function(e){return e.canvas||e.crop||!!e.aspectRatio},t.scale=function(e,i){function a(){var e=Math.max((s||y)/y,(l||v)/v);e>1&&(y*=e,v*=e)}function o(){var e=Math.min((r||y)/y,(n||v)/v);1>e&&(y*=e,v*=e)}i=i||{};var r,n,s,l,d,u,c,g,f,h,m,p=document.createElement("canvas"),S=e.getContext||t.hasCanvasOption(i)&&p.getContext,b=e.naturalWidth||e.width,x=e.naturalHeight||e.height,y=b,v=x;if(S&&(i=t.getTransformedOptions(e,i),c=i.left||0,g=i.top||0,i.sourceWidth?(d=i.sourceWidth,void 0!==i.right&&void 0===i.left&&(c=b-d-i.right)):d=b-c-(i.right||0),i.sourceHeight?(u=i.sourceHeight,void 0!==i.bottom&&void 0===i.top&&(g=x-u-i.bottom)):u=x-g-(i.bottom||0),y=d,v=u),r=i.maxWidth,n=i.maxHeight,s=i.minWidth,l=i.minHeight,S&&r&&n&&i.crop?(y=r,v=n,m=d/u-r/n,0>m?(u=n*d/r,void 0===i.top&&void 0===i.bottom&&(g=(x-u)/2)):m>0&&(d=r*u/n,void 0===i.left&&void 0===i.right&&(c=(b-d)/2))):((i.contain||i.cover)&&(s=r=r||s,l=n=n||l),i.cover?(o(),a()):(a(),o())),S){if(f=i.pixelRatio,f>1&&(p.style.width=y+"px",p.style.height=v+"px",y*=f,v*=f,p.getContext("2d").scale(f,f)),h=i.downsamplingRatio,h>0&&1>h&&d>y&&u>v)for(;d*h>y;)p.width=d*h,p.height=u*h,t.renderImageToCanvas(p,e,c,g,d,u,0,0,p.width,p.height),d=p.width,u=p.height,e=document.createElement("canvas"),e.width=d,e.height=u,t.renderImageToCanvas(e,p,0,0,d,u,0,0,d,u);return p.width=y,p.height=v,t.transformCoordinates(p,i),t.renderImageToCanvas(p,e,c,g,d,u,0,0,y,v)}return e.width=y,e.height=v,e},t.createObjectURL=function(e){return i?i.createObjectURL(e):!1},t.revokeObjectURL=function(e){return i?i.revokeObjectURL(e):!1},t.readFile=function(e,t,i){if(window.FileReader){var a=new FileReader;if(a.onload=a.onerror=t,i=i||"readAsDataURL",a[i])return a[i](e),a}return!1},"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:e.loadImage=t}(window),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],e):e("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(e){"use strict";var t=e.hasCanvasOption,i=e.transformCoordinates,a=e.getTransformedOptions;e.hasCanvasOption=function(i){return!!i.orientation||t.call(e,i)},e.transformCoordinates=function(t,a){i.call(e,t,a);var o=t.getContext("2d"),r=t.width,n=t.height,s=t.style.width,l=t.style.height,d=a.orientation;if(d&&!(d>8))switch(d>4&&(t.width=n,t.height=r,t.style.width=l,t.style.height=s),d){case 2:o.translate(r,0),o.scale(-1,1);break;case 3:o.translate(r,n),o.rotate(Math.PI);break;case 4:o.translate(0,n),o.scale(1,-1);break;case 5:o.rotate(.5*Math.PI),o.scale(1,-1);break;case 6:o.rotate(.5*Math.PI),o.translate(0,-n);break;case 7:o.rotate(.5*Math.PI),o.translate(r,-n),o.scale(-1,1);break;case 8:o.rotate(-.5*Math.PI),o.translate(-r,0)}},e.getTransformedOptions=function(t,i){var o,r,n=a.call(e,t,i),s=n.orientation;if(!s||s>8||1===s)return n;o={};for(r in n)n.hasOwnProperty(r)&&(o[r]=n[r]);switch(n.orientation){case 2:o.left=n.right,o.right=n.left;break;case 3:o.left=n.right,o.top=n.bottom,o.right=n.left,o.bottom=n.top;break;case 4:o.top=n.bottom,o.bottom=n.top;break;case 5:o.left=n.top,o.top=n.left,o.right=n.bottom,o.bottom=n.right;break;case 6:o.left=n.top,o.top=n.right,o.right=n.bottom,o.bottom=n.left;break;case 7:o.left=n.bottom,o.top=n.right,o.right=n.top,o.bottom=n.left;break;case 8:o.left=n.bottom,o.top=n.left,o.right=n.top,o.bottom=n.right}return n.orientation>4&&(o.maxWidth=n.maxHeight,o.maxHeight=n.maxWidth,o.minWidth=n.minHeight,o.minHeight=n.minWidth,o.sourceWidth=n.sourceHeight,o.sourceHeight=n.sourceWidth),o}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image"],e):e("object"==typeof module&&module.exports?require("./load-image"):window.loadImage)}(function(e){"use strict";var t=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.blobSlice=t&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},e.metaDataParsers={jpeg:{65505:[]}},e.parseMetaData=function(t,i,a){a=a||{};var o=this,r=a.maxMetaDataSize||262144,n={},s=!(window.DataView&&t&&t.size>=12&&"image/jpeg"===t.type&&e.blobSlice);(s||!e.readFile(e.blobSlice.call(t,0,r),function(t){if(t.target.error)return console.log(t.target.error),void i(n);var r,s,l,d,u=t.target.result,c=new DataView(u),g=2,f=c.byteLength-4,h=g;if(65496===c.getUint16(0)){for(;f>g&&(r=c.getUint16(g),r>=65504&&65519>=r||65534===r);){if(s=c.getUint16(g+2)+2,g+s>c.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(l=e.metaDataParsers.jpeg[r])for(d=0;d6&&(u.slice?n.imageHead=u.slice(0,h):n.imageHead=new Uint8Array(u).subarray(0,h))}else console.log("Invalid JPEG file: Missing JPEG marker.");i(n)},"readAsArrayBuffer"))&&i(n)}}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-meta"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-meta")):e(window.loadImage)}(function(e){"use strict";e.ExifMap=function(){return this},e.ExifMap.prototype.map={Orientation:274},e.ExifMap.prototype.get=function(e){return this[e]||this[this.map[e]]},e.getExifThumbnail=function(e,t,i){var a,o,r;if(!i||t+i>e.byteLength)return void console.log("Invalid Exif data: Invalid thumbnail data.");for(a=[],o=0;i>o;o+=1)r=e.getUint8(t+o),a.push((16>r?"0":"")+r.toString(16));return"data:image/jpeg,%"+a.join("%")},e.exifTagTypes={1:{getValue:function(e,t){return e.getUint8(t)},size:1},2:{getValue:function(e,t){return String.fromCharCode(e.getUint8(t))},size:1,ascii:!0},3:{getValue:function(e,t,i){return e.getUint16(t,i)},size:2},4:{getValue:function(e,t,i){return e.getUint32(t,i)},size:4},5:{getValue:function(e,t,i){return e.getUint32(t,i)/e.getUint32(t+4,i)},size:8},9:{getValue:function(e,t,i){return e.getInt32(t,i)},size:4},10:{getValue:function(e,t,i){return e.getInt32(t,i)/e.getInt32(t+4,i)},size:8}},e.exifTagTypes[7]=e.exifTagTypes[1],e.getExifValue=function(t,i,a,o,r,n){var s,l,d,u,c,g,f=e.exifTagTypes[o];if(!f)return void console.log("Invalid Exif data: Invalid tag type.");if(s=f.size*r,l=s>4?i+t.getUint32(a+8,n):a+8,l+s>t.byteLength)return void console.log("Invalid Exif data: Invalid data offset.");if(1===r)return f.getValue(t,l,n);for(d=[],u=0;r>u;u+=1)d[u]=f.getValue(t,l+u*f.size,n);if(f.ascii){for(c="",u=0;ue.byteLength)return void console.log("Invalid Exif data: Invalid directory offset.");if(r=e.getUint16(i,a),n=i+2+12*r,n+4>e.byteLength)return void console.log("Invalid Exif data: Invalid directory size.");for(s=0;r>s;s+=1)this.parseExifTag(e,t,i+2+12*s,a,o);return e.getUint32(n,a)},e.parseExifData=function(t,i,a,o,r){if(!r.disableExif){var n,s,l,d=i+10;if(1165519206===t.getUint32(i+4)){if(d+8>t.byteLength)return void console.log("Invalid Exif data: Invalid segment size.");if(0!==t.getUint16(i+8))return void console.log("Invalid Exif data: Missing byte alignment offset.");switch(t.getUint16(d)){case 18761:n=!0;break;case 19789:n=!1;break;default:return void console.log("Invalid Exif data: Invalid byte alignment marker.")}if(42!==t.getUint16(d+2,n))return void console.log("Invalid Exif data: Missing TIFF marker.");s=t.getUint32(d+4,n),o.exif=new e.ExifMap,s=e.parseExifTags(t,d,d+s,n,o),s&&!r.disableExifThumbnail&&(l={exif:{}},s=e.parseExifTags(t,d,d+s,n,l),l.exif[513]&&(o.exif.Thumbnail=e.getExifThumbnail(t,d+l.exif[513],l.exif[514]))),o.exif[34665]&&!r.disableExifSub&&e.parseExifTags(t,d,d+o.exif[34665],n,o),o.exif[34853]&&!r.disableExifGps&&e.parseExifTags(t,d,d+o.exif[34853],n,o)}}},e.metaDataParsers.jpeg[65505].push(e.parseExifData)}),function(e){"use strict";"function"==typeof define&&define.amd?define(["./load-image","./load-image-exif"],e):"object"==typeof module&&module.exports?e(require("./load-image"),require("./load-image-exif")):e(window.loadImage)}(function(e){"use strict";e.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"},e.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"}},e.ExifMap.prototype.getText=function(e){var t=this.get(e);switch(e){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[e][t];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(t[0],t[1],t[2],t[3]);case"ComponentsConfiguration":return this.stringValues[e][t[0]]+this.stringValues[e][t[1]]+this.stringValues[e][t[2]]+this.stringValues[e][t[3]];case"GPSVersionID":return t[0]+"."+t[1]+"."+t[2]+"."+t[3]}return String(t)},function(e){var t,i=e.tags,a=e.map;for(t in i)i.hasOwnProperty(t)&&(a[i[t]]=t)}(e.ExifMap.prototype),e.ExifMap.prototype.getAll=function(){var e,t,i={};for(e in this)this.hasOwnProperty(e)&&(t=this.tags[e],t&&(i[t]=this.getText(t)));return i}}); +//# sourceMappingURL=load-image.all.min.js.map \ No newline at end of file diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.all.min.js.map b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.all.min.js.map new file mode 100755 index 0000000..0bbb4e8 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.all.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["load-image.js","load-image-orientation.js","load-image-meta.js","load-image-exif.js","load-image-exif-map.js"],"names":["$","loadImage","file","callback","options","url","oUrl","img","document","createElement","onerror","onload","noRevoke","revokeObjectURL","scale","isInstanceOf","createObjectURL","_type","type","crossOrigin","src","readFile","e","target","result","urlAPI","window","URL","webkitURL","obj","Object","prototype","toString","call","transformCoordinates","getTransformedOptions","newOptions","i","width","height","aspectRatio","hasOwnProperty","crop","naturalWidth","naturalHeight","maxWidth","maxHeight","renderImageToCanvas","canvas","sourceX","sourceY","sourceWidth","sourceHeight","destX","destY","destWidth","destHeight","getContext","drawImage","hasCanvasOption","scaleUp","Math","max","minWidth","minHeight","scaleDown","min","pixelRatio","downsamplingRatio","tmp","useCanvas","left","top","undefined","right","bottom","contain","cover","style","method","FileReader","fileReader","define","amd","module","exports","factory","require","originalHasCanvasOption","originalTransformCoordinates","originalGetTransformedOptions","orientation","ctx","styleWidth","styleHeight","translate","rotate","PI","opts","hasblobSlice","Blob","slice","webkitSlice","mozSlice","blobSlice","this","apply","arguments","metaDataParsers","jpeg",65505,"parseMetaData","that","maxMetaDataSize","data","noMetaData","DataView","size","error","console","log","markerBytes","markerLength","parsers","buffer","dataView","offset","maxOffset","byteLength","headLength","getUint16","length","disableImageHead","imageHead","Uint8Array","subarray","ExifMap","map","Orientation","get","id","getExifThumbnail","hexData","b","getUint8","push","join","exifTagTypes",1,"getValue","dataOffset",2,"String","fromCharCode","ascii",3,"littleEndian",4,"getUint32",5,9,"getInt32",10,"getExifValue","tiffOffset","tagSize","values","str","c","tagType","parseExifTag","tag","exif","parseExifTags","dirOffset","tagsNumber","dirEndOffset","parseExifData","disableExif","thumbnailData","disableExifThumbnail","Thumbnail","disableExifSub","disableExifGps","tags",256,257,34665,34853,40965,258,259,262,274,277,284,530,531,282,283,296,273,278,279,513,514,301,318,319,529,532,306,270,271,272,305,315,33432,36864,40960,40961,40962,40963,42240,37121,37122,37500,37510,40964,36867,36868,37520,37521,37522,33434,33437,34850,34852,34855,34856,34864,34865,34866,34867,34868,34869,37377,37378,37379,37380,37381,37382,37383,37384,37385,37396,37386,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,42032,42033,42034,42035,42036,42037,0,6,7,8,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,"stringValues","ExposureProgram","MeteringMode",255,"LightSource","Flash",32,65,69,71,73,77,79,89,93,95,"SensingMethod","SceneCaptureType","SceneType","CustomRendered","WhiteBalance","GainControl","Contrast","Saturation","Sharpness","SubjectDistanceRange","FileSource","ComponentsConfiguration","getText","value","exifMapPrototype","prop","getAll"],"mappings":"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","file":"load-image.all.min.js"} \ No newline at end of file diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js old mode 100644 new mode 100755 index 0155d38..b54b786 --- a/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/load-image.js @@ -1,228 +1,348 @@ /* - * JavaScript Load Image 1.3.1 + * JavaScript Load Image * 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'; +/*global define, module, window, document, URL, webkitURL, FileReader */ - // 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); +;(function ($) { + 'use strict' - // 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; + // 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') + var url + var oUrl + img.onerror = callback + img.onload = function () { + if (oUrl && !(options && options.noRevoke)) { + loadImage.revokeObjectURL(oUrl) + } + if (callback) { + callback(loadImage.scale(img, options)) + } + } + if (loadImage.isInstanceOf('Blob', file) || + // Files are also Blob instances, but some browsers + // (Firefox 3.6) support the File API but not Blobs: + loadImage.isInstanceOf('File', file)) { + url = oUrl = loadImage.createObjectURL(file) + // Store the file type for resize processing: + img._type = file.type + } else if (typeof file === 'string') { + url = file + if (options && options.crossOrigin) { + img.crossOrigin = options.crossOrigin + } + } else { + return false + } + 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 { + if (callback) { + callback(e) } - return false; - }; + } + }) + } + // The check for URL.revokeObjectURL fixes an issue with Opera 12, + // which provides URL.createObjectURL but doesn't properly implement it: + var urlAPI = (window.createObjectURL && window) || + (window.URL && URL.revokeObjectURL && URL) || + (window.webkitURL && webkitURL) - // 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; - }; + loadImage.isInstanceOf = function (type, obj) { + // Cross-frame instanceof check + return Object.prototype.toString.call(obj) === '[object ' + type + ']' + } + + // Transform image coordinates, allows to override e.g. + // the canvas orientation based on the orientation option, + // gets canvas, options passed as arguments: + loadImage.transformCoordinates = function () { + return + } + + // Returns transformed options, allows to override e.g. + // maxWidth, maxHeight and crop options based on the aspectRatio. + // gets img, options passed as arguments: + loadImage.getTransformedOptions = function (img, options) { + var aspectRatio = options.aspectRatio + var newOptions + var i + var width + var height + if (!aspectRatio) { + return options + } + newOptions = {} + for (i in options) { + if (options.hasOwnProperty(i)) { + newOptions[i] = options[i] + } + } + newOptions.crop = true + width = img.naturalWidth || img.width + height = img.naturalHeight || img.height + if (width / height > aspectRatio) { + newOptions.maxWidth = height * aspectRatio + newOptions.maxHeight = height + } else { + newOptions.maxWidth = width + newOptions.maxHeight = width / aspectRatio + } + return newOptions + } + + // Canvas render method, allows to implement a different rendering algorithm: + loadImage.renderImageToCanvas = function ( + canvas, + img, + sourceX, + sourceY, + sourceWidth, + sourceHeight, + destX, + destY, + destWidth, + destHeight + ) { + canvas.getContext('2d').drawImage( + img, + sourceX, + sourceY, + sourceWidth, + sourceHeight, + destX, + destY, + destWidth, + destHeight + ) + return canvas + } - // 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; + // This method is used to determine if the target image + // should be a canvas element: + loadImage.hasCanvasOption = function (options) { + return options.canvas || options.crop || !!options.aspectRatio + } + + // Scales and/or crops the given image (img or canvas HTML element) + // using the given options. + // Returns a canvas object if the browser supports canvas + // and the hasCanvasOption method returns 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') + var useCanvas = img.getContext || + (loadImage.hasCanvasOption(options) && canvas.getContext) + var width = img.naturalWidth || img.width + var height = img.naturalHeight || img.height + var destWidth = width + var destHeight = height + var maxWidth + var maxHeight + var minWidth + var minHeight + var sourceWidth + var sourceHeight + var sourceX + var sourceY + var pixelRatio + var downsamplingRatio + var tmp + function scaleUp () { + var scale = Math.max( + (minWidth || destWidth) / destWidth, + (minHeight || destHeight) / destHeight + ) + if (scale > 1) { + destWidth *= scale + destHeight *= scale + } + } + function scaleDown () { + var scale = Math.min( + (maxWidth || destWidth) / destWidth, + (maxHeight || destHeight) / destHeight + ) + if (scale < 1) { + destWidth *= scale + destHeight *= scale + } + } + if (useCanvas) { + options = loadImage.getTransformedOptions(img, options) + sourceX = options.left || 0 + sourceY = options.top || 0 + if (options.sourceWidth) { + sourceWidth = options.sourceWidth + if (options.right !== undefined && options.left === undefined) { + sourceX = width - sourceWidth - options.right } - 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; + } else { + sourceWidth = width - sourceX - (options.right || 0) + } + if (options.sourceHeight) { + sourceHeight = options.sourceHeight + if (options.bottom !== undefined && options.top === undefined) { + sourceY = height - sourceHeight - options.bottom } - 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); + } else { + sourceHeight = height - sourceY - (options.bottom || 0) + } + destWidth = sourceWidth + destHeight = sourceHeight + } + maxWidth = options.maxWidth + maxHeight = options.maxHeight + minWidth = options.minWidth + minHeight = options.minHeight + if (useCanvas && maxWidth && maxHeight && options.crop) { + destWidth = maxWidth + destHeight = maxHeight + tmp = sourceWidth / sourceHeight - maxWidth / maxHeight + if (tmp < 0) { + sourceHeight = maxHeight * sourceWidth / maxWidth + if (options.top === undefined && options.bottom === undefined) { + sourceY = (height - sourceHeight) / 2 } - scale = Math.min( - (options.maxWidth || width) / width, - (options.maxHeight || height) / height - ); - if (scale < 1) { - width = Math.ceil(width * scale); - height = Math.ceil(height * scale); + } else if (tmp > 0) { + sourceWidth = maxWidth * sourceHeight / maxHeight + if (options.left === undefined && options.right === undefined) { + sourceX = (width - sourceWidth) / 2 } - 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; + } + } else { + if (options.contain || options.cover) { + minWidth = maxWidth = maxWidth || minWidth + minHeight = maxHeight = maxHeight || minHeight + } + if (options.cover) { + scaleDown() + scaleUp() + } else { + scaleUp() + scaleDown() + } + } + if (useCanvas) { + pixelRatio = options.pixelRatio + if (pixelRatio > 1) { + canvas.style.width = destWidth + 'px' + canvas.style.height = destHeight + 'px' + destWidth *= pixelRatio + destHeight *= pixelRatio + canvas.getContext('2d').scale(pixelRatio, pixelRatio) + } + downsamplingRatio = options.downsamplingRatio + if (downsamplingRatio > 0 && downsamplingRatio < 1 && + destWidth < sourceWidth && destHeight < sourceHeight) { + while (sourceWidth * downsamplingRatio > destWidth) { + canvas.width = sourceWidth * downsamplingRatio + canvas.height = sourceHeight * downsamplingRatio + loadImage.renderImageToCanvas( + canvas, + img, + sourceX, + sourceY, + sourceWidth, + sourceHeight, + 0, + 0, + canvas.width, + canvas.height + ) + sourceWidth = canvas.width + sourceHeight = canvas.height + img = document.createElement('canvas') + img.width = sourceWidth + img.height = sourceHeight + loadImage.renderImageToCanvas( + img, + canvas, + 0, + 0, + sourceWidth, + sourceHeight, + 0, + 0, + sourceWidth, + sourceHeight + ) } - img.width = width; - img.height = height; - return img; - }; + } + canvas.width = destWidth + canvas.height = destHeight + loadImage.transformCoordinates( + canvas, + options + ) + return loadImage.renderImageToCanvas( + canvas, + img, + sourceX, + sourceY, + sourceWidth, + sourceHeight, + 0, + 0, + destWidth, + destHeight + ) + } + img.width = destWidth + img.height = destHeight + return img + } - loadImage.createObjectURL = function (file) { - return urlAPI ? urlAPI.createObjectURL(file) : false; - }; + loadImage.createObjectURL = function (file) { + return urlAPI ? urlAPI.createObjectURL(file) : false + } - loadImage.revokeObjectURL = function (url) { - return urlAPI ? urlAPI.revokeObjectURL(url) : 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; + // 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, method) { + if (window.FileReader) { + var fileReader = new FileReader() + fileReader.onload = fileReader.onerror = callback + method = method || 'readAsDataURL' + if (fileReader[method]) { + fileReader[method](file) + return fileReader + } } -}(this)); + return false + } + + if (typeof define === 'function' && define.amd) { + define(function () { + return loadImage + }) + } else if (typeof module === 'object' && module.exports) { + module.exports = loadImage + } else { + $.loadImage = loadImage + } +}(window)) diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.js b/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.js deleted file mode 100644 index c8b4b86..0000000 --- a/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.js +++ /dev/null @@ -1,86 +0,0 @@ -/* - * JavaScript Templates 2.1.0 - * https://github.com/blueimp/JavaScript-Templates - * - * Copyright 2011, Sebastian Tschan - * https://blueimp.net - * - * Licensed under the MIT license: - * http://www.opensource.org/licenses/MIT - * - * Inspired by John Resig's JavaScript Micro-Templating: - * http://ejohn.org/blog/javascript-micro-templating/ - */ - -/*jslint evil: true, regexp: true */ -/*global document, define */ - -(function ($) { - "use strict"; - var tmpl = function (str, data) { - var f = !/[^\w\-\.:]/.test(str) ? tmpl.cache[str] = tmpl.cache[str] || - tmpl(tmpl.load(str)) : - new Function( - tmpl.arg + ',tmpl', - "var _e=tmpl.encode" + tmpl.helper + ",_s='" + - str.replace(tmpl.regexp, tmpl.func) + - "';return _s;" - ); - return data ? f(data, tmpl) : function (data) { - return f(data, tmpl); - }; - }; - tmpl.cache = {}; - tmpl.load = function (id) { - return document.getElementById(id).innerHTML; - }; - tmpl.regexp = /([\s'\\])(?![^%]*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g; - tmpl.func = function (s, p1, p2, p3, p4, p5) { - if (p1) { // whitespace, quote and backspace in interpolation context - return { - "\n": "\\n", - "\r": "\\r", - "\t": "\\t", - " " : " " - }[s] || "\\" + s; - } - if (p2) { // interpolation: {%=prop%}, or unescaped: {%#prop%} - if (p2 === "=") { - return "'+_e(" + p3 + ")+'"; - } - return "'+(" + p3 + "||'')+'"; - } - if (p4) { // evaluation start tag: {% - return "';"; - } - if (p5) { // evaluation end tag: %} - return "_s+='"; - } - }; - tmpl.encReg = /[<>&"'\x00]/g; - tmpl.encMap = { - "<" : "<", - ">" : ">", - "&" : "&", - "\"" : """, - "'" : "'" - }; - tmpl.encode = function (s) { - return String(s || "").replace( - tmpl.encReg, - function (c) { - return tmpl.encMap[c] || ""; - } - ); - }; - tmpl.arg = "o"; - tmpl.helper = ",print=function(s,e){_s+=e&&(s||'')||_e(s);}" + - ",include=function(s,d){_s+=tmpl(s,d);}"; - if (typeof define === "function" && define.amd) { - define(function () { - return tmpl; - }); - } else { - $.tmpl = tmpl; - } -}(this)); diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.min.js b/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.min.js new file mode 100755 index 0000000..79cb210 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.min.js @@ -0,0 +1,2 @@ +!function(e){"use strict";var n=function(e,t){var r=/[^\w\-\.:]/.test(e)?new Function(n.arg+",tmpl","var _e=tmpl.encode"+n.helper+",_s='"+e.replace(n.regexp,n.func)+"';return _s;"):n.cache[e]=n.cache[e]||n(n.load(e));return t?r(t,n):function(e){return r(e,n)}};n.cache={},n.load=function(e){return document.getElementById(e).innerHTML},n.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,n.func=function(e,n,t,r,c,u){return n?{"\n":"\\n","\r":"\\r"," ":"\\t"," ":" "}[n]||"\\"+n:t?"="===t?"'+_e("+r+")+'":"'+("+r+"==null?'':"+r+")+'":c?"';":u?"_s+='":void 0},n.encReg=/[<>&"'\x00]/g,n.encMap={"<":"<",">":">","&":"&",'"':""","'":"'"},n.encode=function(e){return(null==e?"":""+e).replace(n.encReg,function(e){return n.encMap[e]||""})},n.arg="o",n.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return n}):"object"==typeof module&&module.exports?module.exports=n:e.tmpl=n}(this); +//# sourceMappingURL=tmpl.min.js.map \ No newline at end of file diff --git a/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.min.js.map b/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.min.js.map new file mode 100755 index 0000000..4191bf1 --- /dev/null +++ b/vendor/assets/javascripts/jquery-fileupload/vendor/tmpl.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["tmpl.js"],"names":["$","tmpl","str","data","f","test","Function","arg","helper","replace","regexp","func","cache","load","id","document","getElementById","innerHTML","s","p1","p2","p3","p4","p5","\n","\r","\t"," ","encReg","encMap","<",">","&","\"","'","encode","c","define","amd","module","exports","this"],"mappings":"CAgBE,SAAUA,GACV,YACA,IAAIC,GAAO,SAAUC,EAAKC,GACxB,GAAIC,GAAK,aAAaC,KAAKH,GAEvB,GAAII,UACJL,EAAKM,IAAM,QACX,qBAAuBN,EAAKO,OAAS,QACnCN,EAAIO,QAAQR,EAAKS,OAAQT,EAAKU,MAAQ,gBAJxCV,EAAKW,MAAMV,GAAOD,EAAKW,MAAMV,IAAQD,EAAKA,EAAKY,KAAKX,GAMxD,OAAOC,GAAOC,EAAED,EAAMF,GAAQ,SAAUE,GACtC,MAAOC,GAAED,EAAMF,IAGnBA,GAAKW,SACLX,EAAKY,KAAO,SAAUC,GACpB,MAAOC,UAASC,eAAeF,GAAIG,WAErChB,EAAKS,OAAS,2EACdT,EAAKU,KAAO,SAAUO,EAAGC,EAAIC,EAAIC,EAAIC,EAAIC,GACvC,MAAIJ,IAEAK,KAAM,MACNC,KAAM,MACNC,IAAM,MACNC,IAAK,KACLR,IAAO,KAAOA,EAEdC,EACS,MAAPA,EACK,QAAUC,EAAK,MAEjB,MAAQA,EAAK,aAAeA,EAAK,MAEtCC,EACK,KAELC,EACK,QADT,QAIFtB,EAAK2B,OAAS,eACd3B,EAAK4B,QACHC,IAAK,OACLC,IAAK,OACLC,IAAK,QACLC,IAAK,SACLC,IAAK,SAEPjC,EAAKkC,OAAS,SAAUjB,GACtB,OAAa,MAALA,EAAY,GAAK,GAAKA,GAAGT,QAC/BR,EAAK2B,OACL,SAAUQ,GACR,MAAOnC,GAAK4B,OAAOO,IAAM,MAI/BnC,EAAKM,IAAM,IACXN,EAAKO,OAAS,0FAEQ,kBAAX6B,SAAyBA,OAAOC,IACzCD,OAAO,WACL,MAAOpC,KAEkB,gBAAXsC,SAAuBA,OAAOC,QAC9CD,OAAOC,QAAUvC,EAEjBD,EAAEC,KAAOA,GAEXwC","file":"tmpl.min.js"} \ No newline at end of file diff --git a/vendor/assets/stylesheets/jquery.fileupload-noscript.css b/vendor/assets/stylesheets/jquery.fileupload-noscript.css new file mode 100755 index 0000000..d0dda3a --- /dev/null +++ b/vendor/assets/stylesheets/jquery.fileupload-noscript.css @@ -0,0 +1,22 @@ +@charset "UTF-8"; +/* + * jQuery File Upload Plugin NoScript CSS + * 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 + */ + +.fileinput-button input { + position: static; + opacity: 1; + filter: none; + font-size: inherit; + direction: inherit; +} +.fileinput-button span { + display: none; +} diff --git a/vendor/assets/stylesheets/jquery.fileupload-ui-noscript.css b/vendor/assets/stylesheets/jquery.fileupload-ui-noscript.css new file mode 100755 index 0000000..6ad2ad6 --- /dev/null +++ b/vendor/assets/stylesheets/jquery.fileupload-ui-noscript.css @@ -0,0 +1,17 @@ +@charset "UTF-8"; +/* + * jQuery File Upload UI Plugin NoScript CSS + * 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 + */ + +.fileinput-button i, +.fileupload-buttonbar .delete, +.fileupload-buttonbar .toggle { + display: none; +} diff --git a/vendor/assets/stylesheets/jquery.fileupload-ui.scss b/vendor/assets/stylesheets/jquery.fileupload-ui.css.scss similarity index 56% rename from vendor/assets/stylesheets/jquery.fileupload-ui.scss rename to vendor/assets/stylesheets/jquery.fileupload-ui.css.scss index 72bfcb6..b349a0f 100755 --- a/vendor/assets/stylesheets/jquery.fileupload-ui.scss +++ b/vendor/assets/stylesheets/jquery.fileupload-ui.css.scss @@ -1,6 +1,6 @@ @charset "UTF-8"; /* - * jQuery File Upload UI Plugin CSS 8.0 + * jQuery File Upload UI Plugin CSS * https://github.com/blueimp/jQuery-File-Upload * * Copyright 2010, Sebastian Tschan @@ -10,40 +10,30 @@ * http://www.opensource.org/licenses/MIT */ -.fileinput-button { - position: relative; - overflow: hidden; -} -.fileinput-button input { - position: absolute; - top: 0; - right: 0; - margin: 0; - opacity: 0; - filter: alpha(opacity=0); - transform: translate(-300px, 0) scale(4); - font-size: 23px; - direction: ltr; - cursor: pointer; -} .fileupload-buttonbar .btn, .fileupload-buttonbar .toggle { margin-bottom: 5px; } +.progress-animated .progress-bar, .progress-animated .bar { - background: url(../img/progressbar.gif) !important; + background: image-url("progressbar.gif") !important; filter: none; } -.fileupload-loading { +.fileupload-process { float: right; + display: none; +} +.fileupload-processing .fileupload-process, +.files .processing .preview { + display: block; width: 32px; height: 32px; - background: url(../img/loading.gif) center no-repeat; + background: image-url("loading.gif") center no-repeat; background-size: contain; - display: none; } -.fileupload-processing .fileupload-loading { - display: block; +.files audio, +.files video { + max-width: 300px; } @media (max-width: 767px) { @@ -56,4 +46,12 @@ width: 80px; word-wrap: break-word; } + .files audio, + .files video { + max-width: 80px; + } + .files img, + .files canvas { + max-width: 100%; + } } diff --git a/vendor/assets/stylesheets/jquery.fileupload.css b/vendor/assets/stylesheets/jquery.fileupload.css new file mode 100755 index 0000000..f714c4d --- /dev/null +++ b/vendor/assets/stylesheets/jquery.fileupload.css @@ -0,0 +1,37 @@ +@charset "UTF-8"; +/* + * jQuery File Upload Plugin CSS + * 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 + */ + +.fileinput-button { + position: relative; + overflow: hidden; + display: inline-block; +} +.fileinput-button input { + position: absolute; + top: 0; + right: 0; + margin: 0; + opacity: 0; + -ms-filter: 'alpha(opacity=0)'; + font-size: 200px !important; + direction: ltr; + cursor: pointer; +} + +/* Fixes for IE < 8 */ +@media screen\9 { + .fileinput-button input { + filter: alpha(opacity=0); + font-size: 100%; + height: 100%; + } +} diff --git a/vendor/assets/stylesheets/vendor/jquery.Jcrop.css.scss b/vendor/assets/stylesheets/vendor/jquery.Jcrop.css.scss new file mode 100755 index 0000000..0800a78 --- /dev/null +++ b/vendor/assets/stylesheets/vendor/jquery.Jcrop.css.scss @@ -0,0 +1,165 @@ +/* jquery.Jcrop.css v0.9.12 - MIT License */ +/* + The outer-most container in a typical Jcrop instance + If you are having difficulty with formatting related to styles + on a parent element, place any fixes here or in a like selector + + You can also style this element if you want to add a border, etc + A better method for styling can be seen below with .jcrop-light + (Add a class to the holder and style elements for that extended class) +*/ +.jcrop-holder { + direction: ltr; + text-align: left; +} +/* Selection Border */ +.jcrop-vline, +.jcrop-hline { + background: #ffffff image-url("Jcrop.gif"); + font-size: 0; + position: absolute; +} +.jcrop-vline { + height: 100%; + width: 1px !important; +} +.jcrop-vline.right { + right: 0; +} +.jcrop-hline { + height: 1px !important; + width: 100%; +} +.jcrop-hline.bottom { + bottom: 0; +} +/* Invisible click targets */ +.jcrop-tracker { + height: 100%; + width: 100%; + /* "turn off" link highlight */ + -webkit-tap-highlight-color: transparent; + /* disable callout, image save panel */ + -webkit-touch-callout: none; + /* disable cut copy paste */ + -webkit-user-select: none; +} +/* Selection Handles */ +.jcrop-handle { + background-color: #333333; + border: 1px #eeeeee solid; + width: 7px; + height: 7px; + font-size: 1px; +} +.jcrop-handle.ord-n { + left: 50%; + margin-left: -4px; + margin-top: -4px; + top: 0; +} +.jcrop-handle.ord-s { + bottom: 0; + left: 50%; + margin-bottom: -4px; + margin-left: -4px; +} +.jcrop-handle.ord-e { + margin-right: -4px; + margin-top: -4px; + right: 0; + top: 50%; +} +.jcrop-handle.ord-w { + left: 0; + margin-left: -4px; + margin-top: -4px; + top: 50%; +} +.jcrop-handle.ord-nw { + left: 0; + margin-left: -4px; + margin-top: -4px; + top: 0; +} +.jcrop-handle.ord-ne { + margin-right: -4px; + margin-top: -4px; + right: 0; + top: 0; +} +.jcrop-handle.ord-se { + bottom: 0; + margin-bottom: -4px; + margin-right: -4px; + right: 0; +} +.jcrop-handle.ord-sw { + bottom: 0; + left: 0; + margin-bottom: -4px; + margin-left: -4px; +} +/* Dragbars */ +.jcrop-dragbar.ord-n, +.jcrop-dragbar.ord-s { + height: 7px; + width: 100%; +} +.jcrop-dragbar.ord-e, +.jcrop-dragbar.ord-w { + height: 100%; + width: 7px; +} +.jcrop-dragbar.ord-n { + margin-top: -4px; +} +.jcrop-dragbar.ord-s { + bottom: 0; + margin-bottom: -4px; +} +.jcrop-dragbar.ord-e { + margin-right: -4px; + right: 0; +} +.jcrop-dragbar.ord-w { + margin-left: -4px; +} +/* The "jcrop-light" class/extension */ +.jcrop-light .jcrop-vline, +.jcrop-light .jcrop-hline { + background: #ffffff; + filter: alpha(opacity=70) !important; + opacity: .70!important; +} +.jcrop-light .jcrop-handle { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + background-color: #000000; + border-color: #ffffff; + border-radius: 3px; +} +/* The "jcrop-dark" class/extension */ +.jcrop-dark .jcrop-vline, +.jcrop-dark .jcrop-hline { + background: #000000; + filter: alpha(opacity=70) !important; + opacity: 0.7 !important; +} +.jcrop-dark .jcrop-handle { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + background-color: #ffffff; + border-color: #000000; + border-radius: 3px; +} +/* Simple macro to turn off the antlines */ +.solid-line .jcrop-vline, +.solid-line .jcrop-hline { + background: #ffffff; +} +/* Fix for twitter bootstrap et al. */ +.jcrop-holder img, +img.jcrop-preview { + max-width: none; +} diff --git a/vendor/assets/stylesheets/vendor/jquery.Jcrop.min.css.scss b/vendor/assets/stylesheets/vendor/jquery.Jcrop.min.css.scss new file mode 100755 index 0000000..cda0deb --- /dev/null +++ b/vendor/assets/stylesheets/vendor/jquery.Jcrop.min.css.scss @@ -0,0 +1,29 @@ +/* jquery.Jcrop.min.css v0.9.12 (build:20130126) */ +.jcrop-holder{direction:ltr;text-align:left;} +.jcrop-vline,.jcrop-hline{background:#FFF image-url("Jcrop.gif");font-size:0;position:absolute;} +.jcrop-vline{height:100%;width:1px!important;} +.jcrop-vline.right{right:0;} +.jcrop-hline{height:1px!important;width:100%;} +.jcrop-hline.bottom{bottom:0;} +.jcrop-tracker{-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;height:100%;width:100%;} +.jcrop-handle{background-color:#333;border:1px #EEE solid;font-size:1px;height:7px;width:7px;} +.jcrop-handle.ord-n{left:50%;margin-left:-4px;margin-top:-4px;top:0;} +.jcrop-handle.ord-s{bottom:0;left:50%;margin-bottom:-4px;margin-left:-4px;} +.jcrop-handle.ord-e{margin-right:-4px;margin-top:-4px;right:0;top:50%;} +.jcrop-handle.ord-w{left:0;margin-left:-4px;margin-top:-4px;top:50%;} +.jcrop-handle.ord-nw{left:0;margin-left:-4px;margin-top:-4px;top:0;} +.jcrop-handle.ord-ne{margin-right:-4px;margin-top:-4px;right:0;top:0;} +.jcrop-handle.ord-se{bottom:0;margin-bottom:-4px;margin-right:-4px;right:0;} +.jcrop-handle.ord-sw{bottom:0;left:0;margin-bottom:-4px;margin-left:-4px;} +.jcrop-dragbar.ord-n,.jcrop-dragbar.ord-s{height:7px;width:100%;} +.jcrop-dragbar.ord-e,.jcrop-dragbar.ord-w{height:100%;width:7px;} +.jcrop-dragbar.ord-n{margin-top:-4px;} +.jcrop-dragbar.ord-s{bottom:0;margin-bottom:-4px;} +.jcrop-dragbar.ord-e{margin-right:-4px;right:0;} +.jcrop-dragbar.ord-w{margin-left:-4px;} +.jcrop-light .jcrop-vline,.jcrop-light .jcrop-hline{background:#FFF;filter:alpha(opacity=70)!important;opacity:.70!important;} +.jcrop-light .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#000;border-color:#FFF;border-radius:3px;} +.jcrop-dark .jcrop-vline,.jcrop-dark .jcrop-hline{background:#000;filter:alpha(opacity=70)!important;opacity:.7!important;} +.jcrop-dark .jcrop-handle{-moz-border-radius:3px;-webkit-border-radius:3px;background-color:#FFF;border-color:#000;border-radius:3px;} +.solid-line .jcrop-vline,.solid-line .jcrop-hline{background:#FFF;} +.jcrop-holder img,img.jcrop-preview{max-width:none;}