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+""+ - ""); - 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 + "" + + ""); + + 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("" + (filename ? filename : "); + + // 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(""+((fn)?fn:"); - // 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("
        "); - $html.parents('.simpleFilePreview_multiUI') - .prepend("" + options.shiftRight + "") - .append("" + options.shiftLeft + ""); + $html.closest('.simpleFilePreview_multiUI') + .prepend("" + options.shiftRight + "") + .append("" + options.shiftLeft + ""); } - var exp = "^(" + $.simpleFilePreview.previewFileTypes + ")$"; var exists = options.existingFiles; - if (exists) { + if (!exists) { if (isMulti) { - // add all of the existing files to preview block - var arr = ($.isArray(exists)) ? 1 : 0; + $('.simpleFilePreview_multi').width($html.outerWidth(true) * $html.parent().find('.simpleFilePreview').length); + } - for (var i in exists) { - var ni = $.simpleFilePreview.uid++; - var nn = $html.clone(true).attr('id', "simpleFilePreview_" + ni); + return these; + } - nn.addClass('simpleFilePreview_existing') - .attr('data-sfprid', arr ? exists[i] : i) - .find('input.simpleFilePreview_formInput').remove(); + var exp = new RegExp("^(" + $.simpleFilePreview.previewFileTypes + ")$"); - $html.before(nn); + if (isMulti) { + // add all of the existing files to preview block + var arr = ($.isArray(exists)) ? 1 : 0; - var ext = getFileExt(exists[i]); - ext = ext ? ext.toLowerCase() : null; + for (var i in exists) { + var ni = $.simpleFilePreview.uid++; + var nn = $html.clone(true).attr('id', "simpleFilePreview_" + ni); - 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] - }; - } + nn.addClass('simpleFilePreview_existing') + .attr('data-sfprid', arr ? exists[i] : i) + .find('input.simpleFilePreview_formInput').remove(); - 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(); + $html.before(nn); - var ext = getFileExt($file['file']); - ext = ext ? ext.toLowerCase() : null; + var ext = getFileExt(exists[i]); + 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 (ext && exp.test(ext)) { + addOrChangePreview(nn, exists[i], '', options); + } else if (options.icons[ext]) { + addOrChangePreview(nn, options.icons[ext], getFilename(exists[i]), options); + } else { + addOrChangePreview(nn, options.defaultIcon, getFilename(exists[i]), options); } } - } - if (isMulti) { $('.simpleFilePreview_multi').width($html.outerWidth(true) * $html.parent().find('.simpleFilePreview').length); + + return these; + } + + // 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) { + return these; + } + + // 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 && exp.test(ext)) { + addOrChangePreview($html, $file['file'], '', options); + } else if (options.icons[ext]) { + addOrChangePreview($html, options.icons[ext], getFilename($file['file']), options); + } else { + addOrChangePreview($html, options.defaultIcon, getFilename($file['file']), options); } + + return these; }; - var addOrChangePreview = function($parents, src, filename) { + var addOrChangePreview = function($parents, src, filename, options) { filename = filename ? filename : null; + src = ((new RegExp('[/\\\\]')).test(src) ? '' : (options.iconPath)) + src $parents.find('.simpleFilePreview_input').hide(); @@ -368,12 +400,14 @@ $('input[type=file]').simpleFilePreview({ $parents.append("" + (filename ? filename : "); + + " title='Remove " + (filename ? filename : 'this file') + "' />"); // for tooltips $parents.find('input.simpleFilePreview_formInput').attr('title', "Remove " + (filename ? filename : 'this file')); } + limit($parents, options); + if (!filename) { return null; } @@ -418,6 +452,7 @@ $('input[type=file]').simpleFilePreview({ 'shiftRight': '>>', 'iconPath': '', 'defaultIcon': 'preview_file.png', + 'limit': 0, 'icons': { 'png': 'preview_png.png', 'gif': 'preview_png.png', diff --git a/simpleFilePreview.css b/simpleFilePreview.css index 0114621..2a3a1d6 100755 --- a/simpleFilePreview.css +++ b/simpleFilePreview.css @@ -1,95 +1,107 @@ - .simpleFilePreview_multiUI { - border: 2px solid #fff; - border-radius:4px; - background-color:#f2f2f2; - box-shadow:0 0 0 1px #c1c1c1; - width: 450px; - position: relative; - padding: 15px 30px; - margin-left: 75px; + padding: 15px 30px; + position: relative; } + .simpleFilePreview_multiClip { - overflow: hidden; + overflow: hidden; } + .simpleFilePreview_multi { - display: block; - height: 130px; - padding: 0; - position: relative; - left: 0; + display: block; + height: 120px; + padding: 0; + position: relative; + left: 0; } .simpleFilePreview_shifter { - position: absolute; - top: 70px; - cursor: pointer; + position: absolute; + top: 78px; + cursor: pointer; +} + +.simpleFilePreview_shiftLeft { + left: 3px; +} + +.simpleFilePreview_shiftRight { + right: 3px; +} + +.imageHolder { + margin: 10px 15px; } -.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; - padding: 3px; - text-align: center; - cursor: pointer; - overflow: hidden; - box-shadow:0 0 4px 0 #555; -} -.simpleFilePreview_multi .simpleFilePreview { float: left; } + 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%; + position: relative; + overflow: hidden; + display: inline-block; + padding-top: 40%; + height: 100%; + width: 100%; } + .simpleFilePreview:hover { - background-color: #ddd; + 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; + position: absolute; + top: 0; + right: 0; + opacity: 0; + -moz-opacity: 0; + filter: alpha(opacity=0); + cursor: pointer; + z-index: 5; } .simpleFilePreview_preview { - max-width: 120px; - max-height: 120px; - z-index: 3; + max-width: 112px; + max-height: 112px; + z-index: 3; } + .simpleFilePreview_preview.simpleFilePreview_hasFilename { - max-width: 120px; - max-height: 100px; + max-width: 120px; + max-height: 100px; } + .simpleFilePreview_filename { - font-size: 0.8em; - color: #666; - width: 95%; - height: 1.15em; - overflow: hidden; - display: inline-block; + font-size: 0.8em; + color: #666; + width: 95%; + height: 1.15em; + overflow: hidden; + display: inline-block; } + .simpleFilePreview_remove { - display: none; - color: #c33; - font-weight: bold; - position: absolute; - top: 0; - right: 0; - z-index: 4; + display: none; + color: #c33; + font-weight: bold; + position: absolute; + top: 5px; + right: 5px; + z-index: 4; } From 4cee495ab7ea516b8c8bd1ab0d29d54524dc720d Mon Sep 17 00:00:00 2001 From: Lito Date: Fri, 10 Apr 2015 16:16:14 +0200 Subject: [PATCH 3/5] Minor fixes and update docs --- jquery.simpleFilePreview.js | 15 +++++++-------- simpleFilePreview.css | 0 2 files changed, 7 insertions(+), 8 deletions(-) mode change 100755 => 100644 simpleFilePreview.css diff --git a/jquery.simpleFilePreview.js b/jquery.simpleFilePreview.js index 3000d3e..3efb43f 100644 --- a/jquery.simpleFilePreview.js +++ b/jquery.simpleFilePreview.js @@ -33,6 +33,7 @@ $('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 }); * * TODO: @@ -47,23 +48,21 @@ $('input[type=file]').simpleFilePreview({ 'use strict'; $.fn.simpleFilePreview = function(options) { - var these = this; - - if (!these || !these.length) { - return these; + if (!this || !this.length) { + return this; } // Set up options (and defaults) options = options ? options : {}; options = $.extend({}, $.simpleFilePreview.defaults, options); - these.each(function() { + this.each(function() { setup($(this), options); }); // set up global events if ($.simpleFilePreview.init) { - return these; + return this; } var $body = $('body'); @@ -258,12 +257,12 @@ $('input[type=file]').simpleFilePreview({ }); // return node for fluid chain calling - return these; + return this; }; var limit = function($this, options, add) { if (!options.limit) { - return these; + return false; } var $files = $this.closest('.simpleFilePreview_multi').find('> li'); diff --git a/simpleFilePreview.css b/simpleFilePreview.css old mode 100755 new mode 100644 From 9cfc4d72b9929e865290e8238586dbc3727891af Mon Sep 17 00:00:00 2001 From: Lito Date: Tue, 14 Apr 2015 00:29:37 +0200 Subject: [PATCH 4/5] Updated styles and fixed duplicated doc extension --- jquery.simpleFilePreview.js | 1 - simpleFilePreview.css | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/jquery.simpleFilePreview.js b/jquery.simpleFilePreview.js index 3efb43f..e4f0d0a 100644 --- a/jquery.simpleFilePreview.js +++ b/jquery.simpleFilePreview.js @@ -481,7 +481,6 @@ $('input[type=file]').simpleFilePreview({ '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', diff --git a/simpleFilePreview.css b/simpleFilePreview.css index 2a3a1d6..3a5b4c9 100644 --- a/simpleFilePreview.css +++ b/simpleFilePreview.css @@ -1,5 +1,5 @@ .simpleFilePreview_multiUI { - padding: 15px 30px; + padding: 0 30px; position: relative; } @@ -17,7 +17,7 @@ .simpleFilePreview_shifter { position: absolute; - top: 78px; + top: 62px; cursor: pointer; } From d08036c04247c2507cfa38e96007ae19264d570a Mon Sep 17 00:00:00 2001 From: Lito Date: Fri, 17 Apr 2015 16:09:40 +0200 Subject: [PATCH 5/5] Added minified files --- jquery.simpleFilePreview.min.js | 6 ++++++ simpleFilePreview.min.css | 1 + 2 files changed, 7 insertions(+) create mode 100644 jquery.simpleFilePreview.min.js create mode 100644 simpleFilePreview.min.css diff --git a/jquery.simpleFilePreview.min.js b/jquery.simpleFilePreview.min.js new file mode 100644 index 0000000..4a87b07 --- /dev/null +++ b/jquery.simpleFilePreview.min.js @@ -0,0 +1,6 @@ +/*! + * jquery.simpleFilePreview v0.1.0 (https://github.com/jakerella/jquerySimpleFilePreview) + * Copyright (c) 2012 Jordan Kasper + * 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 diff --git a/simpleFilePreview.min.css b/simpleFilePreview.min.css new file mode 100644 index 0000000..83064fa --- /dev/null +++ b/simpleFilePreview.min.css @@ -0,0 +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