diff --git a/LICENSE b/LICENSE index 2c1a276..1365220 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Jordan Kasper +Copyright (c) 2012-2015 Jordan Kasper, 2015 eusonlito, 2015 Alexei Ivashkevich Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4bc1ea9..ffe93ff 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ SimpleFilePreview is a jQuery plug-in that allows for pre-form submission file previews on images and icon previews for non-images. The syntax is extremely simple and the UI allows for easy CSS styling. -**Requires jQuery 1.7+** +**Requires: jQuery 1.9.1+, Bootstrap 3.3.4+ (for progressbar only), jQuery UI 1.11.4+ (for dialog only), context.js 1.0.1+ (for link open only)** ### Main Features @@ -47,6 +47,71 @@ simple and the UI allows for easy CSS styling. (default value includes most common file types in this format: {'png': 'preview_png.png', ...} 'limit': INTEGER On multiple files, set a limit +'removeMessage': { + 'prefix': STRING Prefix for remove message + (defaults to "Remove") + 'stub': STRING Stub instead of the file name for remove message +} (defaults to "this file") +'radio': { Display the radio buttons (if necessary) to mark one of the files (only multiple mode) + (defaults to null (no display the radio buttons)) + 'name': STRING Name of input element + (defaults to null) + 'checkedItem': STRING Preselect radio button +} (defaults to null) +'readOnly': BOOLEAN Display with no possibility of modification + (defaults to false) +'ajaxUpload': { Upload file via AJAX + (defaults to null) + 'url': STRING URL for upload file + (defaults to null) + 'progressbar': BOOLEAN Progressbar for upload file (required Bootstrap) + (defaults to false) + 'success': FUNCTION Callback for ajax success function + (defaults to null) + 'error': FUNCTION Callback for ajax error function + (defaults to null) + 'compose': FUNCTION Callback for before send FormData customization +} (defaults to null) +'beforeRemove' Callback for before remove element + (defaults to null) +'removeDialog': { Dialog for remove file (required jQuery UI) + (defaults to null) + 'id': STRING Dialog Id + (defaults to "***_remove_dialog") + 'title': STRING Title dialog + (defaults to "Remove") + 'text': STRING Body text + (defaults to "Are you sure?") + 'ok': STRING Text for OK button + (defaults to "Ok") + 'cancel': STRING Text for Cancel button + (defaults to "Cancel") +} +'contextMenu': { Context menu for select file source + (defaults to null) + 'fileText': STRING Text for file option + (defaults to "Open file") + 'linkText': STRING Text for link option + (defaults to "Open link") + 'id': STRING Dialog Id + (defaults to "***_openlink_dialog") + 'title': STRING Title dialog + (defaults to "Open link") + 'text': STRING Body text + (defaults to "Please enter link to file or image") + 'optionName': STRING Name of input link to image or file + (defaults to "Link") + 'ok': STRING Text for OK button + (defaults to "Ok") + 'cancel': STRING Text for Cancel button + (defaults to "Cancel") + 'inputName': STRING Name of hidden input element + (defaults to "input_openlink_dialog") +} +'parentSelector': STRING Parent selector for component + (defaults to null) + + ``` ### Basic Usage @@ -73,8 +138,12 @@ $('input[type=file]').simpleFilePreview(); You can see [more examples](http://jordankasper.com/jquery/preview/examples) on my personal site. -### Tested Browsers +### Tested Browsers * Firefox 16+ * Internet Explorer 8+ * Chrome 22+ + +### NuGet repository + +https://www.myget.org/F/zorg-public/api/v2 \ No newline at end of file diff --git a/jquery.simpleFilePreview.js b/jquery.simpleFilePreview.js index e4f0d0a..684eb69 100644 --- a/jquery.simpleFilePreview.js +++ b/jquery.simpleFilePreview.js @@ -1,7 +1,10 @@ -/* Copyright (c) 2012 Jordan Kasper +/* Copyright (c) 2012-2015 Jordan Kasper, 2015 eusonlito, 2015-2016 Alexei Ivashkevich * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * Copyright notice and license must remain intact for legal use -* Requires: jQuery 1.2+ +* Requires: jQuery 1.9.1+ +* Bootstrap 3.3.4+ (for progressbar only) +* jQuery UI 1.11.4+ (for dialog only) +* context.js 1.0.1 (for context menu only) * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF @@ -9,7 +12,7 @@ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Fore more usage documentation and examples, visit: * http://jordankasper.com/jquery @@ -33,7 +36,46 @@ $('input[type=file]').simpleFilePreview({ 'iconPath': '', // String The path to the folder containing icon images (when a preview is unavailable) - should be absolute, but if relative, must be relative to the page the file input is on 'defaultIcon': 'preview_file.png', // String The file name to use for the defualt preview icon (when a proper file-type-specific icon cannot be found) 'icons': {'png': 'preview_png.png', ...} // Object A mapping of file type (second half of mime type) to icon image file (used in combination with the "iconPath" option) - 'limit': 0 // Limit files on multiple option + 'limit': 0, // Limit files on multiple option + 'removeMessage': { + 'prefix': 'Remove', // Prefix for remove message + 'stub': 'this file' // Stub instead of the file name for remove message + }, + 'radio': { // Display the radio buttons (if necessary) to mark one of the files (only multiple mode) + 'name': string, // Name of input element + 'checkedItem': string // Preselect radio button + }, + 'readOnly': false, // Display with no possibility of modification + 'ajaxUpload': { // Upload file via AJAX + 'url': string, // URL for upload file + 'progressbar': false, // Progressbar for upload file (required Bootstrap) + 'success': function (data, textStatus, jqXHR, inputFileElement), // Callback for ajax success function + 'error': function (jqXHR, textStatus, errorThrown, inputFileElement), // Callback for ajax error function + 'compose': function (formData) // Callback for before send FormData customization + }, + 'beforeRemove': function (element), // Callback for before remove element + 'removeDialog': { // Dialog for remove file (required jQuery UI) + 'id': string, // Dialog Id + 'title': string, // Title dialog + 'text': string, // Body text + 'ok': string, // Text for OK button + 'cancel': string, // Text for Cancel button + 'options': object // jQuery UI Dialog options + }, + 'contextMenu': { // Context menu for select file source + 'fileText': string, // Text for file option + 'linkText': string, // Text for link option + 'id': string, // Dialog Id + 'title': string, // Title dialog + 'text': string, // Body text + 'optionName': string, // Name of input link to image or file + 'ok': string, // Text for OK button + 'cancel': string, // Text for Cancel button + 'inputName': string // Name of hidden input element + 'options': object // jQuery UI Dialog options + }, + 'parentSelector': string, // Parent selector for component + 'defaultOpen': 'file', // Default action on left button click: open file (file) or open link (link) }); * * TODO: @@ -44,195 +86,186 @@ $('input[type=file]').simpleFilePreview({ * 0.1 Initial release * */ -;(function($) { +; (function ($) { 'use strict'; - $.fn.simpleFilePreview = function(options) { + $.fn.simpleFilePreview = function (options) { if (!this || !this.length) { return this; } // Set up options (and defaults) options = options ? options : {}; - options = $.extend({}, $.simpleFilePreview.defaults, options); + options = $.extend(true, {}, $.simpleFilePreview.defaults, options); - this.each(function() { - setup($(this), options); - }); + // read only mode and radio button incompatible + if (options.readOnly) { + options.radio = null; + } - // set up global events - if ($.simpleFilePreview.init) { - return this; + if (options.removeDialog) { + if (!options.removeDialog.id) { options.removeDialog.id = $(this).id + '_remove_dialog'; } + if (!options.removeDialog.title) { options.removeDialog.title = 'Remove'; } + if (!options.removeDialog.text) { options.removeDialog.text = 'Are you sure?'; } + if (!options.removeDialog.ok) { options.removeDialog.ok = 'Ok'; } + if (!options.removeDialog.cancel) { options.removeDialog.cancel = 'Cancel'; } + if (!options.removeDialog.options) { options.removeDialog.options = {}; } + + $('

' + + '' + + options.removeDialog.text + + '

').dialog($.extend({ + autoOpen: false, + resizable: false, + modal: true + }, options.removeDialog.options)); + } + + if (options.contextMenu) { + if (!options.contextMenu.fileText) { options.contextMenu.fileText = 'Open file'; } + if (!options.contextMenu.linkText) { options.contextMenu.linkText = 'Open link'; } + if (!options.contextMenu.id) { options.contextMenu.id = $(this).id + '_openlink_dialog'; } + if (!options.contextMenu.title) { options.contextMenu.title = 'Open link'; } + if (!options.contextMenu.text) { options.contextMenu.text = 'Please enter link to file or image'; } + if (!options.contextMenu.optionName) { options.contextMenu.optionName = 'Link'; } + if (!options.contextMenu.ok) { options.contextMenu.ok = 'Ok'; } + if (!options.contextMenu.cancel) { options.contextMenu.cancel = 'Cancel'; } + if (!options.contextMenu.inputName) { options.contextMenu.inputName = 'input_openlink_dialog'; } + if (!options.contextMenu.options) { options.contextMenu.options = {}; } + + var $gbody = $('body'); + var gbodyOverflow = $gbody.css('overflow'); + $('

' + + options.contextMenu.text + + '

' + + '' + + '' + + '
' + + '

').dialog($.extend({ + autoOpen: false, + resizable: false, + modal: true, + position: { my: "center", at: "center", of: window }, + open: function (event, ui) { + gbodyOverflow = $gbody.css('overflow'); + $gbody.css('overflow', 'hidden'); + }, + close: function (event, ui) { + $gbody.css('overflow', gbodyOverflow); + }, + buttons: [ + { + text: options.contextMenu.ok, + click: function () { + var $element = $(((options.parentSelector) ? options.parentSelector : 'body') + ' li:has(a.simpleFilePreview_input:visible) input[name^="' + options.contextMenu.inputName + '"]'); + var $link = $('#' + options.contextMenu.id + '_link'); + $element.val($link.val()); + fileProcess(options, $element, 'link'); + $link.val(""); + $(this).dialog("close"); + } + }, { + text: options.contextMenu.cancel, + click: function () { + $(this).dialog("close"); + } + }] + }, options.contextMenu.options)); + + var selector = ((options.parentSelector) ? options.parentSelector : 'body') + ' li:has(a.simpleFilePreview_input:visible)'; + context.init({ preventDoubleContext: false }); + context.settings({ compress: true }); + context.attach(selector, [ + { + text: options.contextMenu.fileText, + action: function (e) { + openFileDialog(e, options, selector); + } + }, { + text: options.contextMenu.linkText, + action: function (e) { + openLinkDialog(e, options); + } + }]); } - var $body = $('body'); + this.each(function () { + setup($(this), options); + }); - $.simpleFilePreview.init = true; + var $body = ((options.parentSelector) ? $(options.parentSelector + ' .simpleFilePreview_body') : $(this).closest('.simpleFilePreview_body')); // open file browser dialog on click of styled "button" - $body.on('click', '.simpleFilePreview_input', function(e) { - $(this).closest('.simpleFilePreview').find('input.simpleFilePreview_formInput').trigger('click'); - e.preventDefault(); + $body.on('click', '.simpleFilePreview_input', function (e) { + if (options.defaultOpen == 'link') { + openLinkDialog(e, options); + } else { + openFileDialog(e, options, e.currentTarget); + } }); // on click of the actual input (which is invisible), check to see if // we need to clear the input (which is the default action for this plugin) - $body.on('click', '.simpleFilePreview input.simpleFilePreview_formInput', function(e) { + $body.on('click', '.simpleFilePreview input.simpleFilePreview_formInput', function (e) { if (!$(this).val().length) { return this; } - $(this).closest('.simpleFilePreview').find('.simpleFilePreview_preview').trigger('click'); + if (!options.readOnly) { + $(this).closest('.simpleFilePreview').find('.simpleFilePreview_preview').trigger('click'); + } e.preventDefault(); }); // when file input changes, get file contents and show preview (if it's an image) - $body.on('change', '.simpleFilePreview input.simpleFilePreview_formInput', function(e) { - var $parents = $(this).closest('.simpleFilePreview'); - - // if it's a multi-select, add another selection box to the end - // NOTE: this is done first since we clone the previous input - // NOTE: the second check is there because IE 8 fires multiple change events for no good reason - if (($parents.attr('data-sfpallowmultiple') == 1) && !$parents.find('.simpleFilePreview_preview').length) { - var newId = $.simpleFilePreview.uid++; - var $newN = $parents.clone(true).attr('id', "simpleFilePreview_" + newId); - - $newN.find('input.simpleFilePreview_formInput') - .attr('id', $newN.find('input.simpleFilePreview_formInput').attr('id') + '_' + newId) - .val(''); - - $parents.after($newN); - - var nw = $parents.closest('.simpleFilePreview_multi').width('+=' + $newN.outerWidth(true)).width(); - - if (nw > $parents.closest('.simpleFilePreview_multiClip').width()) { - $parents.closest('.simpleFilePreview_multiUI').find('.simpleFilePreview_shiftRight').trigger('click'); - } - } - - if (this.files && this.files[0]) { - var exp = new RegExp("^image\/(" + $.simpleFilePreview.previewFileTypes + ")$"); - - if (exp.test(this.files[0].type.toLowerCase()) && window.FileReader) { - // show preview of image file - var $FR = new FileReader(); - - $FR.onload = function(e) { - addOrChangePreview($parents, e.target.result, '', options); - }; - - $FR.readAsDataURL(this.files[0]); - } else { - // show icon if not an image upload - var m = this.files[0].type.toLowerCase().match(/^\s*[^\/]+\/([a-zA-Z0-9\-\.]+)\s*$/); - - if (m && m[1] && options.icons[m[1]]) { - addOrChangePreview($parents, options.icons[m[1]], getFilename(this.value), options); - } else { - addOrChangePreview($parents, options.defaultIcon, getFilename(this.value), options); - } - } - - return this; - } - - // Any browser not supporting the File API (and FileReader) - - // Some versions of IE don't have real paths, and can't support - // any other way to do file preview without uploading to the server - // If a browser does report a valid path (IE or otherwise), then - // we'll try to get the file preview - - var exp = new RegExp("^(" + $.simpleFilePreview.previewFileTypes + ")$"); - - var ext = getFileExt(this.value); - ext = ext ? ext.toLowerCase() : null; - - if (ext && !(/fakepath/.test(this.value.toLowerCase())) && exp.test(e)) { - // older versions of IE (and some other browsers) report the local - // file path, so try to get a preview that way - addOrChangePreview($parents, "file://" + this.value, '', options); - } else { - // not an image (or using fakepath), so no preview anyway - if (options.icons[ext]) { - addOrChangePreview($parents, options.icons[ext], getFilename(this.value), options); - } else { - addOrChangePreview($parents, options.defaultIcon, getFilename(this.value), options); - } - } + $body.on('change', '.simpleFilePreview input.simpleFilePreview_formInput', function (e) { + fileProcess(options, $(this), 'file'); }); // show or hide "remove" icon for file preview/icon - $body.on('mouseover', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() { - var $parents = $(this).closest('.simpleFilePreview'); + $body.on('mouseover', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function () { + if (!options.readOnly) { + var $parents = $(this).closest('.simpleFilePreview'); - if ($parents.find('.simpleFilePreview_preview').is(':visible')) { - $parents.find('.simpleFilePreview_remove').show(); + if ($parents.find('.simpleFilePreview_preview').is(':visible')) { + $parents.find('.simpleFilePreview_remove').show(); + } } }); - $body.on('mouseout', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() { + $body.on('mouseout', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function () { $(this).closest('.simpleFilePreview').find('.simpleFilePreview_remove').hide(); }) // remove file when preview/icon is clicked - $body.on('click', '.simpleFilePreview_preview', function() { - var $this = $(this); - var $parents = $this.closest('.simpleFilePreview'); - - if ($parents.attr('data-sfpallowmultiple') == 1 && $parents.siblings('.simpleFilePreview').length) { - if ($parents.hasClass('simpleFilePreview_existing')) { - $parents.parent().append(""); - } - - limit($this, options, 1); - - $parents.closest('.simpleFilePreview_multi').width('-=' + $parents.width()); - $parents.remove(); - - return this; - } - - // if it was an existing file, show file input and add "removeFiles" hidden input - if ($parents.hasClass('simpleFilePreview_existing')) { - $parents.find('input.simpleFilePreview_formInput').show(); - $parents.append(""); - $parents.removeClass('simpleFilePreview_existing'); // no longer needed - } - - limit($this, options, 1); - - // kill value in the input - var $input = $parents.find('input.simpleFilePreview_formInput').val(''); - - // Some browsers (*cough*IE*cough*) do not allow us to set val() - // on a file input, so we have to clone it without the value - if ($input && $input.length && $input.val().length) { - var attr = $input.get(0).attributes; - var a = ""; - - for (var j = 0, l = attr.length; j < l; ++j) { - if (attr[j].name != 'value' && attr[j].name != 'title') { - a += attr[j].name + "='" + $input.attr(attr[j].name) + "' "; - } + $body.on('click', '.simpleFilePreview_preview', function () { + if (!options.readOnly) { + var $pic = $(this); + if (!options.removeDialog) { + remove($pic, options); + } else { + var $dialog = $('#' + options.removeDialog.id); + $dialog.dialog('option', + 'buttons', [{ + text: options.removeDialog.ok, + click: function () { + remove($pic, options); + $(this).dialog("close"); + } + }, { + text: options.removeDialog.cancel, + click: function () { + $(this).dialog("close"); + } + }]); + $dialog.dialog("open"); } - - $input.before(''); - $input.remove(); } - - // remove the preview element - $this.remove(); - $parents.find('.simpleFilePreview_filename').remove(); - - // show styled input "button" - $parents.find('.simpleFilePreview_remove').hide().end() - .find('.simpleFilePreview_input').show(); }); // shift buttons for multi-selects - $body.on('click', '.simpleFilePreview_shiftRight', function() { + $body.on('click', '.simpleFilePreview_shiftRight', function () { var ul = $(this).closest('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi'); var width = parseInt(ul.css('left')) + ul.width(); @@ -244,7 +277,7 @@ $('input[type=file]').simpleFilePreview({ } }); - $body.on('click', '.simpleFilePreview_shiftLeft', function() { + $body.on('click', '.simpleFilePreview_shiftLeft', function () { var ul = $(this).closest('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi'); var left = parseInt(ul.css('left')); @@ -260,7 +293,64 @@ $('input[type=file]').simpleFilePreview({ return this; }; - var limit = function($this, options, add) { + var remove = function ($this, options) { + var $parents = $this.closest('.simpleFilePreview'); + + if (options.beforeRemove != null) { + options.beforeRemove($parents); + } + + if ($parents.attr('data-sfpallowmultiple') == 1 && $parents.siblings('.simpleFilePreview').length) { + if ($parents.hasClass('simpleFilePreview_existing')) { + $parents.parent().append(""); + } + + limit($this, options, 1); + + $parents.closest('.simpleFilePreview_multi').width('-=' + $parents.width()); + $parents.remove(); + + return this; + } + + // if it was an existing file, show file input and add "removeFiles" hidden input + if ($parents.hasClass('simpleFilePreview_existing')) { + $parents.find('input.simpleFilePreview_formInput').show(); + $parents.append(""); + $parents.removeClass('simpleFilePreview_existing'); // no longer needed + } + + limit($this, options, 1); + + // kill value in the input + var $input = $parents.find('input.simpleFilePreview_formInput').val(''); + + // Some browsers (*cough*IE*cough*) do not allow us to set val() + // on a file input, so we have to clone it without the value + if ($input && $input.length && $input.val().length) { + var attr = $input.get(0).attributes; + var a = ""; + + for (var j = 0, l = attr.length; j < l; ++j) { + if (attr[j].name != 'value' && attr[j].name != 'title') { + a += attr[j].name + "='" + $input.attr(attr[j].name) + "' "; + } + } + + $input.before(''); + $input.remove(); + } + + // remove the preview element + $this.remove(); + $parents.find('.simpleFilePreview_filename').remove(); + + // show styled input "button" + $parents.find('.simpleFilePreview_remove').hide().end() + .find('.simpleFilePreview_input').show(); + }; + + var limit = function ($this, options, add) { if (!options.limit) { return false; } @@ -275,37 +365,44 @@ $('input[type=file]').simpleFilePreview({ } }; - var setup = function(these, options) { + var setup = function (these, options) { var isMulti = these.is('[multiple]'); // "multiple" removed because it's handled later manually these = these.removeAttr('multiple').addClass('simpleFilePreview_formInput'); + // multiple mode and radio button incompatible + if (!isMulti) { + options.radio = null; + } + // wrap input with necessary structure var $html = $("<" + (isMulti ? 'li' : 'div') + " id='simpleFilePreview_" + ($.simpleFilePreview.uid++) + "'" - + " class='simpleFilePreview' data-sfpallowmultiple='" + (isMulti ? 1 : 0) + "'>" + + " class='simpleFilePreview" + ((options.radio) ? " simpleFilePreview_withRadio" : "") + "' data-sfpallowmultiple='" + (isMulti ? 1 : 0) + "'>" + "" + options.buttonContent + "" + "" + options.removeContent + "" + + ((options.radio) ? "" : "") + + ((options.ajaxUpload.progressbar) ? "
" : "") + + ((options.contextMenu) ? '' : '') + ""); these.before($html); $html.append(these); - // mostly for IE, the file input must be sized the same as the container, - // opacity 0, and z-indexed above other elements within the preview container - these.css({ - width: ($html.width() + 'px'), - height: ($html.height() + 'px') - }); + if (options.readOnly) { + $html.hide(); + } // if it's a multi-select we use multiple separate inputs instead to support file preview if (isMulti) { - $html.wrap("
"); + $html.wrap("
"); $html.closest('.simpleFilePreview_multiUI') .prepend("" + options.shiftRight + "") .append("" + options.shiftLeft + ""); + } else { + $html.wrap("
"); } var exists = options.existingFiles; @@ -328,9 +425,14 @@ $('input[type=file]').simpleFilePreview({ var ni = $.simpleFilePreview.uid++; var nn = $html.clone(true).attr('id', "simpleFilePreview_" + ni); + if (options.contextMenu) { + nn.find('[name^="' + options.contextMenu.inputName + '"]').attr('name', options.contextMenu.inputName + '[' + ++$.simpleFilePreview.linkid + ']').val(''); + } + nn.addClass('simpleFilePreview_existing') .attr('data-sfprid', arr ? exists[i] : i) .find('input.simpleFilePreview_formInput').remove(); + nn.show(); $html.before(nn); @@ -344,10 +446,18 @@ $('input[type=file]').simpleFilePreview({ } else { addOrChangePreview(nn, options.defaultIcon, getFilename(exists[i]), options); } + + if (options.radio) { + nn.find('input.simpleFilePreview_radio').val(nn.attr('data-sfprid')); + } } $('.simpleFilePreview_multi').width($html.outerWidth(true) * $html.parent().find('.simpleFilePreview').length); + if (options.radio) { + $html.closest('.simpleFilePreview_multi').find("input[type='radio'][value='" + options.radio.checkedItem + "']").prop("checked", true); + } + return these; } @@ -385,9 +495,9 @@ $('input[type=file]').simpleFilePreview({ return these; }; - var addOrChangePreview = function($parents, src, filename, options) { + var addOrChangePreview = function ($parents, src, filename, options) { filename = filename ? filename : null; - src = ((new RegExp('[/\\\\]')).test(src) ? '' : (options.iconPath)) + src + src = ((new RegExp('^(http|https)://').test(src)) ? src : (((new RegExp('[/\\\\]')).test(src) ? '' : (options.iconPath)) + src)); $parents.find('.simpleFilePreview_input').hide(); @@ -399,10 +509,10 @@ $('input[type=file]').simpleFilePreview({ $parents.append("" + (filename ? filename : "); + + " title='" + options.removeMessage.prefix + ' ' + (filename ? filename : options.removeMessage.stub) + "' />"); // for tooltips - $parents.find('input.simpleFilePreview_formInput').attr('title', "Remove " + (filename ? filename : 'this file')); + $parents.find('input.simpleFilePreview_formInput').attr('title', options.removeMessage.prefix + " " + (filename ? filename : options.removeMessage.stub)); } limit($parents, options); @@ -421,7 +531,7 @@ $('input[type=file]').simpleFilePreview({ } }; - var getFilename = function($parents) { + var getFilename = function ($parents) { var m = $parents.match(/[\/\\]([^\/\\]+)$/); if (m && m[1] && m[1].length) { @@ -431,7 +541,7 @@ $('input[type=file]').simpleFilePreview({ return null; }; - var getFileExt = function($parents) { + var getFileExt = function ($parents) { var m = $parents.match(/[\.]([^\/\\\.]+)$/); if (m && m[1] && m[1].length) { @@ -441,9 +551,179 @@ $('input[type=file]').simpleFilePreview({ return null; }; + var openLinkDialog = function (e, options) { + window.scrollTo(0, 0); + $('#' + options.contextMenu.id).dialog("open"); + }; + + var openFileDialog = function (e, options, that) { + $(that).closest('.simpleFilePreview').find('input.simpleFilePreview_formInput').trigger('click'); + e.preventDefault(); + }; + + var fileProcess = function (options, $this, type) { + if (!options.readOnly) { + var _this = $this.get()[0]; + if (options.ajaxUpload) { + var fd = new FormData(); + var cutNameToken = _this.name.indexOf('['); + var value = ((type == 'file') ? _this.files[0] : ((type == 'link') ? $this.val() : '')); + if (cutNameToken > -1) { + fd.append(_this.name.substr(0, cutNameToken), value); + } else { + fd.append(_this.name, value); + } + + if (options.ajaxUpload.compose) { + options.ajaxUpload.compose(fd); + } + + if (options.ajaxUpload.progressbar) { + $this.parent().find('.simpleFilePreview_progress').show(); + } + + $.ajax({ + url: options.ajaxUpload.url, + type: "POST", + data: fd, + dataType: 'json', + contentType: false, + processData: false, + success: function (data, textStatus, jqXHR) { + if (options.ajaxUpload.progressbar) { + $this.parent().find('.simpleFilePreview_progress').hide(); + } + if (options.ajaxUpload.success) { + options.ajaxUpload.success(data, textStatus, jqXHR, _this); + } + }, + error: function (jqXHR, textStatus, errorThrown) { + if (options.ajaxUpload.progressbar) { + $this.parent().find('.simpleFilePreview_progress').hide(); + } + if (options.ajaxUpload.error) { + options.ajaxUpload.error(jqXHR, textStatus, errorThrown, _this); + } + }, + xhr: function () { + var xhr = new window.XMLHttpRequest(); + //Upload progress + xhr.upload.addEventListener("progress", function (evt) { + if (evt.lengthComputable && options.ajaxUpload.progressbar) { + var percentComplete = evt.loaded * 100 / evt.total; + var progressbar = $this.parent().find('.simpleFilePreview_progress div'); + progressbar.css({ width: percentComplete + '%' }).attr('aria-valuenow', percentComplete); + } + }, false); + return xhr; + } + }); + } + + var $parents = $this.closest('.simpleFilePreview'); + + // if it's a multi-select, add another selection box to the end + // NOTE: this is done first since we clone the previous input + // NOTE: the second check is there because IE 8 fires multiple change events for no good reason + if (($parents.attr('data-sfpallowmultiple') == 1) && !$parents.find('.simpleFilePreview_preview').length) { + var newId = $.simpleFilePreview.uid++; + var $newN = $parents.clone(true).attr('id', "simpleFilePreview_" +newId); + + if (options.contextMenu) { + $newN.find('[name^="' + options.contextMenu.inputName + '"]').attr('name', options.contextMenu.inputName + '[' + ++$.simpleFilePreview.linkid + ']').val(''); + } + + if (options.ajaxUpload.progressbar) { + $newN.find('.simpleFilePreview_progress').hide(); + } + + $newN.find('input.simpleFilePreview_formInput') + .attr('id', $newN.find('input.simpleFilePreview_formInput').attr('id') + '_' + newId) + .attr('name', function (index, previousValue) { + var previousName = $parents.find('input.simpleFilePreview_formInput').attr('name'); + var inputIndex = parseInt(previousName.substring(previousName.indexOf('[') + 1, previousName.indexOf(']'))); + return (!isNaN(inputIndex)) ? previousName.substring(0, previousName.indexOf('[') + 1) + ++inputIndex + previousName.substring(previousName.indexOf(']')) : previousValue; + }) + .val(''); + + $parents.after($newN); + + var nw = $parents.closest('.simpleFilePreview_multi').width('+=' + $newN.outerWidth(true)).width(); + + if (nw > $parents.closest('.simpleFilePreview_multiClip').width()) { + $parents.closest('.simpleFilePreview_multiUI').find('.simpleFilePreview_shiftRight').trigger('click'); + } + } + + var ext = getFileExt(_this.value); + ext = ext ? ext.toLowerCase(): null; + + if ((type == 'file') && _this.files && _this.files[0]) { + var exp = new RegExp("^image\/(" + $.simpleFilePreview.previewFileTypes + ")$"); + + if (exp.test(_this.files[0].type.toLowerCase()) && window.FileReader) { + // show preview of image file + var $FR = new FileReader(); + + $FR.onload = function (e) { + addOrChangePreview($parents, e.target.result, '', options); + }; + + $FR.readAsDataURL(_this.files[0]); + } else { + // show icon if not an image upload + var m = _this.files[0].type.toLowerCase().match(/^\s*[^\/]+\/([a-zA-Z0-9\-\.]+)\s*$/); + + if (m && m[1] && options.icons[m[1]]) { + addOrChangePreview($parents, options.icons[m[1]], getFilename(_this.value), options); + } else { + addOrChangePreview($parents, options.defaultIcon, getFilename(_this.value), options); + } + } + + if (options.radio) { + $parents.find('input.simpleFilePreview_radio').val($parents.context.files[0].name); + } + + return _this; + } + + if (type == 'file') { + // Any browser not supporting the File API (and FileReader) + // Some versions of IE don't have real paths, and can't support + // any other way to do file preview without uploading to the server + // If a browser does report a valid path (IE or otherwise), then + // we'll try to get the file preview + var exp = new RegExp("^(" +$.simpleFilePreview.previewFileTypes + ")$"); + + if (ext && !(/fakepath/.test(_this.value.toLowerCase())) && exp.test(e)) { + // older versions of IE (and some other browsers) report the local + // file path, so try to get a preview that way + addOrChangePreview($parents, "file://" +_this.value, '', options); + } else { + // not an image (or using fakepath), so no preview anyway + if (options.icons[ext]) { + addOrChangePreview($parents, options.icons[ext], getFilename(_this.value), options); + } else { + addOrChangePreview($parents, options.defaultIcon, getFilename(_this.value), options); + } + } + } + + if (type == 'link') { + var exp = new RegExp("^(" + $.simpleFilePreview.previewFileTypes + ")$"); + if (exp.test(ext)) { + addOrChangePreview($parents, $this.val(), '', options); + } else { + addOrChangePreview($parents, _this.value, getFilename(_this.value), options); + } + } + } + }; + // Static properties $.simpleFilePreview = { - defaults: { + defaults: { 'buttonContent': 'Add File', 'removeContent': 'X', 'existingFiles': null, // array or object. if object, key is used in the remove hidden input @@ -452,6 +732,18 @@ $('input[type=file]').simpleFilePreview({ 'iconPath': '', 'defaultIcon': 'preview_file.png', 'limit': 0, + 'removeMessage': { + 'prefix': 'Remove', + 'stub': 'this file', + }, + 'radio': null, + 'readOnly': false, + 'ajaxUpload': null, + 'beforeRemove': null, + 'removeDialog': null, + 'contextMenu': null, + 'parentSelector': null, + 'defaultOpen': 'file', 'icons': { 'png': 'preview_png.png', 'gif': 'preview_png.png', @@ -493,6 +785,7 @@ $('input[type=file]').simpleFilePreview({ } }, uid: 0, + linkid: 0, init: false, previewFileTypes: 'p?jpe?g|png|gif|bmp|svg' }; diff --git a/jquery.simpleFilePreview.min.js b/jquery.simpleFilePreview.min.js index 4a87b07..04737b4 100644 --- a/jquery.simpleFilePreview.min.js +++ b/jquery.simpleFilePreview.min.js @@ -1,6 +1,6 @@ /*! * jquery.simpleFilePreview v0.1.0 (https://github.com/jakerella/jquerySimpleFilePreview) - * Copyright (c) 2012 Jordan Kasper + * Copyright (c) 2012-2015 Jordan Kasper, 2015 eusonlito, 2015-2016 Alexei Ivashkevich * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -!function(a){"use strict";a.fn.simpleFilePreview=function(g){if(!this||!this.length)return this;if(g=g?g:{},g=a.extend({},a.simpleFilePreview.defaults,g),this.each(function(){c(a(this),g)}),a.simpleFilePreview.init)return this;var h=a("body");return a.simpleFilePreview.init=!0,h.on("click",".simpleFilePreview_input",function(b){a(this).closest(".simpleFilePreview").find("input.simpleFilePreview_formInput").trigger("click"),b.preventDefault()}),h.on("click",".simpleFilePreview input.simpleFilePreview_formInput",function(b){return a(this).val().length?(a(this).closest(".simpleFilePreview").find(".simpleFilePreview_preview").trigger("click"),void b.preventDefault()):this}),h.on("change",".simpleFilePreview input.simpleFilePreview_formInput",function(b){var c=a(this).closest(".simpleFilePreview");if(1==c.attr("data-sfpallowmultiple")&&!c.find(".simpleFilePreview_preview").length){var h=a.simpleFilePreview.uid++,i=c.clone(!0).attr("id","simpleFilePreview_"+h);i.find("input.simpleFilePreview_formInput").attr("id",i.find("input.simpleFilePreview_formInput").attr("id")+"_"+h).val(""),c.after(i);var j=c.closest(".simpleFilePreview_multi").width("+="+i.outerWidth(!0)).width();j>c.closest(".simpleFilePreview_multiClip").width()&&c.closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_shiftRight").trigger("click")}if(this.files&&this.files[0]){var k=new RegExp("^image/("+a.simpleFilePreview.previewFileTypes+")$");if(k.test(this.files[0].type.toLowerCase())&&window.FileReader){var l=new FileReader;l.onload=function(a){d(c,a.target.result,"",g)},l.readAsDataURL(this.files[0])}else{var m=this.files[0].type.toLowerCase().match(/^\s*[^\/]+\/([a-zA-Z0-9\-\.]+)\s*$/);m&&m[1]&&g.icons[m[1]]?d(c,g.icons[m[1]],e(this.value),g):d(c,g.defaultIcon,e(this.value),g)}return this}var k=new RegExp("^("+a.simpleFilePreview.previewFileTypes+")$"),n=f(this.value);n=n?n.toLowerCase():null,n&&!/fakepath/.test(this.value.toLowerCase())&&k.test(b)?d(c,"file://"+this.value,"",g):g.icons[n]?d(c,g.icons[n],e(this.value),g):d(c,g.defaultIcon,e(this.value),g)}),h.on("mouseover",".simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput",function(){var b=a(this).closest(".simpleFilePreview");b.find(".simpleFilePreview_preview").is(":visible")&&b.find(".simpleFilePreview_remove").show()}),h.on("mouseout",".simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput",function(){a(this).closest(".simpleFilePreview").find(".simpleFilePreview_remove").hide()}),h.on("click",".simpleFilePreview_preview",function(){var c=a(this),d=c.closest(".simpleFilePreview");if(1==d.attr("data-sfpallowmultiple")&&d.siblings(".simpleFilePreview").length)return d.hasClass("simpleFilePreview_existing")&&d.parent().append(""),b(c,g,1),d.closest(".simpleFilePreview_multi").width("-="+d.width()),d.remove(),this;d.hasClass("simpleFilePreview_existing")&&(d.find("input.simpleFilePreview_formInput").show(),d.append(""),d.removeClass("simpleFilePreview_existing")),b(c,g,1);var e=d.find("input.simpleFilePreview_formInput").val("");if(e&&e.length&&e.val().length){for(var f=e.get(0).attributes,h="",i=0,j=f.length;i'),e.remove()}c.remove(),d.find(".simpleFilePreview_filename").remove(),d.find(".simpleFilePreview_remove").hide().end().find(".simpleFilePreview_input").show()}),h.on("click",".simpleFilePreview_shiftRight",function(){var b=a(this).closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_multi"),c=parseInt(b.css("left"))+b.width();if(c>b.parent().width()){var d=b.find("li:first");b.animate({left:"-="+d.outerWidth(!0)})}}),h.on("click",".simpleFilePreview_shiftLeft",function(){var b=a(this).closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_multi"),c=parseInt(b.css("left"));if(c<0){var d=b.find("li:first").outerWidth(!0);b.animate({left:c+d<1?"+="+d:0})}}),this};var b=function(a,b,c){if(!b.limit)return!1;var d=a.closest(".simpleFilePreview_multi").find("> li");c=c?c:0,d.length>b.limit+c?d.last().hide():d.last().show()},c=function(b,c){var g=b.is("[multiple]");b=b.removeAttr("multiple").addClass("simpleFilePreview_formInput");var h=a("<"+(g?"li":"div")+" id='simpleFilePreview_"+a.simpleFilePreview.uid++ +"' class='simpleFilePreview' data-sfpallowmultiple='"+(g?1:0)+"'>"+c.buttonContent+""+c.removeContent+"");b.before(h),h.append(b),b.css({width:h.width()+"px",height:h.height()+"px"}),g&&(h.wrap("
    "),h.closest(".simpleFilePreview_multiUI").prepend(""+c.shiftRight+"").append(""+c.shiftLeft+""));var i=c.existingFiles;if(!i)return g&&a(".simpleFilePreview_multi").width(h.outerWidth(!0)*h.parent().find(".simpleFilePreview").length),b;var j=new RegExp("^("+a.simpleFilePreview.previewFileTypes+")$");if(g){var k=a.isArray(i)?1:0;for(var l in i){var m=a.simpleFilePreview.uid++,n=h.clone(!0).attr("id","simpleFilePreview_"+m);n.addClass("simpleFilePreview_existing").attr("data-sfprid",k?i[l]:l).find("input.simpleFilePreview_formInput").remove(),h.before(n);var o=f(i[l]);o=o?o.toLowerCase():null,o&&j.test(o)?d(n,i[l],"",c):c.icons[o]?d(n,c.icons[o],e(i[l]),c):d(n,c.defaultIcon,e(i[l]),c)}return a(".simpleFilePreview_multi").width(h.outerWidth(!0)*h.parent().find(".simpleFilePreview").length),b}var p=null,k=a.isArray(i)?1:0;for(var l in i)p={id:k?i[l]:l,file:i[l]};if(!p)return b;h.attr("data-sfprid",p.id).addClass("simpleFilePreview_existing").find("input.simpleFilePreview_formInput").hide();var o=f(p.file);return o=o?o.toLowerCase():null,o&&j.test(o)?d(h,p.file,"",c):c.icons[o]?d(h,c.icons[o],e(p.file),c):d(h,c.defaultIcon,e(p.file),c),b},d=function(a,c,d,e){d=d?d:null,c=(new RegExp("[/\\\\]").test(c)?"":e.iconPath)+c,a.find(".simpleFilePreview_input").hide();var f=a.find(".simpleFilePreview_preview");if(f&&f.length?f.attr("src",c):(a.append(""+(d?d:"File Preview")+""),a.find("input.simpleFilePreview_formInput").attr("title","Remove "+(d?d:"this file"))),b(a,e),!d)return null;var g=a.find(".simpleFilePreview_filename");g&&g.length?g.text(d):a.append(""+d+"").find(".simpleFilePreview_filename")},e=function(a){var b=a.match(/[\/\\]([^\/\\]+)$/);return b&&b[1]&&b[1].length?b[1]:null},f=function(a){var b=a.match(/[\.]([^\/\\\.]+)$/);return b&&b[1]&&b[1].length?b[1]:null};a.simpleFilePreview={defaults:{buttonContent:"Add File",removeContent:"X",existingFiles:null,shiftLeft:"<<",shiftRight:">>",iconPath:"",defaultIcon:"preview_file.png",limit:0,icons:{png:"preview_png.png",gif:"preview_png.png",bmp:"preview_png.png",svg:"preview_png.png",jpg:"preview_png.png",jpeg:"preview_png.png",pjpg:"preview_png.png",pjpeg:"preview_png.png",tif:"preview_png.png",tiff:"preview_png.png",mp3:"preview_mp3.png",mp4:"preview_mp3.png",wav:"preview_mp3.png",wma:"preview_mp3.png",pdf:"preview_pdf.png",txt:"preview_txt.png",rtf:"preview_txt.png",text:"preview_txt.png",plain:"preview_txt.png",zip:"preview_zip.png",tgz:"preview_zip.png","x-rar-compressed":"preview_zip.png","octet-stream":"preview_zip.png",odf:"preview_doc.png",odt:"preview_doc.png",doc:"preview_doc.png",msword:"preview_doc.png","vnd.openxmlformats-officedocument.wordprocessingml.document":"preview_doc.png",docx:"preview_doc.png",ods:"preview_xls.png","vnd.ms-excel":"preview_xls.png",xls:"preview_xls.png",xlx:"preview_xls.png",msexcel:"preview_xls.png","x-excel":"preview_xls.png","x-ms-excel":"preview_xls.png","vnd.openxmlformats-officedocument.spreadsheetml.sheet":"preview_xls.png"}},uid:0,init:!1,previewFileTypes:"p?jpe?g|png|gif|bmp|svg"}}(jQuery); \ No newline at end of file +!function (i) { "use strict"; i.fn.simpleFilePreview = function (e) { if (!this || !this.length) return this; if (e = e ? e : {}, e = i.extend(!0, {}, i.simpleFilePreview.defaults, e), e.readOnly && (e.radio = null), e.removeDialog && (e.removeDialog.id || (e.removeDialog.id = i(this).id + "_remove_dialog"), e.removeDialog.title || (e.removeDialog.title = "Remove"), e.removeDialog.text || (e.removeDialog.text = "Are you sure?"), e.removeDialog.ok || (e.removeDialog.ok = "Ok"), e.removeDialog.cancel || (e.removeDialog.cancel = "Cancel"), e.removeDialog.options || (e.removeDialog.options = {}), i('

    ' + e.removeDialog.text + "

    ").dialog(i.extend({ autoOpen: !1, resizable: !1, modal: !0 }, e.removeDialog.options))), e.contextMenu) { e.contextMenu.fileText || (e.contextMenu.fileText = "Open file"), e.contextMenu.linkText || (e.contextMenu.linkText = "Open link"), e.contextMenu.id || (e.contextMenu.id = i(this).id + "_openlink_dialog"), e.contextMenu.title || (e.contextMenu.title = "Open link"), e.contextMenu.text || (e.contextMenu.text = "Please enter link to file or image"), e.contextMenu.optionName || (e.contextMenu.optionName = "Link"), e.contextMenu.ok || (e.contextMenu.ok = "Ok"), e.contextMenu.cancel || (e.contextMenu.cancel = "Cancel"), e.contextMenu.inputName || (e.contextMenu.inputName = "input_openlink_dialog"), e.contextMenu.options || (e.contextMenu.options = {}); var l = i("body"), r = l.css("overflow"); i('

    ' + e.contextMenu.text + '

    ').dialog(i.extend({ autoOpen: !1, resizable: !1, modal: !0, position: { my: "center", at: "center", of: window }, open: function (e, i) { r = l.css("overflow"), l.css("overflow", "hidden") }, close: function (e, i) { l.css("overflow", r) }, buttons: [{ text: e.contextMenu.ok, click: function () { var t = i((e.parentSelector ? e.parentSelector : "body") + ' li:has(a.simpleFilePreview_input:visible) input[name^="' + e.contextMenu.inputName + '"]'), l = i("#" + e.contextMenu.id + "_link"); t.val(l.val()), a(e, t, "link"), l.val(""), i(this).dialog("close") } }, { text: e.contextMenu.cancel, click: function () { i(this).dialog("close") } }] }, e.contextMenu.options)); var s = (e.parentSelector ? e.parentSelector : "body") + " li:has(a.simpleFilePreview_input:visible)"; context.init({ preventDoubleContext: !1 }), context.settings({ compress: !0 }), context.attach(s, [{ text: e.contextMenu.fileText, action: function (e) { i(s).find(".simpleFilePreview_input").trigger("click") } }, { text: e.contextMenu.linkText, action: function (i) { o(i, e) } }]) } this.each(function () { n(i(this), e) }); var p = e.parentSelector ? i(e.parentSelector + " .simpleFilePreview_body") : i(this).closest(".simpleFilePreview_body"); return p.on("click", ".simpleFilePreview_input", function (e) { i(this).closest(".simpleFilePreview").find("input.simpleFilePreview_formInput").trigger("click"), e.preventDefault() }), p.on("click", ".simpleFilePreview input.simpleFilePreview_formInput", function (t) { return i(this).val().length ? (e.readOnly || i(this).closest(".simpleFilePreview").find(".simpleFilePreview_preview").trigger("click"), void t.preventDefault()) : this }), p.on("change", ".simpleFilePreview input.simpleFilePreview_formInput", function (t) { a(e, i(this), "file") }), p.on("mouseover", ".simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput", function () { if (!e.readOnly) { var t = i(this).closest(".simpleFilePreview"); t.find(".simpleFilePreview_preview").is(":visible") && t.find(".simpleFilePreview_remove").show() } }), p.on("mouseout", ".simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput", function () { i(this).closest(".simpleFilePreview").find(".simpleFilePreview_remove").hide() }), p.on("click", ".simpleFilePreview_preview", function () { if (!e.readOnly) { var l = i(this); if (e.removeDialog) { var n = i("#" + e.removeDialog.id); n.dialog("option", "buttons", [{ text: e.removeDialog.ok, click: function () { t(l, e), i(this).dialog("close") } }, { text: e.removeDialog.cancel, click: function () { i(this).dialog("close") } }]), n.dialog("open") } else t(l, e) } }), p.on("click", ".simpleFilePreview_shiftRight", function () { var e = i(this).closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_multi"), t = parseInt(e.css("left")) + e.width(); if (t > e.parent().width()) { var l = e.find("li:first"); e.animate({ left: "-=" + l.outerWidth(!0) }) } }), p.on("click", ".simpleFilePreview_shiftLeft", function () { var e = i(this).closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_multi"), t = parseInt(e.css("left")); if (0 > t) { var l = e.find("li:first").outerWidth(!0); e.animate({ left: 1 > t + l ? "+=" + l : 0 }) } }), this }; var t = function (e, i) { var t = e.closest(".simpleFilePreview"); if (null != i.beforeRemove && i.beforeRemove(t), 1 == t.attr("data-sfpallowmultiple") && t.siblings(".simpleFilePreview").length) return t.hasClass("simpleFilePreview_existing") && t.parent().append(""), l(e, i, 1), t.closest(".simpleFilePreview_multi").width("-=" + t.width()), t.remove(), this; t.hasClass("simpleFilePreview_existing") && (t.find("input.simpleFilePreview_formInput").show(), t.append(""), t.removeClass("simpleFilePreview_existing")), l(e, i, 1); var n = t.find("input.simpleFilePreview_formInput").val(""); if (n && n.length && n.val().length) { for (var r = n.get(0).attributes, s = "", p = 0, o = r.length; o > p; ++p) "value" != r[p].name && "title" != r[p].name && (s += r[p].name + "='" + n.attr(r[p].name) + "' "); n.before(''), n.remove() } e.remove(), t.find(".simpleFilePreview_filename").remove(), t.find(".simpleFilePreview_remove").hide().end().find(".simpleFilePreview_input").show() }, l = function (e, i, t) { if (!i.limit) return !1; var l = e.closest(".simpleFilePreview_multi").find("> li"); t = t ? t : 0, l.length > i.limit + t ? l.last().hide() : l.last().show() }, n = function (e, t) { var l = e.is("[multiple]"); e = e.removeAttr("multiple").addClass("simpleFilePreview_formInput"), l || (t.radio = null); var n = i("<" + (l ? "li" : "div") + " id='simpleFilePreview_" + i.simpleFilePreview.uid++ + "' class='simpleFilePreview" + (t.radio ? " simpleFilePreview_withRadio" : "") + "' data-sfpallowmultiple='" + (l ? 1 : 0) + "'>" + t.buttonContent + "" + t.removeContent + "" + (t.radio ? "" : "") + (t.ajaxUpload.progressbar ? "
    " : "") + (t.contextMenu ? '' : "") + ""); e.before(n), n.append(e), t.readOnly && n.hide(), e.css({ width: n.width() + "px", height: n.height() - (t.radio ? 20 : 0) + "px" }), l ? (n.wrap("
      "), n.closest(".simpleFilePreview_multiUI").prepend("" + t.shiftRight + "").append("" + t.shiftLeft + "")) : n.wrap("
      "); var o = t.existingFiles; if (!o) return l && i(".simpleFilePreview_multi").width(n.outerWidth(!0) * n.parent().find(".simpleFilePreview").length), e; var a = new RegExp("^(" + i.simpleFilePreview.previewFileTypes + ")$"); if (l) { var v = i.isArray(o) ? 1 : 0; for (var m in o) { var d = i.simpleFilePreview.uid++, u = n.clone(!0).attr("id", "simpleFilePreview_" + d); t.contextMenu && u.find('[name^="' + t.contextMenu.inputName + '"]').attr("name", t.contextMenu.inputName + "[" + ++i.simpleFilePreview.linkid + "]").val(""), u.addClass("simpleFilePreview_existing").attr("data-sfprid", v ? o[m] : m).find("input.simpleFilePreview_formInput").remove(), u.show(), n.before(u); var c = p(o[m]); c = c ? c.toLowerCase() : null, c && a.test(c) ? r(u, o[m], "", t) : t.icons[c] ? r(u, t.icons[c], s(o[m]), t) : r(u, t.defaultIcon, s(o[m]), t), t.radio && u.find("input.simpleFilePreview_radio").val(u.attr("data-sfprid")) } return i(".simpleFilePreview_multi").width(n.outerWidth(!0) * n.parent().find(".simpleFilePreview").length), t.radio && n.closest(".simpleFilePreview_multi").find("input[type='radio'][value='" + t.radio.checkedItem + "']").prop("checked", !0), e } var w = null, v = i.isArray(o) ? 1 : 0; for (var m in o) w = { id: v ? o[m] : m, file: o[m] }; if (!w) return e; n.attr("data-sfprid", w.id).addClass("simpleFilePreview_existing").find("input.simpleFilePreview_formInput").hide(); var c = p(w.file); return c = c ? c.toLowerCase() : null, c && a.test(c) ? r(n, w.file, "", t) : t.icons[c] ? r(n, t.icons[c], s(w.file), t) : r(n, t.defaultIcon, s(w.file), t), e }, r = function (e, i, t, n) { t = t ? t : null, i = new RegExp("^(http|https)://").test(i) ? i : (new RegExp("[/\\\\]").test(i) ? "" : n.iconPath) + i, e.find(".simpleFilePreview_input").hide(); var r = e.find(".simpleFilePreview_preview"); if (r && r.length ? r.attr("src", i) : (e.append("" + (t ? t : "File Preview") + ""), e.find("input.simpleFilePreview_formInput").attr("title", n.removeMessage.prefix + " " + (t ? t : n.removeMessage.stub))), l(e, n), !t) return null; var s = e.find(".simpleFilePreview_filename"); s && s.length ? s.text(t) : e.append("" + t + "").find(".simpleFilePreview_filename") }, s = function (e) { var i = e.match(/[\/\\]([^\/\\]+)$/); return i && i[1] && i[1].length ? i[1] : null }, p = function (e) { var i = e.match(/[\.]([^\/\\\.]+)$/); return i && i[1] && i[1].length ? i[1] : null }, o = function (e, t) { window.scrollTo(0, 0), i("#" + t.contextMenu.id).dialog("open") }, a = function (t, l, n) { if (!t.readOnly) { var o = l.get()[0]; if (t.ajaxUpload) { var a = new FormData, v = o.name.indexOf("["), m = "file" == n ? o.files[0] : "link" == n ? l.val() : ""; v > -1 ? a.append(o.name.substr(0, v), m) : a.append(o.name, m), t.ajaxUpload.compose && t.ajaxUpload.compose(a), t.ajaxUpload.progressbar && l.parent().find(".simpleFilePreview_progress").show(), i.ajax({ url: t.ajaxUpload.url, type: "POST", data: a, dataType: "json", contentType: !1, processData: !1, success: function (e, i, n) { t.ajaxUpload.progressbar && l.parent().find(".simpleFilePreview_progress").hide(), t.ajaxUpload.success && t.ajaxUpload.success(e, i, n, o) }, error: function (e, i, n) { t.ajaxUpload.progressbar && l.parent().find(".simpleFilePreview_progress").hide(), t.ajaxUpload.error && t.ajaxUpload.error(e, i, n, o) }, xhr: function () { var e = new window.XMLHttpRequest; return e.upload.addEventListener("progress", function (e) { if (e.lengthComputable && t.ajaxUpload.progressbar) { var i = 100 * e.loaded / e.total, n = l.parent().find(".simpleFilePreview_progress div"); n.css({ width: i + "%" }).attr("aria-valuenow", i) } }, !1), e } }) } var d = l.closest(".simpleFilePreview"); if (1 == d.attr("data-sfpallowmultiple") && !d.find(".simpleFilePreview_preview").length) { var u = i.simpleFilePreview.uid++, c = d.clone(!0).attr("id", "simpleFilePreview_" + u); t.contextMenu && c.find('[name^="' + t.contextMenu.inputName + '"]').attr("name", t.contextMenu.inputName + "[" + ++i.simpleFilePreview.linkid + "]").val(""), t.ajaxUpload.progressbar && c.find(".simpleFilePreview_progress").hide(), c.find("input.simpleFilePreview_formInput").attr("id", c.find("input.simpleFilePreview_formInput").attr("id") + "_" + u).attr("name", function (e, i) { var t = d.find("input.simpleFilePreview_formInput").attr("name"), l = parseInt(t.substring(t.indexOf("[") + 1, t.indexOf("]"))); return isNaN(l) ? i : t.substring(0, t.indexOf("[") + 1) + ++l + t.substring(t.indexOf("]")) }).val(""), d.after(c); var w = d.closest(".simpleFilePreview_multi").width("+=" + c.outerWidth(!0)).width(); w > d.closest(".simpleFilePreview_multiClip").width() && d.closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_shiftRight").trigger("click") } var f = p(o.value); if (f = f ? f.toLowerCase() : null, "file" == n && o.files && o.files[0]) { var g = new RegExp("^image/(" + i.simpleFilePreview.previewFileTypes + ")$"); if (g.test(o.files[0].type.toLowerCase()) && window.FileReader) { var x = new FileReader; x.onload = function (e) { r(d, e.target.result, "", t) }, x.readAsDataURL(o.files[0]) } else { var _ = o.files[0].type.toLowerCase().match(/^\s*[^\/]+\/([a-zA-Z0-9\-\.]+)\s*$/); _ && _[1] && t.icons[_[1]] ? r(d, t.icons[_[1]], s(o.value), t) : r(d, t.defaultIcon, s(o.value), t) } return t.radio && d.find("input.simpleFilePreview_radio").val(d.context.files[0].name), o } if ("file" == n) { var g = new RegExp("^(" + i.simpleFilePreview.previewFileTypes + ")$"); f && !/fakepath/.test(o.value.toLowerCase()) && g.test(e) ? r(d, "file://" + o.value, "", t) : t.icons[f] ? r(d, t.icons[f], s(o.value), t) : r(d, t.defaultIcon, s(o.value), t) } if ("link" == n) { var g = new RegExp("^(" + i.simpleFilePreview.previewFileTypes + ")$"); g.test(f) ? r(d, l.val(), "", t) : r(d, o.value, s(o.value), t) } } }; i.simpleFilePreview = { defaults: { buttonContent: "Add File", removeContent: "X", existingFiles: null, shiftLeft: "<<", shiftRight: ">>", iconPath: "", defaultIcon: "preview_file.png", limit: 0, removeMessage: { prefix: "Remove", stub: "this file" }, radio: null, readOnly: !1, ajaxUpload: null, beforeRemove: null, removeDialog: null, contextMenu: null, parentSelector: null, icons: { png: "preview_png.png", gif: "preview_png.png", bmp: "preview_png.png", svg: "preview_png.png", jpg: "preview_png.png", jpeg: "preview_png.png", pjpg: "preview_png.png", pjpeg: "preview_png.png", tif: "preview_png.png", tiff: "preview_png.png", mp3: "preview_mp3.png", mp4: "preview_mp3.png", wav: "preview_mp3.png", wma: "preview_mp3.png", pdf: "preview_pdf.png", txt: "preview_txt.png", rtf: "preview_txt.png", text: "preview_txt.png", plain: "preview_txt.png", zip: "preview_zip.png", tgz: "preview_zip.png", "x-rar-compressed": "preview_zip.png", "octet-stream": "preview_zip.png", odf: "preview_doc.png", odt: "preview_doc.png", doc: "preview_doc.png", msword: "preview_doc.png", "vnd.openxmlformats-officedocument.wordprocessingml.document": "preview_doc.png", docx: "preview_doc.png", ods: "preview_xls.png", "vnd.ms-excel": "preview_xls.png", xls: "preview_xls.png", xlx: "preview_xls.png", msexcel: "preview_xls.png", "x-excel": "preview_xls.png", "x-ms-excel": "preview_xls.png", "vnd.openxmlformats-officedocument.spreadsheetml.sheet": "preview_xls.png" } }, uid: 0, linkid: 0, init: !1, previewFileTypes: "p?jpe?g|png|gif|bmp|svg" } }(jQuery), function (i) { "use strict"; i.fn.simpleFilePreview = function (e) { if (!this || !this.length) return this; if (e = e ? e : {}, e = i.extend(!0, {}, i.simpleFilePreview.defaults, e), e.readOnly && (e.radio = null), e.removeDialog && (e.removeDialog.id || (e.removeDialog.id = i(this).id + "_remove_dialog"), e.removeDialog.title || (e.removeDialog.title = "Remove"), e.removeDialog.text || (e.removeDialog.text = "Are you sure?"), e.removeDialog.ok || (e.removeDialog.ok = "Ok"), e.removeDialog.cancel || (e.removeDialog.cancel = "Cancel"), e.removeDialog.options || (e.removeDialog.options = {}), i('

      ' + e.removeDialog.text + "

      ").dialog(i.extend({ autoOpen: !1, resizable: !1, modal: !0 }, e.removeDialog.options))), e.contextMenu) { e.contextMenu.fileText || (e.contextMenu.fileText = "Open file"), e.contextMenu.linkText || (e.contextMenu.linkText = "Open link"), e.contextMenu.id || (e.contextMenu.id = i(this).id + "_openlink_dialog"), e.contextMenu.title || (e.contextMenu.title = "Open link"), e.contextMenu.text || (e.contextMenu.text = "Please enter link to file or image"), e.contextMenu.optionName || (e.contextMenu.optionName = "Link"), e.contextMenu.ok || (e.contextMenu.ok = "Ok"), e.contextMenu.cancel || (e.contextMenu.cancel = "Cancel"), e.contextMenu.inputName || (e.contextMenu.inputName = "input_openlink_dialog"), e.contextMenu.options || (e.contextMenu.options = {}); var l = i("body"), r = l.css("overflow"); i('

      ' + e.contextMenu.text + '

      ').dialog(i.extend({ autoOpen: !1, resizable: !1, modal: !0, position: { my: "center", at: "center", of: window }, open: function (e, i) { r = l.css("overflow"), l.css("overflow", "hidden") }, close: function (e, i) { l.css("overflow", r) }, buttons: [{ text: e.contextMenu.ok, click: function () { var t = i((e.parentSelector ? e.parentSelector : "body") + ' li:has(a.simpleFilePreview_input:visible) input[name^="' + e.contextMenu.inputName + '"]'), l = i("#" + e.contextMenu.id + "_link"); t.val(l.val()), v(e, t, "link"), l.val(""), i(this).dialog("close") } }, { text: e.contextMenu.cancel, click: function () { i(this).dialog("close") } }] }, e.contextMenu.options)); var s = (e.parentSelector ? e.parentSelector : "body") + " li:has(a.simpleFilePreview_input:visible)"; context.init({ preventDoubleContext: !1 }), context.settings({ compress: !0 }), context.attach(s, [{ text: e.contextMenu.fileText, action: function (i) { a(i, e, s) } }, { text: e.contextMenu.linkText, action: function (i) { o(i, e) } }]) } this.each(function () { n(i(this), e) }); var p = e.parentSelector ? i(e.parentSelector + " .simpleFilePreview_body") : i(this).closest(".simpleFilePreview_body"); return p.on("click", ".simpleFilePreview_input", function (i) { "link" == e.defaultOpen ? o(i, e) : a(i, e, i.currentTarget) }), p.on("click", ".simpleFilePreview input.simpleFilePreview_formInput", function (t) { return i(this).val().length ? (e.readOnly || i(this).closest(".simpleFilePreview").find(".simpleFilePreview_preview").trigger("click"), void t.preventDefault()) : this }), p.on("change", ".simpleFilePreview input.simpleFilePreview_formInput", function (t) { v(e, i(this), "file") }), p.on("mouseover", ".simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput", function () { if (!e.readOnly) { var t = i(this).closest(".simpleFilePreview"); t.find(".simpleFilePreview_preview").is(":visible") && t.find(".simpleFilePreview_remove").show() } }), p.on("mouseout", ".simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput", function () { i(this).closest(".simpleFilePreview").find(".simpleFilePreview_remove").hide() }), p.on("click", ".simpleFilePreview_preview", function () { if (!e.readOnly) { var l = i(this); if (e.removeDialog) { var n = i("#" + e.removeDialog.id); n.dialog("option", "buttons", [{ text: e.removeDialog.ok, click: function () { t(l, e), i(this).dialog("close") } }, { text: e.removeDialog.cancel, click: function () { i(this).dialog("close") } }]), n.dialog("open") } else t(l, e) } }), p.on("click", ".simpleFilePreview_shiftRight", function () { var e = i(this).closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_multi"), t = parseInt(e.css("left")) + e.width(); if (t > e.parent().width()) { var l = e.find("li:first"); e.animate({ left: "-=" + l.outerWidth(!0) }) } }), p.on("click", ".simpleFilePreview_shiftLeft", function () { var e = i(this).closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_multi"), t = parseInt(e.css("left")); if (0 > t) { var l = e.find("li:first").outerWidth(!0); e.animate({ left: 1 > t + l ? "+=" + l : 0 }) } }), this }; var t = function (e, i) { var t = e.closest(".simpleFilePreview"); if (null != i.beforeRemove && i.beforeRemove(t), 1 == t.attr("data-sfpallowmultiple") && t.siblings(".simpleFilePreview").length) return t.hasClass("simpleFilePreview_existing") && t.parent().append(""), l(e, i, 1), t.closest(".simpleFilePreview_multi").width("-=" + t.width()), t.remove(), this; t.hasClass("simpleFilePreview_existing") && (t.find("input.simpleFilePreview_formInput").show(), t.append(""), t.removeClass("simpleFilePreview_existing")), l(e, i, 1); var n = t.find("input.simpleFilePreview_formInput").val(""); if (n && n.length && n.val().length) { for (var r = n.get(0).attributes, s = "", p = 0, o = r.length; o > p; ++p) "value" != r[p].name && "title" != r[p].name && (s += r[p].name + "='" + n.attr(r[p].name) + "' "); n.before(''), n.remove() } e.remove(), t.find(".simpleFilePreview_filename").remove(), t.find(".simpleFilePreview_remove").hide().end().find(".simpleFilePreview_input").show() }, l = function (e, i, t) { if (!i.limit) return !1; var l = e.closest(".simpleFilePreview_multi").find("> li"); t = t ? t : 0, l.length > i.limit + t ? l.last().hide() : l.last().show() }, n = function (e, t) { var l = e.is("[multiple]"); e = e.removeAttr("multiple").addClass("simpleFilePreview_formInput"), l || (t.radio = null); var n = i("<" + (l ? "li" : "div") + " id='simpleFilePreview_" + i.simpleFilePreview.uid++ + "' class='simpleFilePreview" + (t.radio ? " simpleFilePreview_withRadio" : "") + "' data-sfpallowmultiple='" + (l ? 1 : 0) + "'>" + t.buttonContent + "" + t.removeContent + "" + (t.radio ? "" : "") + (t.ajaxUpload.progressbar ? "
      " : "") + (t.contextMenu ? '' : "") + ""); e.before(n), n.append(e), t.readOnly && n.hide(), l ? (n.wrap("
        "), n.closest(".simpleFilePreview_multiUI").prepend("" + t.shiftRight + "").append("" + t.shiftLeft + "")) : n.wrap("
        "); var o = t.existingFiles; if (!o) return l && i(".simpleFilePreview_multi").width(n.outerWidth(!0) * n.parent().find(".simpleFilePreview").length), e; var a = new RegExp("^(" + i.simpleFilePreview.previewFileTypes + ")$"); if (l) { var v = i.isArray(o) ? 1 : 0; for (var m in o) { var d = i.simpleFilePreview.uid++, u = n.clone(!0).attr("id", "simpleFilePreview_" + d); t.contextMenu && u.find('[name^="' + t.contextMenu.inputName + '"]').attr("name", t.contextMenu.inputName + "[" + ++i.simpleFilePreview.linkid + "]").val(""), u.addClass("simpleFilePreview_existing").attr("data-sfprid", v ? o[m] : m).find("input.simpleFilePreview_formInput").remove(), u.show(), n.before(u); var c = p(o[m]); c = c ? c.toLowerCase() : null, c && a.test(c) ? r(u, o[m], "", t) : t.icons[c] ? r(u, t.icons[c], s(o[m]), t) : r(u, t.defaultIcon, s(o[m]), t), t.radio && u.find("input.simpleFilePreview_radio").val(u.attr("data-sfprid")) } return i(".simpleFilePreview_multi").width(n.outerWidth(!0) * n.parent().find(".simpleFilePreview").length), t.radio && n.closest(".simpleFilePreview_multi").find("input[type='radio'][value='" + t.radio.checkedItem + "']").prop("checked", !0), e } var w = null, v = i.isArray(o) ? 1 : 0; for (var m in o) w = { id: v ? o[m] : m, file: o[m] }; if (!w) return e; n.attr("data-sfprid", w.id).addClass("simpleFilePreview_existing").find("input.simpleFilePreview_formInput").hide(); var c = p(w.file); return c = c ? c.toLowerCase() : null, c && a.test(c) ? r(n, w.file, "", t) : t.icons[c] ? r(n, t.icons[c], s(w.file), t) : r(n, t.defaultIcon, s(w.file), t), e }, r = function (e, i, t, n) { t = t ? t : null, i = new RegExp("^(http|https)://").test(i) ? i : (new RegExp("[/\\\\]").test(i) ? "" : n.iconPath) + i, e.find(".simpleFilePreview_input").hide(); var r = e.find(".simpleFilePreview_preview"); if (r && r.length ? r.attr("src", i) : (e.append("" + (t ? t : "File Preview") + ""), e.find("input.simpleFilePreview_formInput").attr("title", n.removeMessage.prefix + " " + (t ? t : n.removeMessage.stub))), l(e, n), !t) return null; var s = e.find(".simpleFilePreview_filename"); s && s.length ? s.text(t) : e.append("" + t + "").find(".simpleFilePreview_filename") }, s = function (e) { var i = e.match(/[\/\\]([^\/\\]+)$/); return i && i[1] && i[1].length ? i[1] : null }, p = function (e) { var i = e.match(/[\.]([^\/\\\.]+)$/); return i && i[1] && i[1].length ? i[1] : null }, o = function (e, t) { window.scrollTo(0, 0), i("#" + t.contextMenu.id).dialog("open") }, a = function (e, t, l) { i(l).closest(".simpleFilePreview").find("input.simpleFilePreview_formInput").trigger("click"), e.preventDefault() }, v = function (t, l, n) { if (!t.readOnly) { var o = l.get()[0]; if (t.ajaxUpload) { var a = new FormData, v = o.name.indexOf("["), m = "file" == n ? o.files[0] : "link" == n ? l.val() : ""; v > -1 ? a.append(o.name.substr(0, v), m) : a.append(o.name, m), t.ajaxUpload.compose && t.ajaxUpload.compose(a), t.ajaxUpload.progressbar && l.parent().find(".simpleFilePreview_progress").show(), i.ajax({ url: t.ajaxUpload.url, type: "POST", data: a, dataType: "json", contentType: !1, processData: !1, success: function (e, i, n) { t.ajaxUpload.progressbar && l.parent().find(".simpleFilePreview_progress").hide(), t.ajaxUpload.success && t.ajaxUpload.success(e, i, n, o) }, error: function (e, i, n) { t.ajaxUpload.progressbar && l.parent().find(".simpleFilePreview_progress").hide(), t.ajaxUpload.error && t.ajaxUpload.error(e, i, n, o) }, xhr: function () { var e = new window.XMLHttpRequest; return e.upload.addEventListener("progress", function (e) { if (e.lengthComputable && t.ajaxUpload.progressbar) { var i = 100 * e.loaded / e.total, n = l.parent().find(".simpleFilePreview_progress div"); n.css({ width: i + "%" }).attr("aria-valuenow", i) } }, !1), e } }) } var d = l.closest(".simpleFilePreview"); if (1 == d.attr("data-sfpallowmultiple") && !d.find(".simpleFilePreview_preview").length) { var u = i.simpleFilePreview.uid++, c = d.clone(!0).attr("id", "simpleFilePreview_" + u); t.contextMenu && c.find('[name^="' + t.contextMenu.inputName + '"]').attr("name", t.contextMenu.inputName + "[" + ++i.simpleFilePreview.linkid + "]").val(""), t.ajaxUpload.progressbar && c.find(".simpleFilePreview_progress").hide(), c.find("input.simpleFilePreview_formInput").attr("id", c.find("input.simpleFilePreview_formInput").attr("id") + "_" + u).attr("name", function (e, i) { var t = d.find("input.simpleFilePreview_formInput").attr("name"), l = parseInt(t.substring(t.indexOf("[") + 1, t.indexOf("]"))); return isNaN(l) ? i : t.substring(0, t.indexOf("[") + 1) + ++l + t.substring(t.indexOf("]")) }).val(""), d.after(c); var w = d.closest(".simpleFilePreview_multi").width("+=" + c.outerWidth(!0)).width(); w > d.closest(".simpleFilePreview_multiClip").width() && d.closest(".simpleFilePreview_multiUI").find(".simpleFilePreview_shiftRight").trigger("click") } var f = p(o.value); if (f = f ? f.toLowerCase() : null, "file" == n && o.files && o.files[0]) { var g = new RegExp("^image/(" + i.simpleFilePreview.previewFileTypes + ")$"); if (g.test(o.files[0].type.toLowerCase()) && window.FileReader) { var x = new FileReader; x.onload = function (e) { r(d, e.target.result, "", t) }, x.readAsDataURL(o.files[0]) } else { var _ = o.files[0].type.toLowerCase().match(/^\s*[^\/]+\/([a-zA-Z0-9\-\.]+)\s*$/); _ && _[1] && t.icons[_[1]] ? r(d, t.icons[_[1]], s(o.value), t) : r(d, t.defaultIcon, s(o.value), t) } return t.radio && d.find("input.simpleFilePreview_radio").val(d.context.files[0].name), o } if ("file" == n) { var g = new RegExp("^(" + i.simpleFilePreview.previewFileTypes + ")$"); f && !/fakepath/.test(o.value.toLowerCase()) && g.test(e) ? r(d, "file://" + o.value, "", t) : t.icons[f] ? r(d, t.icons[f], s(o.value), t) : r(d, t.defaultIcon, s(o.value), t) } if ("link" == n) { var g = new RegExp("^(" + i.simpleFilePreview.previewFileTypes + ")$"); g.test(f) ? r(d, l.val(), "", t) : r(d, o.value, s(o.value), t) } } }; i.simpleFilePreview = { defaults: { buttonContent: "Add File", removeContent: "X", existingFiles: null, shiftLeft: "<<", shiftRight: ">>", iconPath: "", defaultIcon: "preview_file.png", limit: 0, removeMessage: { prefix: "Remove", stub: "this file" }, radio: null, readOnly: !1, ajaxUpload: null, beforeRemove: null, removeDialog: null, contextMenu: null, parentSelector: null, defaultOpen: "file", icons: { png: "preview_png.png", gif: "preview_png.png", bmp: "preview_png.png", svg: "preview_png.png", jpg: "preview_png.png", jpeg: "preview_png.png", pjpg: "preview_png.png", pjpeg: "preview_png.png", tif: "preview_png.png", tiff: "preview_png.png", mp3: "preview_mp3.png", mp4: "preview_mp3.png", wav: "preview_mp3.png", wma: "preview_mp3.png", pdf: "preview_pdf.png", txt: "preview_txt.png", rtf: "preview_txt.png", text: "preview_txt.png", plain: "preview_txt.png", zip: "preview_zip.png", tgz: "preview_zip.png", "x-rar-compressed": "preview_zip.png", "octet-stream": "preview_zip.png", odf: "preview_doc.png", odt: "preview_doc.png", doc: "preview_doc.png", msword: "preview_doc.png", "vnd.openxmlformats-officedocument.wordprocessingml.document": "preview_doc.png", docx: "preview_doc.png", ods: "preview_xls.png", "vnd.ms-excel": "preview_xls.png", xls: "preview_xls.png", xlx: "preview_xls.png", msexcel: "preview_xls.png", "x-excel": "preview_xls.png", "x-ms-excel": "preview_xls.png", "vnd.openxmlformats-officedocument.spreadsheetml.sheet": "preview_xls.png" } }, uid: 0, linkid: 0, init: !1, previewFileTypes: "p?jpe?g|png|gif|bmp|svg" } }(jQuery); \ No newline at end of file diff --git a/package.json b/package.json index 599fd13..e5da70f 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "form", "file upload" ], - "author": "Jordan Kasper", + "author": "Jordan Kasper, eusonlito, Alexei Ivashkevich", "license": "MIT", "bugs": { "url": "https://github.com/jakerella/jquerySimpleFilePreview/issues" diff --git a/simpleFilePreview.css b/simpleFilePreview.css index 3a5b4c9..118ec61 100644 --- a/simpleFilePreview.css +++ b/simpleFilePreview.css @@ -13,6 +13,7 @@ padding: 0; position: relative; left: 0; + list-style-type: none; } .simpleFilePreview_shifter { @@ -44,7 +45,6 @@ background-color: #f7f7f7; text-align: center; cursor: pointer; - overflow: hidden; box-shadow: 0 0 4px 0 #555; } @@ -65,7 +65,7 @@ background-color: #ddd; } -.simpleFilePreview input { +.simpleFilePreview input[type="file"] { position: absolute; top: 0; right: 0; @@ -105,3 +105,27 @@ right: 5px; z-index: 4; } + +.simpleFilePreview_withRadio { + height: 140px; +} + +.simpleFilePreview_radio { + position: absolute; + top: 110px; + right: 48px; + z-index: 4; + display: none; +} + +.simpleFilePreview_input[style="display: none;"] ~ .simpleFilePreview_radio{ + display: inherit; +} + +.simpleFilePreview_progress { + z-index: 10; + position: absolute; + width: 100%; + top: 60px; + display: none; +} \ No newline at end of file diff --git a/simpleFilePreview.min.css b/simpleFilePreview.min.css index 83064fa..655faf5 100644 --- a/simpleFilePreview.min.css +++ b/simpleFilePreview.min.css @@ -1 +1 @@ -.simpleFilePreview_multiUI{padding:0 30px;position:relative}.simpleFilePreview_multiClip{overflow:hidden}.simpleFilePreview_multi{display:block;height:120px;padding:0;position:relative;left:0}.simpleFilePreview_shifter{position:absolute;top:62px;cursor:pointer}.simpleFilePreview_shiftLeft{left:3px}.simpleFilePreview_shiftRight{right:3px}.imageHolder{margin:10px 15px}.simpleFilePreview{position:relative;display:block;width:120px;height:120px;margin-left:10px;border:4px solid #fff;border-radius:3px;background-color:#f7f7f7;text-align:center;cursor:pointer;overflow:hidden;box-shadow:0 0 4px 0 #555}.simpleFilePreview_multi .simpleFilePreview{float:left}.simpleFilePreview_input{position:relative;overflow:hidden;display:inline-block;padding-top:40%;height:100%;width:100%}.simpleFilePreview:hover{background-color:#ddd}.simpleFilePreview input{position:absolute;top:0;right:0;opacity:0;-moz-opacity:0;filter:alpha(opacity=0);cursor:pointer;z-index:5}.simpleFilePreview_preview{max-width:112px;max-height:112px;z-index:3}.simpleFilePreview_preview.simpleFilePreview_hasFilename{max-width:120px;max-height:100px}.simpleFilePreview_filename{font-size:.8em;color:#666;width:95%;height:1.15em;overflow:hidden;display:inline-block}.simpleFilePreview_remove{display:none;color:#c33;font-weight:700;position:absolute;top:5px;right:5px;z-index:4} \ No newline at end of file +.simpleFilePreview_multiUI{padding:0 30px;position:relative}.simpleFilePreview_multiClip{overflow:hidden}.simpleFilePreview_multi{display:block;height:120px;padding:0;position:relative;left:0;list-style-type:none}.simpleFilePreview_shifter{position:absolute;top:62px;cursor:pointer}.simpleFilePreview_shiftLeft{left:3px}.simpleFilePreview_shiftRight{right:3px}.imageHolder{margin:10px 15px}.simpleFilePreview{position:relative;display:block;width:120px;height:120px;margin-left:10px;border:4px solid #fff;border-radius:3px;background-color:#f7f7f7;text-align:center;cursor:pointer;box-shadow:0 0 4px 0 #555}.simpleFilePreview_multi .simpleFilePreview{float:left}.simpleFilePreview_input{position:relative;overflow:hidden;display:inline-block;padding-top:40%;height:100%;width:100%}.simpleFilePreview:hover{background-color:#ddd}.simpleFilePreview input[type=file]{position:absolute;top:0;right:0;opacity:0;-moz-opacity:0;filter:alpha(opacity=0);cursor:pointer;z-index:5}.simpleFilePreview_preview{max-width:112px;max-height:112px;z-index:3}.simpleFilePreview_preview.simpleFilePreview_hasFilename{max-width:120px;max-height:100px}.simpleFilePreview_filename{font-size:.8em;color:#666;width:95%;height:1.15em;overflow:hidden;display:inline-block}.simpleFilePreview_remove{display:none;color:#c33;font-weight:700;position:absolute;top:5px;right:5px;z-index:4}.simpleFilePreview_withRadio{height:140px}.simpleFilePreview_radio{position:absolute;top:110px;right:48px;z-index:4;display:none}.simpleFilePreview_input[style="display: none;"]~.simpleFilePreview_radio{display:inherit}.simpleFilePreview_progress{z-index:10;position:absolute;width:100%;top:60px;display:none} \ No newline at end of file