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 |   # GET /archive_files/1/edit | ||||||
|   def edit |   def edit | ||||||
|     @archive_file_category = ArchiveFileCategory.find(params[:id]) |     @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) | 	@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 |   # POST /archive_files.xml | ||||||
|   def create |   def create | ||||||
|     @archive_file = ArchiveFile.new(params[:archive_file]) |     @archive_file = ArchiveFile.new(params[:archive_file]) | ||||||
| 	 |  | ||||||
|     @archive_file.create_user_id = current_user.id |     @archive_file.create_user_id = current_user.id | ||||||
|     @archive_file.update_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.html { redirect_to(panel_archive_back_end_archive_files_url) } | ||||||
|         format.xml  { render :xml => @archive_file, :status => :created, :location => @archive_file } |         format.xml  { render :xml => @archive_file, :status => :created, :location => @archive_file } | ||||||
|       else |       else | ||||||
|  |         get_categorys | ||||||
|  |         get_tags | ||||||
|         format.html { render :action => "new" } |         format.html { render :action => "new" } | ||||||
|         format.xml  { render :xml => @archive_file.errors, :status => :unprocessable_entity } |         format.xml  { render :xml => @archive_file.errors, :status => :unprocessable_entity } | ||||||
|       end |       end | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ class Panel::Archive::FrontEnd::ArchiveFilesController < OrbitWidgetController | ||||||
|      |      | ||||||
| 	@item = Page.find(params[:page_id]) | 	@item = Page.find(params[:page_id]) | ||||||
| 	 | 	 | ||||||
| 	@title = @item.i18n_variable[I18n.locale] | 	@title = @item.title | ||||||
|    |    | ||||||
|   	if @item.frontend_data_count |   	if @item.frontend_data_count | ||||||
| 		@page_num = @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]) | 	@item = Page.find(params[:page_id]) | ||||||
| 	 | 	 | ||||||
| 	@title = @item.i18n_variable[I18n.locale] | 	@title = @item.title | ||||||
| 	 | 	 | ||||||
|     @archive_file = ArchiveFile.find(params[:id]) |     @archive_file = ArchiveFile.find(params[:id]) | ||||||
| 	 | 	 | ||||||
|  | @ -55,7 +55,7 @@ class Panel::Archive::FrontEnd::ArchiveFilesController < OrbitWidgetController | ||||||
|      |      | ||||||
| 	@item = Page.find(params[:page_id]) | 	@item = Page.find(params[:page_id]) | ||||||
| 	 | 	 | ||||||
| 	@title = @item.i18n_variable[I18n.locale] | 	@title = @item.title | ||||||
|    |    | ||||||
|   	if @item.frontend_data_count |   	if @item.frontend_data_count | ||||||
| 		@page_num = @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 |   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 |   after_save :save_archive_file_multiples | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,8 +7,10 @@ class ArchiveFileCategory | ||||||
|    |    | ||||||
|   field :key |   field :key | ||||||
|    |    | ||||||
|   has_one :i18n_variable, :as => :language_value, :autosave => true, :dependent => :destroy |   field :title, localize: true | ||||||
|    |    | ||||||
|   has_many :archive_files |   has_many :archive_files | ||||||
|  | 
 | ||||||
|  |   validates :title, :at_least_one => true | ||||||
|    |    | ||||||
| end | end | ||||||
|  | @ -9,8 +9,6 @@ class ArchiveFileMultiple | ||||||
|   # field :description |   # field :description | ||||||
|   field :choose_lang, :type => Array, :default => nil |   field :choose_lang, :type => Array, :default => nil | ||||||
|    |    | ||||||
|   # has_one :i18n_variable, :as => :language_value, :autosave => true, :dependent => :destroy |  | ||||||
|    |  | ||||||
|   field :should_destroy, :type => Boolean |   field :should_destroy, :type => Boolean | ||||||
| 
 | 
 | ||||||
|   def choose_lang_display(lang) |   def choose_lang_display(lang) | ||||||
|  |  | ||||||
|  | @ -11,6 +11,6 @@ | ||||||
| 			</div> | 			</div> | ||||||
| 		</td> | 		</td> | ||||||
| 		<% @site_valid_locales.each do |locale| %> | 		<% @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 %> | 		<% end %> | ||||||
| 	</tr> | 	</tr> | ||||||
|  | @ -10,12 +10,12 @@ | ||||||
| 	</div> | 	</div> | ||||||
| 	 | 	 | ||||||
| 	<div id="widget-title"> | 	<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| %> | 		  <% @site_valid_locales.each do |locale| %> | ||||||
| 				<div class="control-group"> | 				<div class="control-group"> | ||||||
| 					<%= label_tag "name-#{locale}", "Name-#{I18nVariable.from_locale(locale)}", :class => 'control-label' %> | 					<%= label_tag "name-#{locale}", "Name-#{I18nVariable.from_locale(locale)}", :class => 'control-label' %> | ||||||
| 					<div class="controls"> | 					<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> | ||||||
| 				</div> | 				</div> | ||||||
| 		  <% end %> | 		  <% end %> | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ | ||||||
| 			</ul> | 			</ul> | ||||||
| 		</div> | 		</div> | ||||||
| 	</td> | 	</td> | ||||||
| 	<td><%= post.archive_file_category.i18n_variable[I18n.locale] %></td> | 	<td><%= post.archive_file_category.title %></td> | ||||||
| 	<td> | 	<td> | ||||||
| 	<%= link_to post.title, panel_archive_front_end_archive_file_path(post) %> | 	<%= link_to post.title, panel_archive_front_end_archive_file_path(post) %> | ||||||
| 	</td> | 	</td> | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ | ||||||
| 		<div id="post-body-content" class="clear"> | 		<div id="post-body-content" class="clear"> | ||||||
| 		 | 		 | ||||||
| 			<%= f.label :category %> | 			<%= 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"> | 			<ul class="nav nav-tabs"> | ||||||
| 				<% @site_valid_locales.each_with_index do |locale, i| %> | 				<% @site_valid_locales.each_with_index do |locale, i| %> | ||||||
|  | @ -74,7 +74,7 @@ | ||||||
| 			 | 			 | ||||||
| 			<div> | 			<div> | ||||||
| 						 | 						 | ||||||
| 				<div id='archive_file_multiples' class="archive_file_multiples_block"> | 				<div class="archive_file_multiples_block"> | ||||||
| 					 | 					 | ||||||
| 				<table class="table table-condensed"> | 				<table class="table table-condensed"> | ||||||
| 					<thead> | 					<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> | <ul> | ||||||
| 	<li> | 	<li> | ||||||
|   <b><%= t('announcement.category') %></b> |   <b><%= t('announcement.category') %></b> | ||||||
|   <%= @bulletin.bulletin_category.i18n_variable[I18n.locale] %> |   <%= @bulletin.bulletin_category.title %> | ||||||
| 	</li> | 	</li> | ||||||
| 	<li> | 	<li> | ||||||
|   <b><%= t('announcement.postdate') %></b> |   <b><%= t('announcement.postdate') %></b> | ||||||
|  |  | ||||||
|  | @ -10,11 +10,11 @@ | ||||||
| 	 | 	 | ||||||
| 	<ul class="subm"> | 	<ul class="subm"> | ||||||
| 	<% @archive_file_categorys.each do |afcpost| %> | 	<% @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 %> | 	<% end %> | ||||||
| 	</ul> | 	</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| %> | 	<% @archive_files.each do |post| %> | ||||||
| 	 | 	 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| 	<h1 class="h1"><%= @title %></h1> | 	<h1 class="h1"><%= @title %></h1> | ||||||
| <% end %> | <% 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 %> | <%= @archive_file.title %> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue