From 2fefb2bfc7e42b712badb6280e76a58380b6fb0d Mon Sep 17 00:00:00 2001
From: Lito
Date: Fri, 10 Apr 2015 14:22:47 +0200
Subject: [PATCH 1/5] Improved code style
---
jquery.simpleFilePreview.js | 804 +++++++++++++++++++-----------------
1 file changed, 429 insertions(+), 375 deletions(-)
diff --git a/jquery.simpleFilePreview.js b/jquery.simpleFilePreview.js
index b7a3b60..a92d8a9 100644
--- a/jquery.simpleFilePreview.js
+++ b/jquery.simpleFilePreview.js
@@ -1,412 +1,466 @@
/* Copyright (c) 2012 Jordan Kasper
- * 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+
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Fore more usage documentation and examples, visit:
- * http://jordankasper.com/jquery
- *
- * Basic usage (shown with defaults, except for "existingFiles"):
- *
-
-
- var files = {"file_id": "file_name", ...};
- $('input[type=file]').simpleFilePreview({
- 'buttonContent': 'Add File', // String HTML content for the button to add a new file
- 'removeContent': 'X', // String HTML content for the removal icon shown on hover when a file is selected (or for existing files)
- 'existingFiles': files, // array | object If an object, key is used in the remove hidden input (defaults to null)
- 'shiftLeft': '<<', // String HTML content for the button to shift left for multiple file inputs
- 'shiftRight': '>>', // String HTML content for the button to shift right for multiple file inputs
- '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)
- });
- *
- * TODO:
- * - add events for binding to various actions
- * - add example of html produced
- *
- * REVISIONS:
- * 0.1 Initial release
- *
- */
+* 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+
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+* Fore more usage documentation and examples, visit:
+* http://jordankasper.com/jquery
+*
+* Basic usage (shown with defaults, except for "existingFiles"):
+*
+
+
+var files = {"file_id": "file_name", ...};
+
+$('input[type=file]').simpleFilePreview({
+ 'buttonContent': 'Add File', // String HTML content for the button to add a new file
+ 'removeContent': 'X', // String HTML content for the removal icon shown on hover when a file is selected (or for existing files)
+ 'existingFiles': files, // array | object If an object, key is used in the remove hidden input (defaults to null)
+ 'shiftLeft': '<<', // String HTML content for the button to shift left for multiple file inputs
+ 'shiftRight': '>>', // String HTML content for the button to shift right for multiple file inputs
+ '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)
+});
+*
+* TODO:
+* - add events for binding to various actions
+* - add example of html produced
+*
+* REVISIONS:
+* 0.1 Initial release
+*
+*/
;(function($) {
-
- $.fn.simpleFilePreview = function(o) {
- var n = this;
- if (!n || !n.length) { return n; }
-
- // Set up options (and defaults)
- o = (o)?o:{};
- o = $.extend({}, $.simpleFilePreview.defaults, o);
-
- n.each(function() {
- setup($(this), o);
- });
-
- // set up global events
- if (!$.simpleFilePreview.init) {
- $.simpleFilePreview.init = true;
- $('body')
-
+ 'use strict';
+
+ $.fn.simpleFilePreview = function(options) {
+ var these = this;
+
+ if (!these || !these.length) {
+ return these;
+ }
+
+ // Set up options (and defaults)
+ options = options ? options : {};
+ options = $.extend({}, $.simpleFilePreview.defaults, options);
+
+ these.each(function() {
+ setup($(this), options);
+ });
+
+ // set up global events
+ if ($.simpleFilePreview.init) {
+ return these;
+ }
+
+ var $body = $('body');
+
+ $.simpleFilePreview.init = true;
+
// open file browser dialog on click of styled "button"
- .on('click', '.simpleFilePreview_input', function(e) {
- $(this).parents('.simpleFilePreview').find('input.simpleFilePreview_formInput').trigger('click');
- e.preventDefault();
- return false;
- })
-
+ $body.on('click', '.simpleFilePreview_input', function(e) {
+ $(this).parents('.simpleFilePreview').find('input.simpleFilePreview_formInput').trigger('click');
+ e.preventDefault();
+ });
+
// 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)
- .on('click', '.simpleFilePreview input.simpleFilePreview_formInput', function(e) {
- if ($(this).val().length) {
+ $body.on('click', '.simpleFilePreview input.simpleFilePreview_formInput', function(e) {
+ if (!$(this).val().length) {
+ return this;
+ }
+
+ $(this).parents('.simpleFilePreview').find('.simpleFilePreview_preview').trigger('click');
+
e.preventDefault();
- $(this).parents('.simpleFilePreview').find('.simpleFilePreview_preview').click();
- return false;
- }
- })
-
+ });
+
// when file input changes, get file contents and show preview (if it's an image)
- .on('change', '.simpleFilePreview input.simpleFilePreview_formInput', function(e) {
- var p = $(this).parents('.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 (p.attr('data-sfpallowmultiple') == 1 && !p.find('.simpleFilePreview_preview').length) {
- var newId = $.simpleFilePreview.uid++;
- var newN = p.clone(true).attr('id', "simpleFilePreview_"+newId);
- newN.find('input.simpleFilePreview_formInput').attr('id', newN.find('input.simpleFilePreview_formInput').attr('id')+'_'+newId).val('');
- p.after(newN);
- var nw = p.parents('.simpleFilePreview_multi').width('+='+newN.outerWidth(true)).width();
- if (nw > p.parents('.simpleFilePreview_multiClip').width()) {
- p.parents('.simpleFilePreview_multiUI')
- .find('.simpleFilePreview_shiftRight')
- .click();
+ $body.on('change', '.simpleFilePreview input.simpleFilePreview_formInput', function(e) {
+ var $parents = $(this).parents('.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.parents('.simpleFilePreview_multi').width('+=' + $newN.outerWidth(true)).width();
+
+ if (nw > $parents.parents('.simpleFilePreview_multiClip').width()) {
+ $parents.parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_shiftRight').trigger('click');
+ }
}
- }
-
- if (this.files && this.files[0]) {
- if ((new RegExp("^image\/("+$.simpleFilePreview.previewFileTypes+")$")).test(this.files[0].type.toLowerCase())) {
-
- if (window.FileReader) {
- if ((new RegExp("^image\/("+$.simpleFilePreview.previewFileTypes+")$")).test(this.files[0].type.toLowerCase())) {
- // show preview of image file
- var r = new FileReader();
- r.onload = function (e) {
- addOrChangePreview(p, e.target.result);
- };
- r.readAsDataURL(this.files[0]);
-
+
+ if (this.files && this.files[0]) {
+ var exp = "^image\/(" + $.simpleFilePreview.previewFileTypes + ")$";
+
+ if ((new RegExp(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);
+ };
+
+ $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.iconPath + options.icons[m[1]], getFilename(this.value));
+ } else {
+ addOrChangePreview($parents, options.iconPath + options.defaultIcon, getFilename(this.value));
+ }
}
- }
-
- } 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] && o.icons[m[1]]) {
- addOrChangePreview(p, o.iconPath+o.icons[m[1]], getFilename(this.value));
- } else {
- addOrChangePreview(p, o.iconPath+o.defaultIcon, getFilename(this.value));
- }
+
+ return this;
}
-
- } else {
+
// 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 e = getFileExt(this.value);
- e = (e)?e.toLowerCase():null;
- if (e && !(/fakepath/.test(this.value.toLowerCase())) && (new RegExp("^("+$.simpleFilePreview.previewFileTypes+")$")).test(e)) {
- // older versions of IE (and some other browsers) report the local
- // file path, so try to get a preview that way
- addOrChangePreview(p, "file://"+this.value);
-
+
+ var exp = "^(" + $.simpleFilePreview.previewFileTypes + ")$";
+
+ var ext = getFileExt(this.value);
+ ext = ext ? ext.toLowerCase() : null;
+
+ if (ext && !(/fakepath/.test(this.value.toLowerCase())) && (new RegExp(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);
} else {
- // not an image (or using fakepath), so no preview anyway
- if (o.icons[e]) {
- addOrChangePreview(p, o.iconPath+o.icons[e], getFilename(this.value));
- } else {
- addOrChangePreview(p, o.iconPath+o.defaultIcon, getFilename(this.value));
- }
+ // not an image (or using fakepath), so no preview anyway
+ if (options.icons[ext]) {
+ addOrChangePreview($parents, options.iconPath + options.icons[ext], getFilename(this.value));
+ } else {
+ addOrChangePreview($parents, options.iconPath + options.defaultIcon, getFilename(this.value));
+ }
}
- }
- })
-
+ });
+
// show or hide "remove" icon for file preview/icon
- .on('mouseover', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() {
- var p = $(this).parents('.simpleFilePreview');
- if (p.find('.simpleFilePreview_preview').is(':visible')) {
- p.find('.simpleFilePreview_remove').show();
- }
- })
- .on('mouseout', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() {
- $(this).parents('.simpleFilePreview').find('.simpleFilePreview_remove').hide();
+ $body.on('mouseover', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() {
+ var $parents = $(this).parents('.simpleFilePreview');
+
+ if ($parents.find('.simpleFilePreview_preview').is(':visible')) {
+ $parents.find('.simpleFilePreview_remove').show();
+ }
+ });
+
+ $body.on('mouseout', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() {
+ $(this).parents('.simpleFilePreview').find('.simpleFilePreview_remove').hide();
})
-
+
// remove file when preview/icon is clicked
- .on('click', '.simpleFilePreview_preview', function() {
- var p = $(this).parents('.simpleFilePreview');
-
- if (p.attr('data-sfpallowmultiple') == 1 && p.siblings('.simpleFilePreview').length) {
- if (p.hasClass('simpleFilePreview_existing')) {
- p.parent().append("");
+ $body.on('click', '.simpleFilePreview_preview', function() {
+ var $parents = $(this).parents('.simpleFilePreview');
+
+ if ($parents.attr('data-sfpallowmultiple') == 1 && $parents.siblings('.simpleFilePreview').length) {
+ if ($parents.hasClass('simpleFilePreview_existing')) {
+ $parents.parent().append("");
+ }
+
+ $parents.parents('.simpleFilePreview_multi').width('-=' + $parents.width());
+ $parents.remove();
+
+ return this;
}
-
- p.parents('.simpleFilePreview_multi').width('-='+p.width());
- p.remove();
-
- } else {
+
// if it was an existing file, show file input and add "removeFiles" hidden input
- if (p.hasClass('simpleFilePreview_existing')) {
- p.find('input.simpleFilePreview_formInput').show();
- p.append("");
- p.removeClass('simpleFilePreview_existing'); // no longer needed
+ if ($parents.hasClass('simpleFilePreview_existing')) {
+ $parents.find('input.simpleFilePreview_formInput').show();
+ $parents.append("");
+ $parents.removeClass('simpleFilePreview_existing'); // no longer needed
}
-
+
// kill value in the input
- var i = p.find('input.simpleFilePreview_formInput').val('');
-
+ 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 (i && i.length && i.val().length) {
- var attr = i.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)+"' ";
+ }
}
- }
- var ni = $("");
- i.before(ni);
- i.remove();
+
+ $input.before('');
+ $input.remove();
}
-
+
// remove the preview element
$(this).remove();
- p.find('.simpleFilePreview_filename').remove();
+ $parents.find('.simpleFilePreview_filename').remove();
+
// show styled input "button"
- p.find('.simpleFilePreview_remove').hide().end()
- .find('.simpleFilePreview_input').show();
- }
- })
-
+ $parents.find('.simpleFilePreview_remove').hide().end()
+ .find('.simpleFilePreview_input').show();
+ });
+
// shift buttons for multi-selects
- .on('click', '.simpleFilePreview_shiftRight', function() {
- var ul = $(this).parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
- var r = parseInt(ul.css('left')) + ul.width();
- if (r > ul.parent().width()) {
- var li = ul.find('li:first');
- ul.animate({'left': '-='+li.outerWidth(true)});
- }
- })
- .on('click', '.simpleFilePreview_shiftLeft', function() {
- var ul = $(this).parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
- var l = parseInt(ul.css('left'));
- if (l < 0) {
- var w = ul.find('li:first').outerWidth(true);
- ul.animate({'left': ((l+w)<1)?'+='+w:0});
- }
+ $body.on('click', '.simpleFilePreview_shiftRight', function() {
+ var ul = $(this).parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
+ var width = parseInt(ul.css('left')) + ul.width();
+
+ if (width > ul.parent().width()) {
+ var li = ul.find('li:first');
+ ul.animate({
+ 'left': '-=' + li.outerWidth(true)
+ });
+ }
});
- }
-
- // return node for fluid chain calling
- return n;
- };
-
- var setup = function(n, o) {
- var isMulti = n.is('[multiple]');
- // "multiple" removed because it's handled later manually
- n = n.removeAttr('multiple').addClass('simpleFilePreview_formInput');
-
- // wrap input with necessary structure
- var c = $("<"+((isMulti)?'li':'div')+" id='simpleFilePreview_"+($.simpleFilePreview.uid++)+"' class='simpleFilePreview' data-sfpallowmultiple='"+((isMulti)?1:0)+"'>" +
- ""+o.buttonContent+"" +
- ""+o.removeContent+""+
- ""+((isMulti)?'li':'div')+">");
- n.before(c);
- c.append(n);
- // 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
- n.css({
- width: c.width()+'px',
- height: c.height()+'px'
- });
-
- // if it's a multi-select we use multiple separate inputs instead to support file preview
- if (isMulti) {
- c.wrap("
");
- c.parents('.simpleFilePreview_multiUI')
- .prepend(""+o.shiftRight+"")
- .append(""+o.shiftLeft+"");
- }
-
- var ex = o.existingFiles;
- if (ex) {
- if (isMulti) {
- // add all of the existing files to preview block
- var arr = ($.isArray(ex))?1:0;
- for (var i in ex) {
- var ni = $.simpleFilePreview.uid++;
- var nn = c.clone(true).attr('id', "simpleFilePreview_"+ni);
- nn.addClass('simpleFilePreview_existing')
- .attr('data-sfprid', (arr)?ex[i]:i)
- .find('input.simpleFilePreview_formInput').remove();
- c.before(nn);
-
- var e = getFileExt(ex[i]);
- e = (e)?e.toLowerCase():null;
- if (e && (new RegExp("^("+$.simpleFilePreview.previewFileTypes+")$")).test(e)) {
- addOrChangePreview(nn, ex[i]);
- } else if (o.icons[e]) {
- addOrChangePreview(nn, o.iconPath+o.icons[e], getFilename(ex[i]));
- } else {
- addOrChangePreview(nn, o.iconPath+o.defaultIcon, getFilename(ex[i]));
- }
+
+ $body.on('click', '.simpleFilePreview_shiftLeft', function() {
+ var ul = $(this).parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
+ var left = parseInt(ul.css('left'));
+
+ if (left < 0) {
+ var width = ul.find('li:first').outerWidth(true);
+ ul.animate({
+ 'left': (((left + width) < 1) ? ('+=' + width) : 0)
+ });
+ }
+ });
+
+ // return node for fluid chain calling
+ return these;
+ };
+
+ 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');
+
+ // wrap input with necessary structure
+ var $html = $("<" + (isMulti ? 'li' : 'div')
+ + " id='simpleFilePreview_" + ($.simpleFilePreview.uid++) + "'"
+ + " class='simpleFilePreview' data-sfpallowmultiple='" + (isMulti ? 1 : 0) + "'>"
+ + ""
+ + options.buttonContent + ""
+ + "" + options.removeContent + ""
+ + "" + (isMulti ? 'li' : 'div') + ">");
+
+ 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 it's a multi-select we use multiple separate inputs instead to support file preview
+ if (isMulti) {
+ $html.wrap("
");
+ $html.parents('.simpleFilePreview_multiUI')
+ .prepend("" + options.shiftRight + "")
+ .append("" + options.shiftLeft + "");
+ }
+
+ var exp = "^(" + $.simpleFilePreview.previewFileTypes + ")$";
+ var exists = options.existingFiles;
+
+ if (exists) {
+ if (isMulti) {
+ // add all of the existing files to preview block
+ var arr = ($.isArray(exists)) ? 1 : 0;
+
+ for (var i in exists) {
+ var ni = $.simpleFilePreview.uid++;
+ var nn = $html.clone(true).attr('id', "simpleFilePreview_" + ni);
+
+ nn.addClass('simpleFilePreview_existing')
+ .attr('data-sfprid', arr ? exists[i] : i)
+ .find('input.simpleFilePreview_formInput').remove();
+
+ $html.before(nn);
+
+ var ext = getFileExt(exists[i]);
+ ext = ext ? ext.toLowerCase() : null;
+
+ if (ext && (new RegExp(exp)).test(ext)) {
+ addOrChangePreview(nn, exists[i]);
+ } else if (options.icons[ext]) {
+ addOrChangePreview(nn, options.iconPath+options.icons[ext], getFilename(exists[i]));
+ } else {
+ addOrChangePreview(nn, options.iconPath+options.defaultIcon, getFilename(exists[i]));
+ }
+ }
+ } else {
+ // for single inputs we only take the last file
+ var $file = null;
+ var arr = $.isArray(exists) ? 1 : 0;
+
+ for (var i in exists) {
+ $file = {
+ id: (arr ? exists[i] : i),
+ file: exists[i]
+ };
+ }
+
+ if ($file) {
+ // hide file input, will be shown if existing file is removed
+ $html.attr('data-sfprid', $file['id'])
+ .addClass('simpleFilePreview_existing')
+ .find('input.simpleFilePreview_formInput').hide();
+
+ var ext = getFileExt($file['file']);
+ ext = ext ? ext.toLowerCase() : null;
+
+ if (ext && (new RegExp(exp)).test(ext)) {
+ addOrChangePreview($html, $file['file']);
+ } else if (options.icons[ext]) {
+ addOrChangePreview($html, options.iconPath+options.icons[ext], getFilename($file['file']));
+ } else {
+ addOrChangePreview($html, options.iconPath+options.defaultIcon, getFilename($file['file']));
+ }
+ }
+ }
+ }
+
+ if (isMulti) {
+ $('.simpleFilePreview_multi').width($html.outerWidth(true) * $html.parent().find('.simpleFilePreview').length);
}
-
- } else {
- // for single inputs we only take the last file
- var f = null;
- var arr = ($.isArray(ex))?1:0;
- for (var i in ex) {
- f = {id: (arr)?ex[i]:i, file: ex[i]};
+ };
+
+ var addOrChangePreview = function($parents, src, filename) {
+ filename = filename ? filename : null;
+
+ $parents.find('.simpleFilePreview_input').hide();
+
+ var $image = $parents.find('.simpleFilePreview_preview');
+
+ if ($image && $image.length) {
+ $image.attr('src', src);
+ } else {
+ $parents.append("");
+
+ // for tooltips
+ $parents.find('input.simpleFilePreview_formInput').attr('title', "Remove " + (filename ? filename : 'this file'));
}
- if (f) {
- // hide file input, will be shown if existing file is removed
- c.attr('data-sfprid', f['id'])
- .addClass('simpleFilePreview_existing')
- .find('input.simpleFilePreview_formInput').hide();
-
- var e = getFileExt(f['file']);
- e = (e)?e.toLowerCase():null;
- if (e && (new RegExp("^("+$.simpleFilePreview.previewFileTypes+")$")).test(e)) {
- addOrChangePreview(c, f['file']);
- } else if (o.icons[e]) {
- addOrChangePreview(c, o.iconPath+o.icons[e], getFilename(f['file']));
- } else {
- addOrChangePreview(c, o.iconPath+o.defaultIcon, getFilename(f['file']));
- }
+
+ if (!filename) {
+ return null;
}
- }
- }
-
- if (isMulti) {
- $('.simpleFilePreview_multi').width(c.outerWidth(true) * c.parent().find('.simpleFilePreview').length);
- }
-
- };
-
- var addOrChangePreview = function(p, src, fn) {
- fn = (fn)?(""+fn):null;
-
- p.find('.simpleFilePreview_input').hide();
- var i = p.find('.simpleFilePreview_preview');
- if (i && i.length) {
- i.attr('src', src);
- } else {
- p.append("");
- // for tooltips
- p.find('input.simpleFilePreview_formInput').attr('title', "Remove "+((fn)?fn:'this file'));
- }
-
- if (fn) {
- var f = p.find('.simpleFilePreview_filename');
- if (f && f.length) {
- f.text(fn);
- } else {
- f = p.append(""+fn+"")
- .find('.simpleFilePreview_filename');
- }
- }
- };
-
- var getFilename = function(p) {
- var m = p.match(/[\/\\]([^\/\\]+)$/);
- if (m && m[1] && m[1].length) {
- return m[1];
- }
- return null;
- };
-
- var getFileExt = function(p) {
- var m = p.match(/[\.]([^\/\\\.]+)$/);
- if (m && m[1] && m[1].length) {
- return m[1];
- }
- return null;
- };
-
- // Static properties
- $.simpleFilePreview = {
- defaults: {
- 'buttonContent': 'Add File',
- 'removeContent': 'X',
- 'existingFiles': null, // array or object. if object, key is used in the remove hidden input
- 'shiftLeft': '<<',
- 'shiftRight': '>>',
- 'iconPath': '',
- 'defaultIcon': 'preview_file.png',
- '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',
- 'doc': '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: false,
- previewFileTypes: 'p?jpe?g|png|gif|bmp|svg'
- };
-
+
+ var $filename = $parents.find('.simpleFilePreview_filename');
+
+ if ($filename && $filename.length) {
+ $filename.text(filename);
+ } else {
+ $parents.append("" + filename + "")
+ .find('.simpleFilePreview_filename');
+ }
+ };
+
+ var getFilename = function($parents) {
+ var m = $parents.match(/[\/\\]([^\/\\]+)$/);
+
+ if (m && m[1] && m[1].length) {
+ return m[1];
+ }
+
+ return null;
+ };
+
+ var getFileExt = function($parents) {
+ var m = $parents.match(/[\.]([^\/\\\.]+)$/);
+
+ if (m && m[1] && m[1].length) {
+ return m[1];
+ }
+
+ return null;
+ };
+
+ // Static properties
+ $.simpleFilePreview = {
+ defaults: {
+ 'buttonContent': 'Add File',
+ 'removeContent': 'X',
+ 'existingFiles': null, // array or object. if object, key is used in the remove hidden input
+ 'shiftLeft': '<<',
+ 'shiftRight': '>>',
+ 'iconPath': '',
+ 'defaultIcon': 'preview_file.png',
+ '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',
+ 'doc': '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: false,
+ previewFileTypes: 'p?jpe?g|png|gif|bmp|svg'
+ };
})(jQuery);
From dad0d9891e9c81664ec40151e62ccd3d60eb79b8 Mon Sep 17 00:00:00 2001
From: Lito
Date: Fri, 10 Apr 2015 16:11:00 +0200
Subject: [PATCH 2/5] Added limit option
---
README.md | 1 +
jquery.simpleFilePreview.js | 197 +++++++++++++++++++++---------------
simpleFilePreview.css | 150 ++++++++++++++-------------
3 files changed, 198 insertions(+), 150 deletions(-)
diff --git a/README.md b/README.md
index 1f7fc9b..4bc1ea9 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,7 @@ simple and the UI allows for easy CSS styling.
file (used in combination with the "iconPath" option)
(default value includes most common file types in this format:
{'png': 'preview_png.png', ...}
+'limit': INTEGER On multiple files, set a limit
```
### Basic Usage
diff --git a/jquery.simpleFilePreview.js b/jquery.simpleFilePreview.js
index a92d8a9..3000d3e 100644
--- a/jquery.simpleFilePreview.js
+++ b/jquery.simpleFilePreview.js
@@ -72,7 +72,7 @@ $('input[type=file]').simpleFilePreview({
// open file browser dialog on click of styled "button"
$body.on('click', '.simpleFilePreview_input', function(e) {
- $(this).parents('.simpleFilePreview').find('input.simpleFilePreview_formInput').trigger('click');
+ $(this).closest('.simpleFilePreview').find('input.simpleFilePreview_formInput').trigger('click');
e.preventDefault();
});
@@ -83,19 +83,19 @@ $('input[type=file]').simpleFilePreview({
return this;
}
- $(this).parents('.simpleFilePreview').find('.simpleFilePreview_preview').trigger('click');
+ $(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).parents('.simpleFilePreview');
+ 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) {
+ if (($parents.attr('data-sfpallowmultiple') == 1) && !$parents.find('.simpleFilePreview_preview').length) {
var newId = $.simpleFilePreview.uid++;
var $newN = $parents.clone(true).attr('id', "simpleFilePreview_" + newId);
@@ -105,22 +105,22 @@ $('input[type=file]').simpleFilePreview({
$parents.after($newN);
- var nw = $parents.parents('.simpleFilePreview_multi').width('+=' + $newN.outerWidth(true)).width();
+ var nw = $parents.closest('.simpleFilePreview_multi').width('+=' + $newN.outerWidth(true)).width();
- if (nw > $parents.parents('.simpleFilePreview_multiClip').width()) {
- $parents.parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_shiftRight').trigger('click');
+ if (nw > $parents.closest('.simpleFilePreview_multiClip').width()) {
+ $parents.closest('.simpleFilePreview_multiUI').find('.simpleFilePreview_shiftRight').trigger('click');
}
}
if (this.files && this.files[0]) {
- var exp = "^image\/(" + $.simpleFilePreview.previewFileTypes + ")$";
+ var exp = new RegExp("^image\/(" + $.simpleFilePreview.previewFileTypes + ")$");
- if ((new RegExp(exp)).test(this.files[0].type.toLowerCase()) && window.FileReader) {
+ 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);
+ addOrChangePreview($parents, e.target.result, '', options);
};
$FR.readAsDataURL(this.files[0]);
@@ -129,9 +129,9 @@ $('input[type=file]').simpleFilePreview({
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.iconPath + options.icons[m[1]], getFilename(this.value));
+ addOrChangePreview($parents, options.icons[m[1]], getFilename(this.value), options);
} else {
- addOrChangePreview($parents, options.iconPath + options.defaultIcon, getFilename(this.value));
+ addOrChangePreview($parents, options.defaultIcon, getFilename(this.value), options);
}
}
@@ -145,28 +145,28 @@ $('input[type=file]').simpleFilePreview({
// If a browser does report a valid path (IE or otherwise), then
// we'll try to get the file preview
- var exp = "^(" + $.simpleFilePreview.previewFileTypes + ")$";
+ var exp = new RegExp("^(" + $.simpleFilePreview.previewFileTypes + ")$");
var ext = getFileExt(this.value);
ext = ext ? ext.toLowerCase() : null;
- if (ext && !(/fakepath/.test(this.value.toLowerCase())) && (new RegExp(exp)).test(e)) {
+ 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);
+ addOrChangePreview($parents, "file://" + this.value, '', options);
} else {
// not an image (or using fakepath), so no preview anyway
if (options.icons[ext]) {
- addOrChangePreview($parents, options.iconPath + options.icons[ext], getFilename(this.value));
+ addOrChangePreview($parents, options.icons[ext], getFilename(this.value), options);
} else {
- addOrChangePreview($parents, options.iconPath + options.defaultIcon, getFilename(this.value));
+ addOrChangePreview($parents, options.defaultIcon, getFilename(this.value), options);
}
}
});
// show or hide "remove" icon for file preview/icon
$body.on('mouseover', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() {
- var $parents = $(this).parents('.simpleFilePreview');
+ var $parents = $(this).closest('.simpleFilePreview');
if ($parents.find('.simpleFilePreview_preview').is(':visible')) {
$parents.find('.simpleFilePreview_remove').show();
@@ -174,19 +174,22 @@ $('input[type=file]').simpleFilePreview({
});
$body.on('mouseout', '.simpleFilePreview_preview, .simpleFilePreview input.simpleFilePreview_formInput', function() {
- $(this).parents('.simpleFilePreview').find('.simpleFilePreview_remove').hide();
+ $(this).closest('.simpleFilePreview').find('.simpleFilePreview_remove').hide();
})
// remove file when preview/icon is clicked
$body.on('click', '.simpleFilePreview_preview', function() {
- var $parents = $(this).parents('.simpleFilePreview');
+ 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("");
}
- $parents.parents('.simpleFilePreview_multi').width('-=' + $parents.width());
+ limit($this, options, 1);
+
+ $parents.closest('.simpleFilePreview_multi').width('-=' + $parents.width());
$parents.remove();
return this;
@@ -199,6 +202,8 @@ $('input[type=file]').simpleFilePreview({
$parents.removeClass('simpleFilePreview_existing'); // no longer needed
}
+ limit($this, options, 1);
+
// kill value in the input
var $input = $parents.find('input.simpleFilePreview_formInput').val('');
@@ -210,16 +215,16 @@ $('input[type=file]').simpleFilePreview({
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)+"' ";
+ a += attr[j].name + "='" + $input.attr(attr[j].name) + "' ";
}
}
- $input.before('');
+ $input.before('');
$input.remove();
}
// remove the preview element
- $(this).remove();
+ $this.remove();
$parents.find('.simpleFilePreview_filename').remove();
// show styled input "button"
@@ -229,7 +234,7 @@ $('input[type=file]').simpleFilePreview({
// shift buttons for multi-selects
$body.on('click', '.simpleFilePreview_shiftRight', function() {
- var ul = $(this).parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
+ var ul = $(this).closest('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
var width = parseInt(ul.css('left')) + ul.width();
if (width > ul.parent().width()) {
@@ -241,7 +246,7 @@ $('input[type=file]').simpleFilePreview({
});
$body.on('click', '.simpleFilePreview_shiftLeft', function() {
- var ul = $(this).parents('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
+ var ul = $(this).closest('.simpleFilePreview_multiUI').find('.simpleFilePreview_multi');
var left = parseInt(ul.css('left'));
if (left < 0) {
@@ -256,6 +261,21 @@ $('input[type=file]').simpleFilePreview({
return these;
};
+ var limit = function($this, options, add) {
+ if (!options.limit) {
+ return these;
+ }
+
+ var $files = $this.closest('.simpleFilePreview_multi').find('> li');
+ add = add ? add : 0;
+
+ if ($files.length > (options.limit + add)) {
+ $files.last().hide();
+ } else {
+ $files.last().show();
+ }
+ };
+
var setup = function(these, options) {
var isMulti = these.is('[multiple]');
@@ -277,86 +297,98 @@ $('input[type=file]').simpleFilePreview({
// 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'
+ width: ($html.width() + 'px'),
+ height: ($html.height() + 'px')
});
// if it's a multi-select we use multiple separate inputs instead to support file preview
if (isMulti) {
$html.wrap("