/** Ace file input element. Custom, simple file input element to style browser's default file input. */ (function($ , undefined) { var multiplible = 'multiple' in document.createElement('INPUT'); var hasFileList = 'FileList' in window;//file list enabled in modern browsers var hasFileReader = 'FileReader' in window; var hasFile = 'File' in window; var Ace_File_Input = function(element , settings) { var self = this; this.settings = $.extend({}, $.fn.ace_file_input.defaults, settings); this.$element = $(element); this.element = element; this.disabled = false; this.can_reset = true; this.$element .off('change.ace_inner_call') .on('change.ace_inner_call', function(e , ace_inner_call){ if(ace_inner_call === true) return;//this change event is called from above drop event and extra checkings are taken care of there return handle_on_change.call(self); //if(ret === false) e.preventDefault(); }); var parent_label = this.$element.closest('label').css({'display':'block'}) var tagName = parent_label.length == 0 ? 'label' : 'span';//if not inside a "LABEL" tag, use "LABEL" tag, otherwise use "SPAN" this.$element.wrap('<'+tagName+' class="ace-file-input" />'); this.apply_settings(); this.reset_input_field();//for firefox as it keeps selected file after refresh } Ace_File_Input.error = { 'FILE_LOAD_FAILED' : 1, 'IMAGE_LOAD_FAILED' : 2, 'THUMBNAIL_FAILED' : 3 }; Ace_File_Input.prototype.apply_settings = function() { var self = this; this.multi = this.$element.attr('multiple') && multiplible; this.well_style = this.settings.style == 'well'; if(this.well_style) this.$element.parent().addClass('ace-file-multiple'); else this.$element.parent().removeClass('ace-file-multiple'); this.$element.parent().find(':not(input[type=file])').remove();//remove all except our input, good for when changing settings this.$element.after(''+(this.settings.no_icon ? '' : '')+''); this.$label = this.$element.next(); this.$container = this.$element.closest('.ace-file-input'); var remove_btn = !!this.settings.icon_remove; if(remove_btn) { var btn = $('') .appendTo(this.$element.parent()); btn.on(ace.click_event, function(e){ e.preventDefault(); if( !self.can_reset ) return false; var ret = true; if(self.settings.before_remove) ret = self.settings.before_remove.call(self.element); if(!ret) return false; var r = self.reset_input(); return false; }); } if(this.settings.droppable && hasFileList) { enable_drop_functionality.call(this); } } Ace_File_Input.prototype.show_file_list = function($files) { var files = typeof $files === "undefined" ? this.$element.data('ace_input_files') : $files; if(!files || files.length == 0) return; ////////////////////////////////////////////////////////////////// if(this.well_style) { this.$label.find('.ace-file-name').remove(); if(!this.settings.btn_change) this.$label.addClass('hide-placeholder'); } this.$label.attr('data-title', this.settings.btn_change).addClass('selected'); for (var i = 0; i < files.length; i++) { var filename = typeof files[i] === "string" ? files[i] : $.trim( files[i].name ); var index = filename.lastIndexOf("\\") + 1; if(index == 0)index = filename.lastIndexOf("/") + 1; filename = filename.substr(index); var fileIcon = 'fa fa-file'; var format = 'file'; if((/\.(jpe?g|png|gif|svg|bmp|tiff?)$/i).test(filename)) { fileIcon = 'fa fa-picture-o file-image'; format = 'image'; } else if((/\.(mpe?g|flv|mov|avi|swf|mp4|mkv|webm|wmv|3gp)$/i).test(filename)) { fileIcon = 'fa fa-film file-video'; format = 'video'; } else if((/\.(mp3|ogg|wav|wma|amr|aac)$/i).test(filename)) { fileIcon = 'fa fa-music file-audio'; format = 'audio'; } if(!this.well_style) this.$label.find('.ace-file-name').attr({'data-title':filename}).find(ace.vars['.icon']).attr('class', ace.vars['icon'] + fileIcon); else { this.$label.append(''); var type = $.trim(files[i].type); var can_preview = hasFileReader && this.settings.thumbnail && ( (type.length > 0 && type.match('image')) || (type.length == 0 && format == 'image') )//the second one is for Android's default browser which gives an empty text for file.type if(can_preview) { var self = this; $.when(preview_image.call(this, files[i])).fail(function(result){ //called on failure to load preview if(self.settings.preview_error) self.settings.preview_error.call(self, filename, result.code); }); } } } return true; } Ace_File_Input.prototype.reset_input = function() { this.reset_input_ui(); this.reset_input_field(); } Ace_File_Input.prototype.reset_input_ui = function() { this.$label.attr({'data-title':this.settings.btn_choose, 'class':'ace-file-container'}) .find('.ace-file-name:first').attr({'data-title':this.settings.no_file , 'class':'ace-file-name'}) .find(ace.vars['.icon']).attr('class', ace.vars['icon'] + this.settings.no_icon) .prev('img').remove(); if(!this.settings.no_icon) this.$label.find(ace.vars['.icon']).remove(); this.$label.find('.ace-file-name').not(':first').remove(); this.reset_input_data(); } Ace_File_Input.prototype.reset_input_field = function() { //http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery/13351234#13351234 this.$element.wrap('