Make the archive module work (it needs more details)
This commit is contained in:
		
							parent
							
								
									73fd9d1f97
								
							
						
					
					
						commit
						3c85f3ef00
					
				|  | @ -37,7 +37,6 @@ class Panel::Archive::BackEnd::ArchiveFileCategorysController < OrbitBackendCont | |||
|   # GET /archive_files/1/edit | ||||
|   def edit | ||||
|     @archive_file_category = ArchiveFileCategory.find(params[:id]) | ||||
|     @i18n_variable = @archive_file_category.i18n_variable	 | ||||
| 	 | ||||
| 	@url = panel_archive_back_end_archive_file_category_path(@archive_file_category) | ||||
| 
 | ||||
|  |  | |||
|  | @ -55,7 +55,6 @@ class Panel::Archive::BackEnd::ArchiveFilesController < OrbitBackendController | |||
|   # POST /archive_files.xml | ||||
|   def create | ||||
|     @archive_file = ArchiveFile.new(params[:archive_file]) | ||||
| 	 | ||||
|     @archive_file.create_user_id = current_user.id | ||||
|     @archive_file.update_user_id = current_user.id | ||||
| 
 | ||||
|  | @ -64,6 +63,8 @@ class Panel::Archive::BackEnd::ArchiveFilesController < OrbitBackendController | |||
|         format.html { redirect_to(panel_archive_back_end_archive_files_url) } | ||||
|         format.xml  { render :xml => @archive_file, :status => :created, :location => @archive_file } | ||||
|       else | ||||
|         get_categorys | ||||
|         get_tags | ||||
|         format.html { render :action => "new" } | ||||
|         format.xml  { render :xml => @archive_file.errors, :status => :unprocessable_entity } | ||||
|       end | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ class Panel::Archive::FrontEnd::ArchiveFilesController < OrbitWidgetController | |||
|      | ||||
| 	@item = Page.find(params[:page_id]) | ||||
| 	 | ||||
| 	@title = @item.i18n_variable[I18n.locale] | ||||
| 	@title = @item.title | ||||
|    | ||||
|   	if @item.frontend_data_count | ||||
| 		@page_num = @item.frontend_data_count | ||||
|  | @ -41,7 +41,7 @@ class Panel::Archive::FrontEnd::ArchiveFilesController < OrbitWidgetController | |||
|      | ||||
| 	@item = Page.find(params[:page_id]) | ||||
| 	 | ||||
| 	@title = @item.i18n_variable[I18n.locale] | ||||
| 	@title = @item.title | ||||
| 	 | ||||
|     @archive_file = ArchiveFile.find(params[:id]) | ||||
| 	 | ||||
|  | @ -55,7 +55,7 @@ class Panel::Archive::FrontEnd::ArchiveFilesController < OrbitWidgetController | |||
|      | ||||
| 	@item = Page.find(params[:page_id]) | ||||
| 	 | ||||
| 	@title = @item.i18n_variable[I18n.locale] | ||||
| 	@title = @item.title | ||||
|    | ||||
|   	if @item.frontend_data_count | ||||
| 		@page_num = @item.frontend_data_count | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ class ArchiveFile | |||
| 
 | ||||
|   accepts_nested_attributes_for :archive_file_multiples, :allow_destroy => true | ||||
|    | ||||
|   validates_presence_of :title | ||||
|   validates :title, :at_least_one => true | ||||
|    | ||||
|   after_save :save_archive_file_multiples | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,8 +7,10 @@ class ArchiveFileCategory | |||
|    | ||||
|   field :key | ||||
|    | ||||
|   has_one :i18n_variable, :as => :language_value, :autosave => true, :dependent => :destroy | ||||
|   field :title, localize: true | ||||
|    | ||||
|   has_many :archive_files | ||||
| 
 | ||||
|   validates :title, :at_least_one => true | ||||
|    | ||||
| end | ||||
|  | @ -9,8 +9,6 @@ class ArchiveFileMultiple | |||
|   # field :description | ||||
|   field :choose_lang, :type => Array, :default => nil | ||||
|    | ||||
|   # has_one :i18n_variable, :as => :language_value, :autosave => true, :dependent => :destroy | ||||
|    | ||||
|   field :should_destroy, :type => Boolean | ||||
| 
 | ||||
|   def choose_lang_display(lang) | ||||
|  |  | |||
|  | @ -11,6 +11,6 @@ | |||
| 			</div> | ||||
| 		</td> | ||||
| 		<% @site_valid_locales.each do |locale| %> | ||||
| 		<td><%= archive_file_category.i18n_variable[locale] rescue nil %></td> | ||||
| 		<td><%= archive_file_category.title_translations[locale] rescue nil %></td> | ||||
| 		<% end %> | ||||
| 	</tr> | ||||
|  | @ -10,12 +10,12 @@ | |||
| 	</div> | ||||
| 	 | ||||
| 	<div id="widget-title"> | ||||
| 		<%= f.fields_for :i18n_variable, (@archive_file_category.new_record? ? @archive_file_category.build_i18n_variable : @archive_file_category.i18n_variable) do |f| %> | ||||
| 		<%= f.fields_for :title_translations do |f| %> | ||||
| 		  <% @site_valid_locales.each do |locale| %> | ||||
| 				<div class="control-group"> | ||||
| 					<%= label_tag "name-#{locale}", "Name-#{I18nVariable.from_locale(locale)}", :class => 'control-label' %> | ||||
| 					<div class="controls"> | ||||
| 						<%= f.text_field locale, :class => 'input-xxlarge' %> | ||||
| 						<%= f.text_field locale, :class =>' input-xxlarge', :value => (@archive_file_category.title[locale] rescue nil) %> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 		  <% end %> | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| 			</ul> | ||||
| 		</div> | ||||
| 	</td> | ||||
| 	<td><%= post.archive_file_category.i18n_variable[I18n.locale] %></td> | ||||
| 	<td><%= post.archive_file_category.title %></td> | ||||
| 	<td> | ||||
| 	<%= link_to post.title, panel_archive_front_end_archive_file_path(post) %> | ||||
| 	</td> | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ | |||
| 		<div id="post-body-content" class="clear"> | ||||
| 		 | ||||
| 			<%= f.label :category %> | ||||
| 			<%= f.select :archive_file_category_id, @archive_file_categorys.collect {|t| [ t.i18n_variable[I18n.locale], t.id ]} %> | ||||
| 			<%= f.select :archive_file_category_id, @archive_file_categorys.collect {|t| [ t.title, t.id ]} %> | ||||
| 			 | ||||
| 			<ul class="nav nav-tabs"> | ||||
| 				<% @site_valid_locales.each_with_index do |locale, i| %> | ||||
|  | @ -74,7 +74,7 @@ | |||
| 			 | ||||
| 			<div> | ||||
| 						 | ||||
| 				<div id='archive_file_multiples' class="archive_file_multiples_block"> | ||||
| 				<div class="archive_file_multiples_block"> | ||||
| 					 | ||||
| 				<table class="table table-condensed"> | ||||
| 					<thead> | ||||
|  |  | |||
|  | @ -1,219 +0,0 @@ | |||
| /* | ||||
|  * jQuery File Upload File Processing Plugin 1.0 | ||||
|  * https://github.com/blueimp/jQuery-File-Upload
 | ||||
|  * | ||||
|  * Copyright 2012, Sebastian Tschan | ||||
|  * https://blueimp.net
 | ||||
|  * | ||||
|  * Licensed under the MIT license: | ||||
|  * http://www.opensource.org/licenses/MIT
 | ||||
|  */ | ||||
| 
 | ||||
| /*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 IP version extends the basic fileupload widget
 | ||||
|     // with file processing functionality:
 | ||||
|     $.widget('blueimpFP.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) { | ||||
|                 $(this).fileupload('process', data).done(function () { | ||||
|                     data.submit(); | ||||
|                 }); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         processActions: { | ||||
|             // Loads the image given via data.files and data.index
 | ||||
|             // as canvas element.
 | ||||
|             // 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 (canvas) { | ||||
|                             data.canvas = canvas; | ||||
|                             dfd.resolveWith(that, [data]); | ||||
|                         }, | ||||
|                         {canvas: true} | ||||
|                     ); | ||||
|                 } else { | ||||
|                     dfd.rejectWith(that, [data]); | ||||
|                 } | ||||
|                 return dfd.promise(); | ||||
|             }, | ||||
|             // Resizes the image given as data.canvas and updates
 | ||||
|             // data.canvas with the resized image.
 | ||||
|             // Accepts the options maxWidth, maxHeight, minWidth and
 | ||||
|             // minHeight to scale the given image:
 | ||||
|             resize: function (data, options) { | ||||
|                 if (data.canvas) { | ||||
|                     var canvas = loadImage.scale(data.canvas, options); | ||||
|                     if (canvas.width !== data.canvas.width || | ||||
|                             canvas.height !== data.canvas.height) { | ||||
|                         data.canvas = canvas; | ||||
|                         data.processed = true; | ||||
|                     } | ||||
|                 } | ||||
|                 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 || !data.processed) { | ||||
|                     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 () { | ||||
|             $.blueimp.fileupload.prototype._create.call(this); | ||||
|             this._processing = 0; | ||||
|             this._processingQueue = $.Deferred().resolveWith(this) | ||||
|                 .promise(); | ||||
|         } | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
| })); | ||||
|  | @ -1,736 +0,0 @@ | |||
| /* | ||||
|  * jQuery File Upload User Interface Plugin 6.9.4 | ||||
|  * https://github.com/blueimp/jQuery-File-Upload
 | ||||
|  * | ||||
|  * Copyright 2010, Sebastian Tschan | ||||
|  * https://blueimp.net
 | ||||
|  * | ||||
|  * Licensed under the MIT license: | ||||
|  * http://www.opensource.org/licenses/MIT
 | ||||
|  */ | ||||
| 
 | ||||
| /*jslint nomen: true, unparam: true, regexp: true */ | ||||
| /*global define, window, document, URL, webkitURL, FileReader */ | ||||
| 
 | ||||
| (function (factory) { | ||||
|     'use strict'; | ||||
|     if (typeof define === 'function' && define.amd) { | ||||
|         // Register as an anonymous AMD module:
 | ||||
|         define([ | ||||
|             'jquery', | ||||
|             'tmpl', | ||||
|             'load-image', | ||||
|             './jquery.fileupload-fp' | ||||
|         ], factory); | ||||
|     } else { | ||||
|         // Browser globals:
 | ||||
|         factory( | ||||
|             window.jQuery, | ||||
|             window.tmpl, | ||||
|             window.loadImage | ||||
|         ); | ||||
|     } | ||||
| }(function ($, tmpl, loadImage) { | ||||
|     'use strict'; | ||||
| 
 | ||||
|     // The UI version extends the FP (file processing) version or the basic
 | ||||
|     // file upload widget and adds complete user interface interaction:
 | ||||
|     var parentWidget = ($.blueimpFP || $.blueimp).fileupload; | ||||
|     $.widget('blueimpUI.fileupload', parentWidget, { | ||||
| 
 | ||||
|         options: { | ||||
|             // By default, files added to the widget are uploaded as soon
 | ||||
|             // as the user clicks on the start buttons. To enable automatic
 | ||||
|             // uploads, set the following option to true:
 | ||||
|             autoUpload: false, | ||||
|             // The following option limits the number of files that are
 | ||||
|             // allowed to be uploaded using this widget:
 | ||||
|             maxNumberOfFiles: undefined, | ||||
|             // The maximum allowed file size:
 | ||||
|             maxFileSize: undefined, | ||||
|             // The minimum allowed file size:
 | ||||
|             minFileSize: undefined, | ||||
|             // The regular expression for allowed file types, matches
 | ||||
|             // against either file type or file name:
 | ||||
|             acceptFileTypes:  /.+$/i, | ||||
|             // The regular expression to define for which files a preview
 | ||||
|             // image is shown, matched against the file type:
 | ||||
|             previewSourceFileTypes: /^image\/(gif|jpeg|png)$/, | ||||
|             // The maximum file size of images that are to be displayed as preview:
 | ||||
|             previewSourceMaxFileSize: 5000000, // 5MB
 | ||||
|             // The maximum width of the preview images:
 | ||||
|             previewMaxWidth: 80, | ||||
|             // The maximum height of the preview images:
 | ||||
|             previewMaxHeight: 80, | ||||
|             // By default, preview images are displayed as canvas elements
 | ||||
|             // if supported by the browser. Set the following option to false
 | ||||
|             // to always display preview images as img elements:
 | ||||
|             previewAsCanvas: true, | ||||
|             // The ID of the upload template:
 | ||||
|             uploadTemplateId: 'template-upload', | ||||
|             // The ID of the download template:
 | ||||
|             downloadTemplateId: 'template-download', | ||||
|             // The container for the list of files. If undefined, it is set to
 | ||||
|             // an element with class "files" inside of the widget element:
 | ||||
|             filesContainer: undefined, | ||||
|             // By default, files are appended to the files container.
 | ||||
|             // Set the following option to true, to prepend files instead:
 | ||||
|             prependFiles: false, | ||||
|             // The expected data type of the upload response, sets the dataType
 | ||||
|             // option of the $.ajax upload requests:
 | ||||
|             dataType: 'json', | ||||
| 
 | ||||
|             // The add callback is invoked as soon as files are added to the fileupload
 | ||||
|             // widget (via file input selection, drag & drop or add API call).
 | ||||
|             // See the basic file upload widget for more information:
 | ||||
|             add: function (e, data) { | ||||
|                 var that = $(this).data('fileupload'), | ||||
|                     options = that.options, | ||||
|                     files = data.files; | ||||
|                 $(this).fileupload('process', data).done(function () { | ||||
|                     that._adjustMaxNumberOfFiles(-files.length); | ||||
|                     data.maxNumberOfFilesAdjusted = true; | ||||
|                     data.files.valid = data.isValidated = that._validate(files); | ||||
|                     data.context = that._renderUpload(files).data('data', data); | ||||
|                     options.filesContainer[ | ||||
|                         options.prependFiles ? 'prepend' : 'append' | ||||
|                     ](data.context); | ||||
|                     that._renderPreviews(files, 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.isValidated) { | ||||
|                                 data.submit(); | ||||
|                             } | ||||
|                         } | ||||
|                     ); | ||||
|                 }); | ||||
|             }, | ||||
|             // Callback for the start of each file upload request:
 | ||||
|             send: function (e, data) { | ||||
|                 var that = $(this).data('fileupload'); | ||||
|                 if (!data.isValidated) { | ||||
|                     if (!data.maxNumberOfFilesAdjusted) { | ||||
|                         that._adjustMaxNumberOfFiles(-data.files.length); | ||||
|                         data.maxNumberOfFilesAdjusted = true; | ||||
|                     } | ||||
|                     if (!that._validate(data.files)) { | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|                 if (data.context && data.dataType && | ||||
|                         data.dataType.substr(0, 6) === 'iframe') { | ||||
|                     // Iframe Transport does not support progress events.
 | ||||
|                     // In lack of an indeterminate progress bar, we set
 | ||||
|                     // the progress to 100%, showing the full animated bar:
 | ||||
|                     data.context | ||||
|                         .find('.progress').addClass( | ||||
|                             !$.support.transition && 'progress-animated' | ||||
|                         ) | ||||
|                         .attr('aria-valuenow', 100) | ||||
|                         .find('.bar').css( | ||||
|                             'width', | ||||
|                             '100%' | ||||
|                         ); | ||||
|                 } | ||||
|                 return that._trigger('sent', e, data); | ||||
|             }, | ||||
|             // Callback for successful uploads:
 | ||||
|             done: function (e, data) { | ||||
|                 var that = $(this).data('fileupload'), | ||||
|                     template; | ||||
|                 if (data.context) { | ||||
|                     data.context.each(function (index) { | ||||
|                         var file = ($.isArray(data.result) && | ||||
|                                 data.result[index]) || {error: 'emptyResult'}; | ||||
|                         if (file.error) { | ||||
|                             that._adjustMaxNumberOfFiles(1); | ||||
|                         } | ||||
|                         that._transition($(this)).done( | ||||
|                             function () { | ||||
|                                 var node = $(this); | ||||
|                                 template = that._renderDownload([file]) | ||||
|                                     .replaceAll(node); | ||||
|                                 that._forceReflow(template); | ||||
|                                 that._transition(template).done( | ||||
|                                     function () { | ||||
|                                         data.context = $(this); | ||||
|                                         that._trigger('completed', e, data); | ||||
|                                     } | ||||
|                                 ); | ||||
|                             } | ||||
|                         ); | ||||
|                     }); | ||||
|                 } else { | ||||
|                     if ($.isArray(data.result)) { | ||||
|                         $.each(data.result, function (index, file) { | ||||
|                             if (data.maxNumberOfFilesAdjusted && file.error) { | ||||
|                                 that._adjustMaxNumberOfFiles(1); | ||||
|                             } else if (!data.maxNumberOfFilesAdjusted && | ||||
|                                     !file.error) { | ||||
|                                 that._adjustMaxNumberOfFiles(-1); | ||||
|                             } | ||||
|                         }); | ||||
|                         data.maxNumberOfFilesAdjusted = true; | ||||
|                     } | ||||
|                     template = that._renderDownload(data.result) | ||||
|                         .appendTo(that.options.filesContainer); | ||||
|                     that._forceReflow(template); | ||||
|                     that._transition(template).done( | ||||
|                         function () { | ||||
|                             data.context = $(this); | ||||
|                             that._trigger('completed', e, data); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             }, | ||||
|             // Callback for failed (abort or error) uploads:
 | ||||
|             fail: function (e, data) { | ||||
|                 var that = $(this).data('fileupload'), | ||||
|                     template; | ||||
|                 if (data.maxNumberOfFilesAdjusted) { | ||||
|                     that._adjustMaxNumberOfFiles(data.files.length); | ||||
|                 } | ||||
|                 if (data.context) { | ||||
|                     data.context.each(function (index) { | ||||
|                         if (data.errorThrown !== 'abort') { | ||||
|                             var file = data.files[index]; | ||||
|                             file.error = file.error || data.errorThrown || | ||||
|                                 true; | ||||
|                             that._transition($(this)).done( | ||||
|                                 function () { | ||||
|                                     var node = $(this); | ||||
|                                     template = that._renderDownload([file]) | ||||
|                                         .replaceAll(node); | ||||
|                                     that._forceReflow(template); | ||||
|                                     that._transition(template).done( | ||||
|                                         function () { | ||||
|                                             data.context = $(this); | ||||
|                                             that._trigger('failed', e, data); | ||||
|                                         } | ||||
|                                     ); | ||||
|                                 } | ||||
|                             ); | ||||
|                         } else { | ||||
|                             that._transition($(this)).done( | ||||
|                                 function () { | ||||
|                                     $(this).remove(); | ||||
|                                     that._trigger('failed', e, data); | ||||
|                                 } | ||||
|                             ); | ||||
|                         } | ||||
|                     }); | ||||
|                 } else if (data.errorThrown !== 'abort') { | ||||
|                     data.context = that._renderUpload(data.files) | ||||
|                         .appendTo(that.options.filesContainer) | ||||
|                         .data('data', data); | ||||
|                     that._forceReflow(data.context); | ||||
|                     that._transition(data.context).done( | ||||
|                         function () { | ||||
|                             data.context = $(this); | ||||
|                             that._trigger('failed', e, data); | ||||
|                         } | ||||
|                     ); | ||||
|                 } else { | ||||
|                     that._trigger('failed', e, data); | ||||
|                 } | ||||
|             }, | ||||
|             // Callback for upload progress events:
 | ||||
|             progress: function (e, data) { | ||||
|                 if (data.context) { | ||||
|                     var progress = parseInt(data.loaded / data.total * 100, 10); | ||||
|                     data.context.find('.progress') | ||||
|                         .attr('aria-valuenow', progress) | ||||
|                         .find('.bar').css( | ||||
|                             'width', | ||||
|                             progress + '%' | ||||
|                         ); | ||||
|                 } | ||||
|             }, | ||||
|             // Callback for global upload progress events:
 | ||||
|             progressall: function (e, data) { | ||||
|                 var $this = $(this), | ||||
|                     progress = parseInt(data.loaded / data.total * 100, 10), | ||||
|                     globalProgressNode = $this.find('.fileupload-progress'), | ||||
|                     extendedProgressNode = globalProgressNode | ||||
|                         .find('.progress-extended'); | ||||
|                 if (extendedProgressNode.length) { | ||||
|                     extendedProgressNode.html( | ||||
|                         $this.data('fileupload')._renderExtendedProgress(data) | ||||
|                     ); | ||||
|                 } | ||||
|                 globalProgressNode | ||||
|                     .find('.progress') | ||||
|                     .attr('aria-valuenow', progress) | ||||
|                     .find('.bar').css( | ||||
|                         'width', | ||||
|                         progress + '%' | ||||
|                     ); | ||||
|             }, | ||||
|             // Callback for uploads start, equivalent to the global ajaxStart event:
 | ||||
|             start: function (e) { | ||||
|                 var that = $(this).data('fileupload'); | ||||
|                 that._transition($(this).find('.fileupload-progress')).done( | ||||
|                     function () { | ||||
|                         that._trigger('started', e); | ||||
|                     } | ||||
|                 ); | ||||
|             }, | ||||
|             // Callback for uploads stop, equivalent to the global ajaxStop event:
 | ||||
|             stop: function (e) { | ||||
|                 var that = $(this).data('fileupload'); | ||||
|                 that._transition($(this).find('.fileupload-progress')).done( | ||||
|                     function () { | ||||
|                         $(this).find('.progress') | ||||
|                             .attr('aria-valuenow', '0') | ||||
|                             .find('.bar').css('width', '0%'); | ||||
|                         $(this).find('.progress-extended').html(' '); | ||||
|                         that._trigger('stopped', e); | ||||
|                     } | ||||
|                 ); | ||||
|             }, | ||||
|             // Callback for file deletion:
 | ||||
|             destroy: function (e, data) { | ||||
|                 var that = $(this).data('fileupload'); | ||||
|                 if (data.url) { | ||||
|                     $.ajax(data); | ||||
|                     that._adjustMaxNumberOfFiles(1); | ||||
|                 } | ||||
|                 that._transition(data.context).done( | ||||
|                     function () { | ||||
|                         $(this).remove(); | ||||
|                         that._trigger('destroyed', e, data); | ||||
|                     } | ||||
|                 ); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         // Link handler, that allows to download files
 | ||||
|         // by drag & drop of the links to the desktop:
 | ||||
|         _enableDragToDesktop: function () { | ||||
|             var link = $(this), | ||||
|                 url = link.prop('href'), | ||||
|                 name = link.prop('download'), | ||||
|                 type = 'application/octet-stream'; | ||||
|             link.bind('dragstart', function (e) { | ||||
|                 try { | ||||
|                     e.originalEvent.dataTransfer.setData( | ||||
|                         'DownloadURL', | ||||
|                         [type, name, url].join(':') | ||||
|                     ); | ||||
|                 } catch (err) {} | ||||
|             }); | ||||
|         }, | ||||
| 
 | ||||
|         _adjustMaxNumberOfFiles: function (operand) { | ||||
|             if (typeof this.options.maxNumberOfFiles === 'number') { | ||||
|                 this.options.maxNumberOfFiles += operand; | ||||
|                 if (this.options.maxNumberOfFiles < 1) { | ||||
|                     this._disableFileInputButton(); | ||||
|                 } else { | ||||
|                     this._enableFileInputButton(); | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _formatFileSize: function (bytes) { | ||||
|             if (typeof bytes !== 'number') { | ||||
|                 return ''; | ||||
|             } | ||||
|             if (bytes >= 1000000000) { | ||||
|                 return (bytes / 1000000000).toFixed(2) + ' GB'; | ||||
|             } | ||||
|             if (bytes >= 1000000) { | ||||
|                 return (bytes / 1000000).toFixed(2) + ' MB'; | ||||
|             } | ||||
|             return (bytes / 1000).toFixed(2) + ' KB'; | ||||
|         }, | ||||
| 
 | ||||
|         _formatBitrate: function (bits) { | ||||
|             if (typeof bits !== 'number') { | ||||
|                 return ''; | ||||
|             } | ||||
|             if (bits >= 1000000000) { | ||||
|                 return (bits / 1000000000).toFixed(2) + ' Gbit/s'; | ||||
|             } | ||||
|             if (bits >= 1000000) { | ||||
|                 return (bits / 1000000).toFixed(2) + ' Mbit/s'; | ||||
|             } | ||||
|             if (bits >= 1000) { | ||||
|                 return (bits / 1000).toFixed(2) + ' kbit/s'; | ||||
|             } | ||||
|             return bits + ' bit/s'; | ||||
|         }, | ||||
| 
 | ||||
|         _formatTime: function (seconds) { | ||||
|             var date = new Date(seconds * 1000), | ||||
|                 days = parseInt(seconds / 86400, 10); | ||||
|             days = days ? days + 'd ' : ''; | ||||
|             return days + | ||||
|                 ('0' + date.getUTCHours()).slice(-2) + ':' + | ||||
|                 ('0' + date.getUTCMinutes()).slice(-2) + ':' + | ||||
|                 ('0' + date.getUTCSeconds()).slice(-2); | ||||
|         }, | ||||
| 
 | ||||
|         _formatPercentage: function (floatValue) { | ||||
|             return (floatValue * 100).toFixed(2) + ' %'; | ||||
|         }, | ||||
| 
 | ||||
|         _renderExtendedProgress: function (data) { | ||||
|             return this._formatBitrate(data.bitrate) + ' | ' + | ||||
|                 this._formatTime( | ||||
|                     (data.total - data.loaded) * 8 / data.bitrate | ||||
|                 ) + ' | ' + | ||||
|                 this._formatPercentage( | ||||
|                     data.loaded / data.total | ||||
|                 ) + ' | ' + | ||||
|                 this._formatFileSize(data.loaded) + ' / ' + | ||||
|                 this._formatFileSize(data.total); | ||||
|         }, | ||||
| 
 | ||||
|         _hasError: function (file) { | ||||
|             if (file.error) { | ||||
|                 return file.error; | ||||
|             } | ||||
|             // The number of added files is subtracted from
 | ||||
|             // maxNumberOfFiles before validation, so we check if
 | ||||
|             // maxNumberOfFiles is below 0 (instead of below 1):
 | ||||
|             if (this.options.maxNumberOfFiles < 0) { | ||||
|                 return 'maxNumberOfFiles'; | ||||
|             } | ||||
|             // Files are accepted if either the file type or the file name
 | ||||
|             // matches against the acceptFileTypes regular expression, as
 | ||||
|             // only browsers with support for the File API report the type:
 | ||||
|             if (!(this.options.acceptFileTypes.test(file.type) || | ||||
|                     this.options.acceptFileTypes.test(file.name))) { | ||||
|                 return 'acceptFileTypes'; | ||||
|             } | ||||
|             if (this.options.maxFileSize && | ||||
|                     file.size > this.options.maxFileSize) { | ||||
|                 return 'maxFileSize'; | ||||
|             } | ||||
|             if (typeof file.size === 'number' && | ||||
|                     file.size < this.options.minFileSize) { | ||||
|                 return 'minFileSize'; | ||||
|             } | ||||
|             return null; | ||||
|         }, | ||||
| 
 | ||||
|         _validate: function (files) { | ||||
|             var that = this, | ||||
|                 valid = !!files.length; | ||||
|             $.each(files, function (index, file) { | ||||
|                 file.error = that._hasError(file); | ||||
|                 if (file.error) { | ||||
|                     valid = false; | ||||
|                 } | ||||
|             }); | ||||
|             return valid; | ||||
|         }, | ||||
| 
 | ||||
|         _renderTemplate: function (func, files) { | ||||
|             if (!func) { | ||||
|                 return $(); | ||||
|             } | ||||
|             var result = func({ | ||||
|                 files: files, | ||||
|                 formatFileSize: this._formatFileSize, | ||||
|                 options: this.options | ||||
|             }); | ||||
|             if (result instanceof $) { | ||||
|                 return result; | ||||
|             } | ||||
|             return $(this.options.templatesContainer).html(result).children(); | ||||
|         }, | ||||
| 
 | ||||
|         _renderPreview: function (file, node) { | ||||
|             var that = this, | ||||
|                 options = this.options, | ||||
|                 dfd = $.Deferred(); | ||||
|             return ((loadImage && loadImage( | ||||
|                 file, | ||||
|                 function (img) { | ||||
|                     node.append(img); | ||||
|                     that._forceReflow(node); | ||||
|                     that._transition(node).done(function () { | ||||
|                         dfd.resolveWith(node); | ||||
|                     }); | ||||
|                     if (!$.contains(document.body, node[0])) { | ||||
|                         // If the element is not part of the DOM,
 | ||||
|                         // transition events are not triggered,
 | ||||
|                         // so we have to resolve manually:
 | ||||
|                         dfd.resolveWith(node); | ||||
|                     } | ||||
|                 }, | ||||
|                 { | ||||
|                     maxWidth: options.previewMaxWidth, | ||||
|                     maxHeight: options.previewMaxHeight, | ||||
|                     canvas: options.previewAsCanvas | ||||
|                 } | ||||
|             )) || dfd.resolveWith(node)) && dfd; | ||||
|         }, | ||||
| 
 | ||||
|         _renderPreviews: function (files, nodes) { | ||||
|             var that = this, | ||||
|                 options = this.options; | ||||
|             nodes.find('.preview span').each(function (index, element) { | ||||
|                 var file = files[index]; | ||||
|                 if (options.previewSourceFileTypes.test(file.type) && | ||||
|                         ($.type(options.previewSourceMaxFileSize) !== 'number' || | ||||
|                         file.size < options.previewSourceMaxFileSize)) { | ||||
|                     that._processingQueue = that._processingQueue.pipe(function () { | ||||
|                         var dfd = $.Deferred(); | ||||
|                         that._renderPreview(file, $(element)).done( | ||||
|                             function () { | ||||
|                                 dfd.resolveWith(that); | ||||
|                             } | ||||
|                         ); | ||||
|                         return dfd.promise(); | ||||
|                     }); | ||||
|                 } | ||||
|             }); | ||||
|             return this._processingQueue; | ||||
|         }, | ||||
| 
 | ||||
|         _renderUpload: function (files) { | ||||
|             return this._renderTemplate( | ||||
|                 this.options.uploadTemplate, | ||||
|                 files | ||||
|             ); | ||||
|         }, | ||||
| 
 | ||||
|         _renderDownload: function (files) { | ||||
|             return this._renderTemplate( | ||||
|                 this.options.downloadTemplate, | ||||
|                 files | ||||
|             ).find('a[download]').each(this._enableDragToDesktop).end(); | ||||
|         }, | ||||
| 
 | ||||
|         _startHandler: function (e) { | ||||
|             e.preventDefault(); | ||||
|             var button = $(this), | ||||
|                 template = button.closest('.template-upload'), | ||||
|                 data = template.data('data'); | ||||
|             if (data && data.submit && !data.jqXHR && data.submit()) { | ||||
|                 button.prop('disabled', true); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _cancelHandler: function (e) { | ||||
|             e.preventDefault(); | ||||
|             var template = $(this).closest('.template-upload'), | ||||
|                 data = template.data('data') || {}; | ||||
|             if (!data.jqXHR) { | ||||
|                 data.errorThrown = 'abort'; | ||||
|                 e.data.fileupload._trigger('fail', e, data); | ||||
|             } else { | ||||
|                 data.jqXHR.abort(); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _deleteHandler: function (e) { | ||||
|             e.preventDefault(); | ||||
|             var button = $(this); | ||||
|             e.data.fileupload._trigger('destroy', e, { | ||||
|                 context: button.closest('.template-download'), | ||||
|                 url: button.attr('data-url'), | ||||
|                 type: button.attr('data-type') || 'DELETE', | ||||
|                 dataType: e.data.fileupload.options.dataType | ||||
|             }); | ||||
|         }, | ||||
| 
 | ||||
|         _forceReflow: function (node) { | ||||
|             return $.support.transition && node.length && | ||||
|                 node[0].offsetWidth; | ||||
|         }, | ||||
| 
 | ||||
|         _transition: function (node) { | ||||
|             var dfd = $.Deferred(); | ||||
|             if ($.support.transition && node.hasClass('fade')) { | ||||
|                 node.bind( | ||||
|                     $.support.transition.end, | ||||
|                     function (e) { | ||||
|                         // Make sure we don't respond to other transitions events
 | ||||
|                         // in the container element, e.g. from button elements:
 | ||||
|                         if (e.target === node[0]) { | ||||
|                             node.unbind($.support.transition.end); | ||||
|                             dfd.resolveWith(node); | ||||
|                         } | ||||
|                     } | ||||
|                 ).toggleClass('in'); | ||||
|             } else { | ||||
|                 node.toggleClass('in'); | ||||
|                 dfd.resolveWith(node); | ||||
|             } | ||||
|             return dfd; | ||||
|         }, | ||||
| 
 | ||||
|         _initButtonBarEventHandlers: function () { | ||||
|             var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'), | ||||
|                 filesList = this.options.filesContainer, | ||||
|                 ns = this.options.namespace; | ||||
|             fileUploadButtonBar.find('.start') | ||||
|                 .bind('click.' + ns, function (e) { | ||||
|                     e.preventDefault(); | ||||
|                     filesList.find('.start button').click(); | ||||
|                 }); | ||||
|             fileUploadButtonBar.find('.cancel') | ||||
|                 .bind('click.' + ns, function (e) { | ||||
|                     e.preventDefault(); | ||||
|                     filesList.find('.cancel button').click(); | ||||
|                 }); | ||||
|             fileUploadButtonBar.find('.delete') | ||||
|                 .bind('click.' + ns, function (e) { | ||||
|                     e.preventDefault(); | ||||
|                     filesList.find('.delete input:checked') | ||||
|                         .siblings('button').click(); | ||||
|                     fileUploadButtonBar.find('.toggle') | ||||
|                         .prop('checked', false); | ||||
|                 }); | ||||
|             fileUploadButtonBar.find('.toggle') | ||||
|                 .bind('change.' + ns, function (e) { | ||||
|                     filesList.find('.delete input').prop( | ||||
|                         'checked', | ||||
|                         $(this).is(':checked') | ||||
|                     ); | ||||
|                 }); | ||||
|         }, | ||||
| 
 | ||||
|         _destroyButtonBarEventHandlers: function () { | ||||
|             this.element.find('.fileupload-buttonbar button') | ||||
|                 .unbind('click.' + this.options.namespace); | ||||
|             this.element.find('.fileupload-buttonbar .toggle') | ||||
|                 .unbind('change.' + this.options.namespace); | ||||
|         }, | ||||
| 
 | ||||
|         _initEventHandlers: function () { | ||||
|             parentWidget.prototype._initEventHandlers.call(this); | ||||
|             var eventData = {fileupload: this}; | ||||
|             this.options.filesContainer | ||||
|                 .delegate( | ||||
|                     '.start button', | ||||
|                     'click.' + this.options.namespace, | ||||
|                     eventData, | ||||
|                     this._startHandler | ||||
|                 ) | ||||
|                 .delegate( | ||||
|                     '.cancel button', | ||||
|                     'click.' + this.options.namespace, | ||||
|                     eventData, | ||||
|                     this._cancelHandler | ||||
|                 ) | ||||
|                 .delegate( | ||||
|                     '.delete button', | ||||
|                     'click.' + this.options.namespace, | ||||
|                     eventData, | ||||
|                     this._deleteHandler | ||||
|                 ); | ||||
|             this._initButtonBarEventHandlers(); | ||||
|         }, | ||||
| 
 | ||||
|         _destroyEventHandlers: function () { | ||||
|             var options = this.options; | ||||
|             this._destroyButtonBarEventHandlers(); | ||||
|             options.filesContainer | ||||
|                 .undelegate('.start button', 'click.' + options.namespace) | ||||
|                 .undelegate('.cancel button', 'click.' + options.namespace) | ||||
|                 .undelegate('.delete button', 'click.' + options.namespace); | ||||
|             parentWidget.prototype._destroyEventHandlers.call(this); | ||||
|         }, | ||||
| 
 | ||||
|         _enableFileInputButton: function () { | ||||
|             this.element.find('.fileinput-button input') | ||||
|                 .prop('disabled', false) | ||||
|                 .parent().removeClass('disabled'); | ||||
|         }, | ||||
| 
 | ||||
|         _disableFileInputButton: function () { | ||||
|             this.element.find('.fileinput-button input') | ||||
|                 .prop('disabled', true) | ||||
|                 .parent().addClass('disabled'); | ||||
|         }, | ||||
| 
 | ||||
|         _initTemplates: function () { | ||||
|             var options = this.options; | ||||
|             options.templatesContainer = document.createElement( | ||||
|                 options.filesContainer.prop('nodeName') | ||||
|             ); | ||||
|             if (tmpl) { | ||||
|                 if (options.uploadTemplateId) { | ||||
|                     options.uploadTemplate = tmpl(options.uploadTemplateId); | ||||
|                 } | ||||
|                 if (options.downloadTemplateId) { | ||||
|                     options.downloadTemplate = tmpl(options.downloadTemplateId); | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _initFilesContainer: function () { | ||||
|             var options = this.options; | ||||
|             if (options.filesContainer === undefined) { | ||||
|                 options.filesContainer = this.element.find('.files'); | ||||
|             } else if (!(options.filesContainer instanceof $)) { | ||||
|                 options.filesContainer = $(options.filesContainer); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _stringToRegExp: function (str) { | ||||
|             var parts = str.split('/'), | ||||
|                 modifiers = parts.pop(); | ||||
|             parts.shift(); | ||||
|             return new RegExp(parts.join('/'), modifiers); | ||||
|         }, | ||||
| 
 | ||||
|         _initRegExpOptions: function () { | ||||
|             var options = this.options; | ||||
|             if ($.type(options.acceptFileTypes) === 'string') { | ||||
|                 options.acceptFileTypes = this._stringToRegExp( | ||||
|                     options.acceptFileTypes | ||||
|                 ); | ||||
|             } | ||||
|             if ($.type(options.previewSourceFileTypes) === 'string') { | ||||
|                 options.previewSourceFileTypes = this._stringToRegExp( | ||||
|                     options.previewSourceFileTypes | ||||
|                 ); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _initSpecialOptions: function () { | ||||
|             parentWidget.prototype._initSpecialOptions.call(this); | ||||
|             this._initFilesContainer(); | ||||
|             this._initTemplates(); | ||||
|             this._initRegExpOptions(); | ||||
|         }, | ||||
| 
 | ||||
|         _create: function () { | ||||
|             parentWidget.prototype._create.call(this); | ||||
|             this._refreshOptionsList.push( | ||||
|                 'filesContainer', | ||||
|                 'uploadTemplateId', | ||||
|                 'downloadTemplateId' | ||||
|             ); | ||||
|             if (!$.blueimpFP) { | ||||
|                 this._processingQueue = $.Deferred().resolveWith(this).promise(); | ||||
|                 this.process = function () { | ||||
|                     return this._processingQueue; | ||||
|                 }; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         enable: function () { | ||||
|             parentWidget.prototype.enable.call(this); | ||||
|             this.element.find('input, button').prop('disabled', false); | ||||
|             this._enableFileInputButton(); | ||||
|         }, | ||||
| 
 | ||||
|         disable: function () { | ||||
|             this.element.find('input, button').prop('disabled', true); | ||||
|             this._disableFileInputButton(); | ||||
|             parentWidget.prototype.disable.call(this); | ||||
|         } | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
| })); | ||||
|  | @ -1,975 +0,0 @@ | |||
| /* | ||||
|  * jQuery File Upload Plugin 5.14 | ||||
|  * https://github.com/blueimp/jQuery-File-Upload
 | ||||
|  * | ||||
|  * Copyright 2010, Sebastian Tschan | ||||
|  * https://blueimp.net
 | ||||
|  * | ||||
|  * Licensed under the MIT license: | ||||
|  * http://www.opensource.org/licenses/MIT
 | ||||
|  */ | ||||
| 
 | ||||
| /*jslint nomen: true, unparam: true, regexp: true */ | ||||
| /*global define, window, document, Blob, FormData, location */ | ||||
| 
 | ||||
| (function (factory) { | ||||
|     'use strict'; | ||||
|     if (typeof define === 'function' && define.amd) { | ||||
|         // Register as an anonymous AMD module:
 | ||||
|         define([ | ||||
|             'jquery', | ||||
|             'jquery.ui.widget' | ||||
|         ], factory); | ||||
|     } else { | ||||
|         // Browser globals:
 | ||||
|         factory(window.jQuery); | ||||
|     } | ||||
| }(function ($) { | ||||
|     'use strict'; | ||||
| 
 | ||||
|     // The FileReader API is not actually used, but works as feature detection,
 | ||||
|     // as e.g. Safari supports XHR file uploads via the FormData API,
 | ||||
|     // but not non-multipart XHR file uploads:
 | ||||
|     $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader); | ||||
|     $.support.xhrFormDataFileUpload = !!window.FormData; | ||||
| 
 | ||||
|     // 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
 | ||||
|     // exposes the "add" and "send" methods, to add or directly send files using
 | ||||
|     // the fileupload API.
 | ||||
|     // By default, files added via file input selection, paste, drag & drop or
 | ||||
|     // "add" method are uploaded immediately, but it is possible to override
 | ||||
|     // the "add" callback option to queue file uploads.
 | ||||
|     $.widget('blueimp.fileupload', { | ||||
| 
 | ||||
|         options: { | ||||
|             // The namespace used for event handler binding on the dropZone and
 | ||||
|             // fileInput collections.
 | ||||
|             // If not set, the name of the widget ("fileupload") is used.
 | ||||
|             namespace: undefined, | ||||
|             // The drop target collection, by the default the complete document.
 | ||||
|             // Set to null or an empty collection to disable drag & drop support:
 | ||||
|             dropZone: $(document), | ||||
|             // The file input field collection, that is listened for change events.
 | ||||
|             // If undefined, it is set to the file input fields inside
 | ||||
|             // of the widget element on plugin initialization.
 | ||||
|             // Set to null or an empty collection to disable the change listener.
 | ||||
|             fileInput: undefined, | ||||
|             // By default, the file input field is replaced with a clone after
 | ||||
|             // each input field change event. This is required for iframe transport
 | ||||
|             // queues and allows change events to be fired for the same file
 | ||||
|             // selection, but can be disabled by setting the following option to false:
 | ||||
|             replaceFileInput: true, | ||||
|             // The parameter name for the file form data (the request argument name).
 | ||||
|             // If undefined or empty, the name property of the file input field is
 | ||||
|             // used, or "files[]" if the file input name property is also empty,
 | ||||
|             // can be a string or an array of strings:
 | ||||
|             paramName: undefined, | ||||
|             // By default, each file of a selection is uploaded using an individual
 | ||||
|             // request for XHR type uploads. Set to false to upload file
 | ||||
|             // selections in one request each:
 | ||||
|             singleFileUploads: true, | ||||
|             // To limit the number of files uploaded with one XHR request,
 | ||||
|             // set the following option to an integer greater than 0:
 | ||||
|             limitMultiFileUploads: undefined, | ||||
|             // Set the following option to true to issue all file upload requests
 | ||||
|             // in a sequential order:
 | ||||
|             sequentialUploads: false, | ||||
|             // To limit the number of concurrent uploads,
 | ||||
|             // set the following option to an integer greater than 0:
 | ||||
|             limitConcurrentUploads: undefined, | ||||
|             // Set the following option to true to force iframe transport uploads:
 | ||||
|             forceIframeTransport: false, | ||||
|             // Set the following option to the location of a redirect url on the
 | ||||
|             // origin server, for cross-domain iframe transport uploads:
 | ||||
|             redirect: undefined, | ||||
|             // The parameter name for the redirect url, sent as part of the form
 | ||||
|             // data and set to 'redirect' if this option is empty:
 | ||||
|             redirectParamName: undefined, | ||||
|             // Set the following option to the location of a postMessage window,
 | ||||
|             // to enable postMessage transport uploads:
 | ||||
|             postMessage: undefined, | ||||
|             // By default, XHR file uploads are sent as multipart/form-data.
 | ||||
|             // The iframe transport is always using multipart/form-data.
 | ||||
|             // Set to false to enable non-multipart XHR uploads:
 | ||||
|             multipart: true, | ||||
|             // To upload large files in smaller chunks, set the following option
 | ||||
|             // to a preferred maximum chunk size. If set to 0, null or undefined,
 | ||||
|             // or the browser does not support the required Blob API, files will
 | ||||
|             // be uploaded as a whole.
 | ||||
|             maxChunkSize: undefined, | ||||
|             // When a non-multipart upload or a chunked multipart upload has been
 | ||||
|             // aborted, this option can be used to resume the upload by setting
 | ||||
|             // it to the size of the already uploaded bytes. This option is most
 | ||||
|             // useful when modifying the options object inside of the "add" or
 | ||||
|             // "send" callbacks, as the options are cloned for each file upload.
 | ||||
|             uploadedBytes: undefined, | ||||
|             // By default, failed (abort or error) file uploads are removed from the
 | ||||
|             // global progress calculation. Set the following option to false to
 | ||||
|             // prevent recalculating the global progress data:
 | ||||
|             recalculateProgress: true, | ||||
|             // Interval in milliseconds to calculate and trigger progress events:
 | ||||
|             progressInterval: 100, | ||||
|             // Interval in milliseconds to calculate progress bitrate:
 | ||||
|             bitrateInterval: 500, | ||||
| 
 | ||||
|             // Additional form data to be sent along with the file uploads can be set
 | ||||
|             // using this option, which accepts an array of objects with name and
 | ||||
|             // value properties, a function returning such an array, a FormData
 | ||||
|             // object (for XHR file uploads), or a simple object.
 | ||||
|             // The form of the first fileInput is given as parameter to the function:
 | ||||
|             formData: function (form) { | ||||
|                 return form.serializeArray(); | ||||
|             }, | ||||
| 
 | ||||
|             // 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
 | ||||
|             // 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.
 | ||||
|             // 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) { | ||||
|                 data.submit(); | ||||
|             }, | ||||
| 
 | ||||
|             // Other callbacks:
 | ||||
|             // Callback for the submit event of each file upload:
 | ||||
|             // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
 | ||||
|             // Callback for the start of each file upload request:
 | ||||
|             // send: function (e, data) {}, // .bind('fileuploadsend', func);
 | ||||
|             // Callback for successful uploads:
 | ||||
|             // done: function (e, data) {}, // .bind('fileuploaddone', func);
 | ||||
|             // Callback for failed (abort or error) uploads:
 | ||||
|             // fail: function (e, data) {}, // .bind('fileuploadfail', func);
 | ||||
|             // Callback for completed (success, abort or error) requests:
 | ||||
|             // always: function (e, data) {}, // .bind('fileuploadalways', func);
 | ||||
|             // Callback for upload progress events:
 | ||||
|             // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
 | ||||
|             // Callback for global upload progress events:
 | ||||
|             // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
 | ||||
|             // Callback for uploads start, equivalent to the global ajaxStart event:
 | ||||
|             // start: function (e) {}, // .bind('fileuploadstart', func);
 | ||||
|             // Callback for uploads stop, equivalent to the global ajaxStop event:
 | ||||
|             // stop: function (e) {}, // .bind('fileuploadstop', func);
 | ||||
|             // Callback for change events of the fileInput collection:
 | ||||
|             // change: function (e, data) {}, // .bind('fileuploadchange', func);
 | ||||
|             // Callback for paste events to the dropZone collection:
 | ||||
|             // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
 | ||||
|             // Callback for drop events of the dropZone collection:
 | ||||
|             // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
 | ||||
|             // Callback for dragover events of the dropZone collection:
 | ||||
|             // dragover: function (e) {}, // .bind('fileuploaddragover', func);
 | ||||
| 
 | ||||
|             // The plugin options are used as settings object for the ajax calls.
 | ||||
|             // The following are jQuery ajax settings required for the file uploads:
 | ||||
|             processData: false, | ||||
|             contentType: false, | ||||
|             cache: false | ||||
|         }, | ||||
| 
 | ||||
|         // A list of options that require a refresh after assigning a new value:
 | ||||
|         _refreshOptionsList: [ | ||||
|             'namespace', | ||||
|             'dropZone', | ||||
|             'fileInput', | ||||
|             'multipart', | ||||
|             'forceIframeTransport' | ||||
|         ], | ||||
| 
 | ||||
|         _BitrateTimer: function () { | ||||
|             this.timestamp = +(new Date()); | ||||
|             this.loaded = 0; | ||||
|             this.bitrate = 0; | ||||
|             this.getBitrate = function (now, loaded, interval) { | ||||
|                 var timeDiff = now - this.timestamp; | ||||
|                 if (!this.bitrate || !interval || timeDiff > interval) { | ||||
|                     this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; | ||||
|                     this.loaded = loaded; | ||||
|                     this.timestamp = now; | ||||
|                 } | ||||
|                 return this.bitrate; | ||||
|             }; | ||||
|         }, | ||||
| 
 | ||||
|         _isXHRUpload: function (options) { | ||||
|             return !options.forceIframeTransport && | ||||
|                 ((!options.multipart && $.support.xhrFileUpload) || | ||||
|                 $.support.xhrFormDataFileUpload); | ||||
|         }, | ||||
| 
 | ||||
|         _getFormData: function (options) { | ||||
|             var formData; | ||||
|             if (typeof options.formData === 'function') { | ||||
|                 return options.formData(options.form); | ||||
|             } | ||||
| 			if ($.isArray(options.formData)) { | ||||
|                 return options.formData; | ||||
|             } | ||||
| 			if (options.formData) { | ||||
|                 formData = []; | ||||
|                 $.each(options.formData, function (name, value) { | ||||
|                     formData.push({name: name, value: value}); | ||||
|                 }); | ||||
|                 return formData; | ||||
|             } | ||||
|             return []; | ||||
|         }, | ||||
| 
 | ||||
|         _getTotal: function (files) { | ||||
|             var total = 0; | ||||
|             $.each(files, function (index, file) { | ||||
|                 total += file.size || 1; | ||||
|             }); | ||||
|             return total; | ||||
|         }, | ||||
| 
 | ||||
|         _onProgress: function (e, data) { | ||||
|             if (e.lengthComputable) { | ||||
|                 var now = +(new Date()), | ||||
|                     total, | ||||
|                     loaded; | ||||
|                 if (data._time && data.progressInterval && | ||||
|                         (now - data._time < data.progressInterval) && | ||||
|                         e.loaded !== e.total) { | ||||
|                     return; | ||||
|                 } | ||||
|                 data._time = now; | ||||
|                 total = data.total || this._getTotal(data.files); | ||||
|                 loaded = parseInt( | ||||
|                     e.loaded / e.total * (data.chunkSize || total), | ||||
|                     10 | ||||
|                 ) + (data.uploadedBytes || 0); | ||||
|                 this._loaded += loaded - (data.loaded || data.uploadedBytes || 0); | ||||
|                 data.lengthComputable = true; | ||||
|                 data.loaded = loaded; | ||||
|                 data.total = total; | ||||
|                 data.bitrate = data._bitrateTimer.getBitrate( | ||||
|                     now, | ||||
|                     loaded, | ||||
|                     data.bitrateInterval | ||||
|                 ); | ||||
|                 // 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); | ||||
|                 // Trigger a global progress event for all current file uploads,
 | ||||
|                 // including ajax calls queued for sequential file uploads:
 | ||||
|                 this._trigger('progressall', e, { | ||||
|                     lengthComputable: true, | ||||
|                     loaded: this._loaded, | ||||
|                     total: this._total, | ||||
|                     bitrate: this._bitrateTimer.getBitrate( | ||||
|                         now, | ||||
|                         this._loaded, | ||||
|                         data.bitrateInterval | ||||
|                     ) | ||||
|                 }); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _initProgressListener: function (options) { | ||||
|             var that = this, | ||||
|                 xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); | ||||
|             // Accesss to the native XHR object is required to add event listeners
 | ||||
|             // for the upload progress event:
 | ||||
|             if (xhr.upload) { | ||||
|                 $(xhr.upload).bind('progress', function (e) { | ||||
|                     var oe = e.originalEvent; | ||||
|                     // Make sure the progress event properties get copied over:
 | ||||
|                     e.lengthComputable = oe.lengthComputable; | ||||
|                     e.loaded = oe.loaded; | ||||
|                     e.total = oe.total; | ||||
|                     that._onProgress(e, options); | ||||
|                 }); | ||||
|                 options.xhr = function () { | ||||
|                     return xhr; | ||||
|                 }; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _initXHRData: function (options) { | ||||
|             var formData, | ||||
|                 file = options.files[0], | ||||
|                 // Ignore non-multipart setting if not supported:
 | ||||
|                 multipart = options.multipart || !$.support.xhrFileUpload, | ||||
|                 paramName = options.paramName[0]; | ||||
|             if (!multipart || options.blob) { | ||||
|                 // For non-multipart uploads and chunked uploads,
 | ||||
|                 // file meta data is not part of the request body,
 | ||||
|                 // so we transmit this data as part of the HTTP headers.
 | ||||
|                 // For cross domain requests, these headers must be allowed
 | ||||
|                 // via Access-Control-Allow-Headers or removed using
 | ||||
|                 // the beforeSend callback:
 | ||||
|                 options.headers = $.extend(options.headers, { | ||||
|                     'X-File-Name': file.name, | ||||
|                     'X-File-Type': file.type, | ||||
|                     'X-File-Size': file.size | ||||
|                 }); | ||||
|                 if (!options.blob) { | ||||
|                     // Non-chunked non-multipart upload:
 | ||||
|                     options.contentType = file.type; | ||||
|                     options.data = file; | ||||
|                 } else if (!multipart) { | ||||
|                     // Chunked non-multipart upload:
 | ||||
|                     options.contentType = 'application/octet-stream'; | ||||
|                     options.data = options.blob; | ||||
|                 } | ||||
|             } | ||||
|             if (multipart && $.support.xhrFormDataFileUpload) { | ||||
|                 if (options.postMessage) { | ||||
|                     // window.postMessage does not allow sending FormData
 | ||||
|                     // objects, so we just add the File/Blob objects to
 | ||||
|                     // the formData array and let the postMessage window
 | ||||
|                     // create the FormData object out of this array:
 | ||||
|                     formData = this._getFormData(options); | ||||
|                     if (options.blob) { | ||||
|                         formData.push({ | ||||
|                             name: paramName, | ||||
|                             value: options.blob | ||||
|                         }); | ||||
|                     } else { | ||||
|                         $.each(options.files, function (index, file) { | ||||
|                             formData.push({ | ||||
|                                 name: options.paramName[index] || paramName, | ||||
|                                 value: file | ||||
|                             }); | ||||
|                         }); | ||||
|                     } | ||||
|                 } else { | ||||
|                     if (options.formData instanceof FormData) { | ||||
|                         formData = options.formData; | ||||
|                     } else { | ||||
|                         formData = new FormData(); | ||||
|                         $.each(this._getFormData(options), function (index, field) { | ||||
|                             formData.append(field.name, field.value); | ||||
|                         }); | ||||
|                     } | ||||
|                     if (options.blob) { | ||||
|                         formData.append(paramName, options.blob, file.name); | ||||
|                     } else { | ||||
|                         $.each(options.files, function (index, file) { | ||||
|                             // File objects are also Blob instances.
 | ||||
|                             // This check allows the tests to run with
 | ||||
|                             // dummy objects:
 | ||||
|                             if (file instanceof Blob) { | ||||
|                                 formData.append( | ||||
|                                     options.paramName[index] || paramName, | ||||
|                                     file, | ||||
|                                     file.name | ||||
|                                 ); | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                 options.data = formData; | ||||
|             } | ||||
|             // Blob reference is not needed anymore, free memory:
 | ||||
|             options.blob = null; | ||||
|         }, | ||||
| 
 | ||||
|         _initIframeSettings: function (options) { | ||||
|             // 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 && $('<a></a>').prop('href', options.url) | ||||
|                     .prop('host') !== location.host) { | ||||
|                 options.formData.push({ | ||||
|                     name: options.redirectParamName || 'redirect', | ||||
|                     value: options.redirect | ||||
|                 }); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _initDataSettings: function (options) { | ||||
|             if (this._isXHRUpload(options)) { | ||||
|                 if (!this._chunkedUpload(options, true)) { | ||||
|                     if (!options.data) { | ||||
|                         this._initXHRData(options); | ||||
|                     } | ||||
|                     this._initProgressListener(options); | ||||
|                 } | ||||
|                 if (options.postMessage) { | ||||
|                     // Setting the dataType to postmessage enables the
 | ||||
|                     // postMessage transport:
 | ||||
|                     options.dataType = 'postmessage ' + (options.dataType || ''); | ||||
|                 } | ||||
|             } else { | ||||
|                 this._initIframeSettings(options, 'iframe'); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _getParamName: function (options) { | ||||
|             var fileInput = $(options.fileInput), | ||||
|                 paramName = options.paramName; | ||||
|             if (!paramName) { | ||||
|                 paramName = []; | ||||
|                 fileInput.each(function () { | ||||
|                     var input = $(this), | ||||
|                         name = input.prop('name') || 'files[]', | ||||
|                         i = (input.prop('files') || [1]).length; | ||||
|                     while (i) { | ||||
|                         paramName.push(name); | ||||
|                         i -= 1; | ||||
|                     } | ||||
|                 }); | ||||
|                 if (!paramName.length) { | ||||
|                     paramName = [fileInput.prop('name') || 'files[]']; | ||||
|                 } | ||||
|             } else if (!$.isArray(paramName)) { | ||||
|                 paramName = [paramName]; | ||||
|             } | ||||
|             return paramName; | ||||
|         }, | ||||
| 
 | ||||
|         _initFormSettings: function (options) { | ||||
|             // Retrieve missing options from the input field and the
 | ||||
|             // associated form, if available:
 | ||||
|             if (!options.form || !options.form.length) { | ||||
|                 options.form = $(options.fileInput.prop('form')); | ||||
|             } | ||||
|             options.paramName = this._getParamName(options); | ||||
|             if (!options.url) { | ||||
|                 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(); | ||||
|             if (options.type !== 'POST' && options.type !== 'PUT') { | ||||
|                 options.type = 'POST'; | ||||
|             } | ||||
|             if (!options.formAcceptCharset) { | ||||
|                 options.formAcceptCharset = options.form.attr('accept-charset'); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _getAJAXSettings: function (data) { | ||||
|             var options = $.extend({}, this.options, data); | ||||
|             this._initFormSettings(options); | ||||
|             this._initDataSettings(options); | ||||
|             return options; | ||||
|         }, | ||||
| 
 | ||||
|         // Maps jqXHR callbacks to the equivalent
 | ||||
|         // methods of the given Promise object:
 | ||||
|         _enhancePromise: function (promise) { | ||||
|             promise.success = promise.done; | ||||
|             promise.error = promise.fail; | ||||
|             promise.complete = promise.always; | ||||
|             return promise; | ||||
|         }, | ||||
| 
 | ||||
|         // Creates and returns a Promise object enhanced with
 | ||||
|         // the jqXHR methods abort, success, error and complete:
 | ||||
|         _getXHRPromise: function (resolveOrReject, context, args) { | ||||
|             var dfd = $.Deferred(), | ||||
|                 promise = dfd.promise(); | ||||
|             context = context || this.options.context || promise; | ||||
|             if (resolveOrReject === true) { | ||||
|                 dfd.resolveWith(context, args); | ||||
|             } else if (resolveOrReject === false) { | ||||
|                 dfd.rejectWith(context, args); | ||||
|             } | ||||
|             promise.abort = dfd.promise; | ||||
|             return this._enhancePromise(promise); | ||||
|         }, | ||||
| 
 | ||||
|         // Uploads a file in multiple, sequential requests
 | ||||
|         // by splitting the file up in multiple blob chunks.
 | ||||
|         // If the second parameter is true, only tests if the file
 | ||||
|         // should be uploaded in chunks, but does not invoke any
 | ||||
|         // upload requests:
 | ||||
|         _chunkedUpload: function (options, testOnly) { | ||||
|             var that = this, | ||||
|                 file = options.files[0], | ||||
|                 fs = file.size, | ||||
|                 ub = options.uploadedBytes = options.uploadedBytes || 0, | ||||
|                 mcs = options.maxChunkSize || fs, | ||||
|                 // Use the Blob methods with the slice implementation
 | ||||
|                 // according to the W3C Blob API specification:
 | ||||
|                 slice = file.webkitSlice || file.mozSlice || file.slice, | ||||
|                 upload, | ||||
|                 n, | ||||
|                 jqXHR, | ||||
|                 pipe; | ||||
|             if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || | ||||
|                     options.data) { | ||||
|                 return false; | ||||
|             } | ||||
|             if (testOnly) { | ||||
|                 return true; | ||||
|             } | ||||
|             if (ub >= fs) { | ||||
|                 file.error = 'uploadedBytes'; | ||||
|                 return this._getXHRPromise( | ||||
|                     false, | ||||
|                     options.context, | ||||
|                     [null, 'error', file.error] | ||||
|                 ); | ||||
|             } | ||||
|             // n is the number of blobs to upload,
 | ||||
|             // calculated via filesize, uploaded bytes and max chunk size:
 | ||||
|             n = Math.ceil((fs - ub) / mcs); | ||||
|             // The chunk upload method accepting the chunk number as parameter:
 | ||||
|             upload = function (i) { | ||||
|                 if (!i) { | ||||
|                     return that._getXHRPromise(true, options.context); | ||||
|                 } | ||||
|                 // Upload the blobs in sequential order:
 | ||||
|                 return upload(i -= 1).pipe(function () { | ||||
|                     // Clone the options object for each chunk upload:
 | ||||
|                     var o = $.extend({}, options); | ||||
|                     o.blob = slice.call( | ||||
|                         file, | ||||
|                         ub + i * mcs, | ||||
|                         ub + (i + 1) * mcs | ||||
|                     ); | ||||
|                     // Expose the chunk index:
 | ||||
|                     o.chunkIndex = i; | ||||
|                     // Expose the number of chunks:
 | ||||
|                     o.chunksNumber = n; | ||||
|                     // Store the current chunk size, as the blob itself
 | ||||
|                     // will be dereferenced after data processing:
 | ||||
|                     o.chunkSize = o.blob.size; | ||||
|                     // Process the upload data (the blob and potential form data):
 | ||||
|                     that._initXHRData(o); | ||||
|                     // Add progress listeners for this chunk upload:
 | ||||
|                     that._initProgressListener(o); | ||||
|                     jqXHR = ($.ajax(o) || that._getXHRPromise(false, o.context)) | ||||
|                         .done(function () { | ||||
|                             // Create a progress event if upload is done and
 | ||||
|                             // no progress event has been invoked for this chunk:
 | ||||
|                             if (!o.loaded) { | ||||
|                                 that._onProgress($.Event('progress', { | ||||
|                                     lengthComputable: true, | ||||
|                                     loaded: o.chunkSize, | ||||
|                                     total: o.chunkSize | ||||
|                                 }), o); | ||||
|                             } | ||||
|                             options.uploadedBytes = o.uploadedBytes += | ||||
|                                 o.chunkSize; | ||||
|                         }); | ||||
|                     return jqXHR; | ||||
|                 }); | ||||
|             }; | ||||
|             // Return the piped Promise object, enhanced with an abort method,
 | ||||
|             // which is delegated to the jqXHR object of the current upload,
 | ||||
|             // and jqXHR callbacks mapped to the equivalent Promise methods:
 | ||||
|             pipe = upload(n); | ||||
|             pipe.abort = function () { | ||||
|                 return jqXHR.abort(); | ||||
|             }; | ||||
|             return this._enhancePromise(pipe); | ||||
|         }, | ||||
| 
 | ||||
|         _beforeSend: function (e, data) { | ||||
|             if (this._active === 0) { | ||||
|                 // the start callback is triggered when an upload starts
 | ||||
|                 // and no other uploads are currently running,
 | ||||
|                 // equivalent to the global ajaxStart event:
 | ||||
|                 this._trigger('start'); | ||||
|                 // Set timer for global bitrate progress calculation:
 | ||||
|                 this._bitrateTimer = new this._BitrateTimer(); | ||||
|             } | ||||
|             this._active += 1; | ||||
|             // Initialize the global progress values:
 | ||||
|             this._loaded += data.uploadedBytes || 0; | ||||
|             this._total += this._getTotal(data.files); | ||||
|         }, | ||||
| 
 | ||||
|         _onDone: function (result, textStatus, jqXHR, options) { | ||||
|             if (!this._isXHRUpload(options)) { | ||||
|                 // Create a progress event for each iframe load:
 | ||||
|                 this._onProgress($.Event('progress', { | ||||
|                     lengthComputable: true, | ||||
|                     loaded: 1, | ||||
|                     total: 1 | ||||
|                 }), options); | ||||
|             } | ||||
|             options.result = result; | ||||
|             options.textStatus = textStatus; | ||||
|             options.jqXHR = jqXHR; | ||||
|             this._trigger('done', null, options); | ||||
|         }, | ||||
| 
 | ||||
|         _onFail: function (jqXHR, textStatus, errorThrown, options) { | ||||
|             options.jqXHR = jqXHR; | ||||
|             options.textStatus = textStatus; | ||||
|             options.errorThrown = errorThrown; | ||||
|             this._trigger('fail', null, options); | ||||
|             if (options.recalculateProgress) { | ||||
|                 // Remove the failed (error or abort) file upload from
 | ||||
|                 // the global progress calculation:
 | ||||
|                 this._loaded -= options.loaded || options.uploadedBytes || 0; | ||||
|                 this._total -= options.total || this._getTotal(options.files); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { | ||||
|             this._active -= 1; | ||||
|             options.textStatus = textStatus; | ||||
|             if (jqXHRorError && jqXHRorError.always) { | ||||
|                 options.jqXHR = jqXHRorError; | ||||
|                 options.result = jqXHRorResult; | ||||
|             } else { | ||||
|                 options.jqXHR = jqXHRorResult; | ||||
|                 options.errorThrown = jqXHRorError; | ||||
|             } | ||||
|             this._trigger('always', null, options); | ||||
|             if (this._active === 0) { | ||||
|                 // The stop callback is triggered when all uploads have
 | ||||
|                 // been completed, equivalent to the global ajaxStop event:
 | ||||
|                 this._trigger('stop'); | ||||
|                 // Reset the global progress values:
 | ||||
|                 this._loaded = this._total = 0; | ||||
|                 this._bitrateTimer = null; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _onSend: function (e, data) { | ||||
|             var that = this, | ||||
|                 jqXHR, | ||||
|                 slot, | ||||
|                 pipe, | ||||
|                 options = that._getAJAXSettings(data), | ||||
|                 send = function (resolve, args) { | ||||
|                     that._sending += 1; | ||||
|                     // Set timer for bitrate progress calculation:
 | ||||
|                     options._bitrateTimer = new that._BitrateTimer(); | ||||
|                     jqXHR = jqXHR || ( | ||||
|                         (resolve !== false && | ||||
|                         that._trigger('send', e, options) !== false && | ||||
|                         (that._chunkedUpload(options) || $.ajax(options))) || | ||||
|                         that._getXHRPromise(false, options.context, args) | ||||
|                     ).done(function (result, textStatus, jqXHR) { | ||||
|                         that._onDone(result, textStatus, jqXHR, options); | ||||
|                     }).fail(function (jqXHR, textStatus, errorThrown) { | ||||
|                         that._onFail(jqXHR, textStatus, errorThrown, options); | ||||
|                     }).always(function (jqXHRorResult, textStatus, jqXHRorError) { | ||||
|                         that._sending -= 1; | ||||
|                         that._onAlways( | ||||
|                             jqXHRorResult, | ||||
|                             textStatus, | ||||
|                             jqXHRorError, | ||||
|                             options | ||||
|                         ); | ||||
|                         if (options.limitConcurrentUploads && | ||||
|                                 options.limitConcurrentUploads > that._sending) { | ||||
|                             // Start the next queued upload,
 | ||||
|                             // that has not been aborted:
 | ||||
|                             var nextSlot = that._slots.shift(); | ||||
|                             while (nextSlot) { | ||||
|                                 if (!nextSlot.isRejected()) { | ||||
|                                     nextSlot.resolve(); | ||||
|                                     break; | ||||
|                                 } | ||||
|                                 nextSlot = that._slots.shift(); | ||||
|                             } | ||||
|                         } | ||||
|                     }); | ||||
|                     return jqXHR; | ||||
|                 }; | ||||
|             this._beforeSend(e, options); | ||||
|             if (this.options.sequentialUploads || | ||||
|                     (this.options.limitConcurrentUploads && | ||||
|                     this.options.limitConcurrentUploads <= this._sending)) { | ||||
|                 if (this.options.limitConcurrentUploads > 1) { | ||||
|                     slot = $.Deferred(); | ||||
|                     this._slots.push(slot); | ||||
|                     pipe = slot.pipe(send); | ||||
|                 } else { | ||||
|                     pipe = (this._sequence = this._sequence.pipe(send, send)); | ||||
|                 } | ||||
|                 // Return the piped Promise object, enhanced with an abort method,
 | ||||
|                 // which is delegated to the jqXHR object of the current upload,
 | ||||
|                 // and jqXHR callbacks mapped to the equivalent Promise methods:
 | ||||
|                 pipe.abort = function () { | ||||
|                     var args = [undefined, 'abort', 'abort']; | ||||
|                     if (!jqXHR) { | ||||
|                         if (slot) { | ||||
|                             slot.rejectWith(args); | ||||
|                         } | ||||
|                         return send(false, args); | ||||
|                     } | ||||
|                     return jqXHR.abort(); | ||||
|                 }; | ||||
|                 return this._enhancePromise(pipe); | ||||
|             } | ||||
|             return send(); | ||||
|         }, | ||||
| 
 | ||||
|         _onAdd: function (e, data) { | ||||
|             var that = this, | ||||
|                 result = true, | ||||
|                 options = $.extend({}, this.options, data), | ||||
|                 limit = options.limitMultiFileUploads, | ||||
|                 paramName = this._getParamName(options), | ||||
|                 paramNameSet, | ||||
|                 paramNameSlice, | ||||
|                 fileSet, | ||||
|                 i; | ||||
|             if (!(options.singleFileUploads || limit) || | ||||
|                     !this._isXHRUpload(options)) { | ||||
|                 fileSet = [data.files]; | ||||
|                 paramNameSet = [paramName]; | ||||
|             } else if (!options.singleFileUploads && limit) { | ||||
|                 fileSet = []; | ||||
|                 paramNameSet = []; | ||||
|                 for (i = 0; i < data.files.length; i += limit) { | ||||
|                     fileSet.push(data.files.slice(i, i + limit)); | ||||
|                     paramNameSlice = paramName.slice(i, i + limit); | ||||
|                     if (!paramNameSlice.length) { | ||||
|                         paramNameSlice = paramName; | ||||
|                     } | ||||
|                     paramNameSet.push(paramNameSlice); | ||||
|                 } | ||||
|             } else { | ||||
|                 paramNameSet = paramName; | ||||
|             } | ||||
|             data.originalFiles = data.files; | ||||
|             $.each(fileSet || data.files, function (index, element) { | ||||
|                 var newData = $.extend({}, data); | ||||
|                 newData.files = fileSet ? element : [element]; | ||||
|                 newData.paramName = paramNameSet[index]; | ||||
|                 newData.submit = function () { | ||||
|                     newData.jqXHR = this.jqXHR = | ||||
|                         (that._trigger('submit', e, this) !== false) && | ||||
|                         that._onSend(e, this); | ||||
|                     return this.jqXHR; | ||||
|                 }; | ||||
|                 return (result = that._trigger('add', e, newData)); | ||||
|             }); | ||||
|             return result; | ||||
|         }, | ||||
| 
 | ||||
|         // File Normalization for Gecko 1.9.1 (Firefox 3.5) support:
 | ||||
|         _normalizeFile: function (index, file) { | ||||
|             if (file.name === undefined && file.size === undefined) { | ||||
|                 file.name = file.fileName; | ||||
|                 file.size = file.fileSize; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _replaceFileInput: function (input) { | ||||
|             var inputClone = input.clone(true); | ||||
|             $('<form></form>').append(inputClone)[0].reset(); | ||||
|             // Detaching allows to insert the fileInput on another form
 | ||||
|             // without loosing the file input value:
 | ||||
|             input.after(inputClone).detach(); | ||||
|             // Avoid memory leaks with the detached file input:
 | ||||
|             $.cleanData(input.unbind('remove')); | ||||
|             // Replace the original file input element in the fileInput
 | ||||
|             // collection with the clone, which has been copied including
 | ||||
|             // event handlers:
 | ||||
|             this.options.fileInput = this.options.fileInput.map(function (i, el) { | ||||
|                 if (el === input[0]) { | ||||
|                     return inputClone[0]; | ||||
|                 } | ||||
|                 return el; | ||||
|             }); | ||||
|             // If the widget has been initialized on the file input itself,
 | ||||
|             // override this.element with the file input clone:
 | ||||
|             if (input[0] === this.element[0]) { | ||||
|                 this.element = inputClone; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _getFileInputFiles: function (fileInput) { | ||||
|             fileInput = $(fileInput); | ||||
|             var files = $.each($.makeArray(fileInput.prop('files')), this._normalizeFile), | ||||
|                 value; | ||||
|             if (!files.length) { | ||||
|                 value = fileInput.prop('value'); | ||||
|                 if (!value) { | ||||
|                     return []; | ||||
|                 } | ||||
|                 // If the files property is not available, the browser does not
 | ||||
|                 // support the File API and we add a pseudo File object with
 | ||||
|                 // the input value as name with path information removed:
 | ||||
|                 files = [{name: value.replace(/^.*\\/, '')}]; | ||||
|             } | ||||
|             return files; | ||||
|         }, | ||||
| 
 | ||||
|         _onChange: function (e) { | ||||
|             var that = e.data.fileupload, | ||||
|                 data = { | ||||
|                     fileInput: $(e.target), | ||||
|                     form: $(e.target.form) | ||||
|                 }; | ||||
|             data.files = that._getFileInputFiles(data.fileInput); | ||||
|             if (that.options.replaceFileInput) { | ||||
|                 that._replaceFileInput(data.fileInput); | ||||
|             } | ||||
|             if (that._trigger('change', e, data) === false || | ||||
|                     that._onAdd(e, data) === false) { | ||||
|                 return false; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _onPaste: function (e) { | ||||
|             var that = e.data.fileupload, | ||||
|                 cbd = e.originalEvent.clipboardData, | ||||
|                 items = (cbd && cbd.items) || [], | ||||
|                 data = {files: []}; | ||||
|             $.each(items, function (index, item) { | ||||
|                 var file = item.getAsFile && item.getAsFile(); | ||||
|                 if (file) { | ||||
|                     data.files.push(file); | ||||
|                 } | ||||
|             }); | ||||
|             if (that._trigger('paste', e, data) === false || | ||||
|                     that._onAdd(e, data) === false) { | ||||
|                 return false; | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _onDrop: function (e) { | ||||
|             var that = e.data.fileupload, | ||||
|                 dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer, | ||||
|                 data = { | ||||
|                     files: $.each( | ||||
|                         $.makeArray(dataTransfer && dataTransfer.files), | ||||
|                         that._normalizeFile | ||||
|                     ) | ||||
|                 }; | ||||
|             if (that._trigger('drop', e, data) === false || | ||||
|                     that._onAdd(e, data) === false) { | ||||
|                 return false; | ||||
|             } | ||||
|             e.preventDefault(); | ||||
|         }, | ||||
| 
 | ||||
|         _onDragOver: function (e) { | ||||
|             var that = e.data.fileupload, | ||||
|                 dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer; | ||||
|             if (that._trigger('dragover', e) === false) { | ||||
|                 return false; | ||||
|             } | ||||
|             if (dataTransfer) { | ||||
|                 dataTransfer.dropEffect = 'copy'; | ||||
|             } | ||||
|             e.preventDefault(); | ||||
|         }, | ||||
| 
 | ||||
|         _initEventHandlers: function () { | ||||
|             var ns = this.options.namespace; | ||||
|             if (this._isXHRUpload(this.options)) { | ||||
|                 this.options.dropZone | ||||
|                     .bind('dragover.' + ns, {fileupload: this}, this._onDragOver) | ||||
|                     .bind('drop.' + ns, {fileupload: this}, this._onDrop) | ||||
|                     .bind('paste.' + ns, {fileupload: this}, this._onPaste); | ||||
|             } | ||||
|             this.options.fileInput | ||||
|                 .bind('change.' + ns, {fileupload: this}, this._onChange); | ||||
|         }, | ||||
| 
 | ||||
|         _destroyEventHandlers: function () { | ||||
|             var ns = this.options.namespace; | ||||
|             this.options.dropZone | ||||
|                 .unbind('dragover.' + ns, this._onDragOver) | ||||
|                 .unbind('drop.' + ns, this._onDrop) | ||||
|                 .unbind('paste.' + ns, this._onPaste); | ||||
|             this.options.fileInput | ||||
|                 .unbind('change.' + ns, this._onChange); | ||||
|         }, | ||||
| 
 | ||||
|         _setOption: function (key, value) { | ||||
|             var refresh = $.inArray(key, this._refreshOptionsList) !== -1; | ||||
|             if (refresh) { | ||||
|                 this._destroyEventHandlers(); | ||||
|             } | ||||
|             $.Widget.prototype._setOption.call(this, key, value); | ||||
|             if (refresh) { | ||||
|                 this._initSpecialOptions(); | ||||
|                 this._initEventHandlers(); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _initSpecialOptions: function () { | ||||
|             var options = this.options; | ||||
|             if (options.fileInput === undefined) { | ||||
|                 options.fileInput = this.element.is('input:file') ? | ||||
|                         this.element : this.element.find('input:file'); | ||||
|             } else if (!(options.fileInput instanceof $)) { | ||||
|                 options.fileInput = $(options.fileInput); | ||||
|             } | ||||
|             if (!(options.dropZone instanceof $)) { | ||||
|                 options.dropZone = $(options.dropZone); | ||||
|             } | ||||
|         }, | ||||
| 
 | ||||
|         _create: function () { | ||||
|             var options = this.options; | ||||
|             // Initialize options set via HTML5 data-attributes:
 | ||||
|             $.extend(options, $(this.element[0].cloneNode(false)).data()); | ||||
|             options.namespace = options.namespace || this.widgetName; | ||||
|             this._initSpecialOptions(); | ||||
|             this._slots = []; | ||||
|             this._sequence = this._getXHRPromise(true); | ||||
|             this._sending = this._active = this._loaded = this._total = 0; | ||||
|             this._initEventHandlers(); | ||||
|         }, | ||||
| 
 | ||||
|         destroy: function () { | ||||
|             this._destroyEventHandlers(); | ||||
|             $.Widget.prototype.destroy.call(this); | ||||
|         }, | ||||
| 
 | ||||
|         enable: function () { | ||||
|             $.Widget.prototype.enable.call(this); | ||||
|             this._initEventHandlers(); | ||||
|         }, | ||||
| 
 | ||||
|         disable: function () { | ||||
|             this._destroyEventHandlers(); | ||||
|             $.Widget.prototype.disable.call(this); | ||||
|         }, | ||||
| 
 | ||||
|         // This method is exposed to the widget API and allows adding files
 | ||||
|         // using the fileupload API. The data parameter accepts an object which
 | ||||
|         // must have a files property and can contain additional options:
 | ||||
|         // .fileupload('add', {files: filesList});
 | ||||
|         add: function (data) { | ||||
|             if (!data || this.options.disabled) { | ||||
|                 return; | ||||
|             } | ||||
|             if (data.fileInput && !data.files) { | ||||
|                 data.files = this._getFileInputFiles(data.fileInput); | ||||
|             } else { | ||||
|                 data.files = $.each($.makeArray(data.files), this._normalizeFile); | ||||
|             } | ||||
|             this._onAdd(null, data); | ||||
|         }, | ||||
| 
 | ||||
|         // This method is exposed to the widget API and allows sending files
 | ||||
|         // using the fileupload API. The data parameter accepts an object which
 | ||||
|         // must have a files property and can contain additional options:
 | ||||
|         // .fileupload('send', {files: filesList});
 | ||||
|         // The method returns a Promise object for the file upload call.
 | ||||
|         send: function (data) { | ||||
|             if (data && !this.options.disabled) { | ||||
|                 if (data.fileInput && !data.files) { | ||||
|                     data.files = this._getFileInputFiles(data.fileInput); | ||||
|                 } else { | ||||
|                     data.files = $.each($.makeArray(data.files), this._normalizeFile); | ||||
|                 } | ||||
|                 if (data.files.length) { | ||||
|                     return this._onSend(null, data); | ||||
|                 } | ||||
|             } | ||||
|             return this._getXHRPromise(false, data && data.context); | ||||
|         } | ||||
| 
 | ||||
|     }); | ||||
| 
 | ||||
| })); | ||||
|  | @ -1,172 +0,0 @@ | |||
| /* | ||||
|  * jQuery Iframe Transport Plugin 1.5 | ||||
|  * https://github.com/blueimp/jQuery-File-Upload
 | ||||
|  * | ||||
|  * Copyright 2011, Sebastian Tschan | ||||
|  * https://blueimp.net
 | ||||
|  * | ||||
|  * Licensed under the MIT license: | ||||
|  * http://www.opensource.org/licenses/MIT
 | ||||
|  */ | ||||
| 
 | ||||
| /*jslint unparam: true, nomen: true */ | ||||
| /*global define, window, document */ | ||||
| 
 | ||||
| (function (factory) { | ||||
|     'use strict'; | ||||
|     if (typeof define === 'function' && define.amd) { | ||||
|         // Register as an anonymous AMD module:
 | ||||
|         define(['jquery'], factory); | ||||
|     } else { | ||||
|         // Browser globals:
 | ||||
|         factory(window.jQuery); | ||||
|     } | ||||
| }(function ($) { | ||||
|     'use strict'; | ||||
| 
 | ||||
|     // Helper variable to create unique names for the transport iframes:
 | ||||
|     var counter = 0; | ||||
| 
 | ||||
|     // The iframe transport accepts three 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),
 | ||||
|     //  can be a string or an array of strings.
 | ||||
|     // 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}]
 | ||||
|     $.ajaxTransport('iframe', function (options) { | ||||
|         if (options.async && (options.type === 'POST' || options.type === 'GET')) { | ||||
|             var form, | ||||
|                 iframe; | ||||
|             return { | ||||
|                 send: function (_, completeCallback) { | ||||
|                     form = $('<form style="display:none;"></form>'); | ||||
|                     form.attr('accept-charset', options.formAcceptCharset); | ||||
|                     // 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:
 | ||||
|                     iframe = $( | ||||
|                         '<iframe src="javascript:false;" name="iframe-transport-' + | ||||
|                             (counter += 1) + '"></iframe>' | ||||
|                     ).bind('load', function () { | ||||
|                         var fileInputClones, | ||||
|                             paramNames = $.isArray(options.paramName) ? | ||||
|                                     options.paramName : [options.paramName]; | ||||
|                         iframe | ||||
|                             .unbind('load') | ||||
|                             .bind('load', function () { | ||||
|                                 var response; | ||||
|                                 // Wrap in a try/catch block to catch exceptions thrown
 | ||||
|                                 // when trying to access cross-domain iframe contents:
 | ||||
|                                 try { | ||||
|                                     response = iframe.contents(); | ||||
|                                     // Google Chrome and Firefox do not throw an
 | ||||
|                                     // exception when calling iframe.contents() on
 | ||||
|                                     // cross-domain requests, so we unify the response:
 | ||||
|                                     if (!response.length || !response[0].firstChild) { | ||||
|                                         throw new Error(); | ||||
|                                     } | ||||
|                                 } catch (e) { | ||||
|                                     response = undefined; | ||||
|                                 } | ||||
|                                 // The complete callback returns the
 | ||||
|                                 // iframe content document as response object:
 | ||||
|                                 completeCallback( | ||||
|                                     200, | ||||
|                                     'success', | ||||
|                                     {'iframe': response} | ||||
|                                 ); | ||||
|                                 // Fix for IE endless progress bar activity bug
 | ||||
|                                 // (happens on form submits to iframe targets):
 | ||||
|                                 $('<iframe src="javascript:false;"></iframe>') | ||||
|                                     .appendTo(form); | ||||
|                                 form.remove(); | ||||
|                             }); | ||||
|                         form | ||||
|                             .prop('target', iframe.prop('name')) | ||||
|                             .prop('action', options.url) | ||||
|                             .prop('method', options.type); | ||||
|                         if (options.formData) { | ||||
|                             $.each(options.formData, function (index, field) { | ||||
|                                 $('<input type="hidden"/>') | ||||
|                                     .prop('name', field.name) | ||||
|                                     .val(field.value) | ||||
|                                     .appendTo(form); | ||||
|                             }); | ||||
|                         } | ||||
|                         if (options.fileInput && options.fileInput.length && | ||||
|                                 options.type === 'POST') { | ||||
|                             fileInputClones = options.fileInput.clone(); | ||||
|                             // Insert a clone for each file input field:
 | ||||
|                             options.fileInput.after(function (index) { | ||||
|                                 return fileInputClones[index]; | ||||
|                             }); | ||||
|                             if (options.paramName) { | ||||
|                                 options.fileInput.each(function (index) { | ||||
|                                     $(this).prop( | ||||
|                                         'name', | ||||
|                                         paramNames[index] || options.paramName | ||||
|                                     ); | ||||
|                                 }); | ||||
|                             } | ||||
|                             // Appending the file input fields to the hidden form
 | ||||
|                             // removes them from their original location:
 | ||||
|                             form | ||||
|                                 .append(options.fileInput) | ||||
|                                 .prop('enctype', 'multipart/form-data') | ||||
|                                 // enctype must be set as encoding for IE:
 | ||||
|                                 .prop('encoding', 'multipart/form-data'); | ||||
|                         } | ||||
|                         form.submit(); | ||||
|                         // Insert the file input fields at their original location
 | ||||
|                         // by replacing the clones with the originals:
 | ||||
|                         if (fileInputClones && fileInputClones.length) { | ||||
|                             options.fileInput.each(function (index, input) { | ||||
|                                 var clone = $(fileInputClones[index]); | ||||
|                                 $(input).prop('name', clone.prop('name')); | ||||
|                                 clone.replaceWith(input); | ||||
|                             }); | ||||
|                         } | ||||
|                     }); | ||||
|                     form.append(iframe).appendTo(document.body); | ||||
|                 }, | ||||
|                 abort: function () { | ||||
|                     if (iframe) { | ||||
|                         // javascript:false as iframe src aborts the request
 | ||||
|                         // and prevents warning popups on HTTPS in IE6.
 | ||||
|                         // concat is used to avoid the "Script URL" JSLint error:
 | ||||
|                         iframe | ||||
|                             .unbind('load') | ||||
|                             .prop('src', 'javascript'.concat(':false;')); | ||||
|                     } | ||||
|                     if (form) { | ||||
|                         form.remove(); | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     // The iframe transport returns the iframe content document as response.
 | ||||
|     // The following adds converters from iframe to text, json, html, and script:
 | ||||
|     $.ajaxSetup({ | ||||
|         converters: { | ||||
|             'iframe text': function (iframe) { | ||||
|                 return $(iframe[0].body).text(); | ||||
|             }, | ||||
|             'iframe json': function (iframe) { | ||||
|                 return $.parseJSON($(iframe[0].body).text()); | ||||
|             }, | ||||
|             'iframe html': function (iframe) { | ||||
|                 return $(iframe[0].body).html(); | ||||
|             }, | ||||
|             'iframe script': function (iframe) { | ||||
|                 return $.globalEval($(iframe[0].body).text()); | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
| })); | ||||
|  | @ -1,29 +0,0 @@ | |||
| /* | ||||
|  * jQuery File Upload Plugin Localization Example 6.5.1 | ||||
|  * 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
 | ||||
|  */ | ||||
| 
 | ||||
| /*global window */ | ||||
| 
 | ||||
| window.locale = { | ||||
|     "fileupload": { | ||||
|         "errors": { | ||||
|             "maxFileSize": "File is too big", | ||||
|             "minFileSize": "File is too small", | ||||
|             "acceptFileTypes": "Filetype not allowed", | ||||
|             "maxNumberOfFiles": "Max number of files exceeded", | ||||
|             "uploadedBytes": "Uploaded bytes exceed file size", | ||||
|             "emptyResult": "Empty file upload result" | ||||
|         }, | ||||
|         "error": "Error", | ||||
|         "start": "Start", | ||||
|         "cancel": "Cancel", | ||||
|         "destroy": "Delete" | ||||
|     } | ||||
| }; | ||||
|  | @ -1,78 +0,0 @@ | |||
| /* | ||||
|  * jQuery File Upload Plugin JS Example 6.7 | ||||
|  * https://github.com/blueimp/jQuery-File-Upload
 | ||||
|  * | ||||
|  * Copyright 2010, Sebastian Tschan | ||||
|  * https://blueimp.net
 | ||||
|  * | ||||
|  * Licensed under the MIT license: | ||||
|  * http://www.opensource.org/licenses/MIT
 | ||||
|  */ | ||||
| 
 | ||||
| /*jslint nomen: true, unparam: true, regexp: true */ | ||||
| /*global $, window, document */ | ||||
| 
 | ||||
| $(function () { | ||||
|     'use strict'; | ||||
| 
 | ||||
|     // Initialize the jQuery File Upload widget:
 | ||||
|     $('#fileupload').fileupload(); | ||||
| 
 | ||||
|     // Enable iframe cross-domain access via redirect option:
 | ||||
|     $('#fileupload').fileupload( | ||||
|         'option', | ||||
|         'redirect', | ||||
|         window.location.href.replace( | ||||
|             /\/[^\/]*$/, | ||||
|             '/cors/result.html?%s' | ||||
|         ) | ||||
|     ); | ||||
| 
 | ||||
|     if (window.location.hostname === 'blueimp.github.com') { | ||||
|         // Demo settings:
 | ||||
|         $('#fileupload').fileupload('option', { | ||||
|             url: '//jquery-file-upload.appspot.com/', | ||||
|             maxFileSize: 5000000, | ||||
|             acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, | ||||
|             process: [ | ||||
|                 { | ||||
|                     action: 'load', | ||||
|                     fileTypes: /^image\/(gif|jpeg|png)$/, | ||||
|                     maxFileSize: 20000000 // 20MB
 | ||||
|                 }, | ||||
|                 { | ||||
|                     action: 'resize', | ||||
|                     maxWidth: 1440, | ||||
|                     maxHeight: 900 | ||||
|                 }, | ||||
|                 { | ||||
|                     action: 'save' | ||||
|                 } | ||||
|             ] | ||||
|         }); | ||||
|         // Upload server status check for browsers with CORS support:
 | ||||
|         if ($.support.cors) { | ||||
|             $.ajax({ | ||||
|                 url: '//jquery-file-upload.appspot.com/', | ||||
|                 type: 'HEAD' | ||||
|             }).fail(function () { | ||||
|                 $('<span class="alert alert-error"/>') | ||||
|                     .text('Upload server currently unavailable - ' + | ||||
|                             new Date()) | ||||
|                     .appendTo('#fileupload'); | ||||
|             }); | ||||
|         } | ||||
|     } else { | ||||
|         // Load existing files:
 | ||||
|         $('#fileupload').each(function () { | ||||
|             var that = this; | ||||
|             $.getJSON(this.action, function (result) { | ||||
|                 if (result && result.length) { | ||||
|                     $(that).fileupload('option', 'done') | ||||
|                         .call(that, null, {result: result}); | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
| }); | ||||
|  | @ -9,7 +9,7 @@ | |||
| <ul> | ||||
| 	<li> | ||||
|   <b><%= t('announcement.category') %></b> | ||||
|   <%= @bulletin.bulletin_category.i18n_variable[I18n.locale] %> | ||||
|   <%= @bulletin.bulletin_category.title %> | ||||
| 	</li> | ||||
| 	<li> | ||||
|   <b><%= t('announcement.postdate') %></b> | ||||
|  |  | |||
|  | @ -10,11 +10,11 @@ | |||
| 	 | ||||
| 	<ul class="subm"> | ||||
| 	<% @archive_file_categorys.each do |afcpost| %> | ||||
| 		<li><%= link_to afcpost.i18n_variable[I18n.locale], panel_archive_front_end_archive_files_path(:category_id => afcpost.id) %></li> | ||||
| 		<li><%= link_to afcpost.title, panel_archive_front_end_archive_files_path(:category_id => afcpost.id) %></li> | ||||
| 	<% end %> | ||||
| 	</ul> | ||||
| 	 | ||||
| 	<h3><%= @archive_files.first.archive_file_category.i18n_variable[I18n.locale] rescue nil %></h3> | ||||
| 	<h3><%= @archive_files.first.archive_file_category.title rescue nil %></h3> | ||||
| 	 | ||||
| 	<% @archive_files.each do |post| %> | ||||
| 	 | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 	<h1 class="h1"><%= @title %></h1> | ||||
| <% end %> | ||||
| 
 | ||||
| <h3><%= @archive_file.archive_file_category.i18n_variable[I18n.locale] rescue nil %></h3> | ||||
| <h3><%= @archive_file.archive_file_category.title rescue nil %></h3> | ||||
| 
 | ||||
| <%= @archive_file.title %> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue