diff --git a/jquery.jeditable.js b/jquery.jeditable.js index 1d066d4..c0ea32d 100644 --- a/jquery.jeditable.js +++ b/jquery.jeditable.js @@ -15,52 +15,56 @@ */ /** - * Version 1.7.3 - * - * ** means there is basic unit tests for this parameter. - * - * @name Jeditable - * @type jQuery - * @param String target (POST) URL or function to send edited content to ** - * @param Hash options additional options - * @param String options[method] method to use to send edited content (POST or PUT) ** - * @param Function options[callback] Function to run after submitting edited content ** - * @param String options[name] POST parameter name of edited content - * @param String options[id] POST parameter name of edited div id - * @param Hash options[submitdata] Extra parameters to send when submitting edited content. - * @param String options[type] text, textarea or select (or any 3rd party input type) ** - * @param Integer options[rows] number of rows if using textarea ** - * @param Integer options[cols] number of columns if using textarea ** - * @param Mixed options[height] 'auto', 'none' or height in pixels ** - * @param Mixed options[width] 'auto', 'none' or width in pixels ** - * @param String options[loadurl] URL to fetch input content before editing ** - * @param String options[loadtype] Request type for load url. Should be GET or POST. - * @param String options[loadtext] Text to display while loading external content. - * @param Mixed options[loaddata] Extra parameters to pass when fetching content before editing. - * @param Mixed options[data] Or content given as paramameter. String or function.** - * @param String options[indicator] indicator html to show when saving - * @param String options[tooltip] optional tooltip text via title attribute ** - * @param String options[event] jQuery event such as 'click' of 'dblclick' ** - * @param String options[submit] submit button value, empty means no button ** - * @param String options[cancel] cancel button value, empty means no button ** - * @param String options[cssclass] CSS class to apply to input form. 'inherit' to copy from parent. ** - * @param String options[style] Style to apply to input form 'inherit' to copy from parent. ** - * @param String options[select] true or false, when true text is highlighted ?? - * @param String options[placeholder] Placeholder text or html to insert when element is empty. ** - * @param String options[onblur] 'cancel', 'submit', 'ignore' or function ?? - * - * @param Function options[onsubmit] function(settings, original) { ... } called before submit - * @param Function options[onreset] function(settings, original) { ... } called before reset - * @param Function options[onerror] function(settings, original, xhr) { ... } called on error - * - * @param Hash options[ajaxoptions] jQuery Ajax options. See docs.jquery.com. - * - */ + * Version 1.7.3 + * + * ** means there is basic unit tests for this parameter. + * + * @name Jeditable + * @type jQuery + * @param String target (POST) URL or function to send edited content to ** + * @param Hash options additional options + * @param String options[method] method to use to send edited content (POST or PUT) ** + * @param Function options[callback] Function to run after submitting edited content ** + * @param String options[name] POST parameter name of edited content + * @param String options[id] POST parameter name of edited div id + + * @param String options[params] POST parameter name of edited element data-params - it's more better for HTML syntax + * @param String options[loadpar] POST parameter name of edited element data-loadpar - it's more better for HTML syntax + + * @param Hash options[submitdata] Extra parameters to send when submitting edited content. + * @param String options[type] text, textarea or select (or any 3rd party input type) ** + * @param Integer options[rows] number of rows if using textarea ** + * @param Integer options[cols] number of columns if using textarea ** + * @param Mixed options[height] 'auto', 'none' or height in pixels ** + * @param Mixed options[width] 'auto', 'none' or width in pixels ** + * @param String options[loadurl] URL to fetch input content before editing ** + * @param String options[loadtype] Request type for load url. Should be GET or POST. + * @param String options[loadtext] Text to display while loading external content. + * @param Mixed options[loaddata] Extra parameters to pass when fetching content before editing. + * @param Mixed options[data] Or content given as paramameter. String or function.** + * @param String options[indicator] indicator html to show when saving + * @param String options[tooltip] optional tooltip text via title attribute ** + * @param String options[event] jQuery event such as 'click' of 'dblclick' ** + * @param String options[submit] submit button value, empty means no button ** + * @param String options[cancel] cancel button value, empty means no button ** + * @param String options[cssclass] CSS class to apply to input form. 'inherit' to copy from parent. ** + * @param String options[style] Style to apply to input form 'inherit' to copy from parent. ** + * @param String options[select] true or false, when true text is highlighted ?? + * @param String options[placeholder] Placeholder text or html to insert when element is empty. ** + * @param String options[onblur] 'cancel', 'submit', 'ignore' or function ?? + * + * @param Function options[onsubmit] function(settings, original) { ... } called before submit + * @param Function options[onreset] function(settings, original) { ... } called before reset + * @param Function options[onerror] function(settings, original, xhr) { ... } called on error + * + * @param Hash options[ajaxoptions] jQuery Ajax options. See docs.jquery.com. + * + */ (function($) { $.fn.editable = function(target, options) { - + if ('disable' == target) { $(this).data('disabled.editable', true); return; @@ -76,107 +80,105 @@ .removeData('event.editable'); return; } - - var settings = $.extend({}, $.fn.editable.defaults, {target:target}, options); - + + var settings = $.extend({}, $.fn.editable.defaults, { + target: target + }, options); + /* setup some functions */ - var plugin = $.editable.types[settings.type].plugin || function() { }; - var submit = $.editable.types[settings.type].submit || function() { }; - var buttons = $.editable.types[settings.type].buttons - || $.editable.types['defaults'].buttons; - var content = $.editable.types[settings.type].content - || $.editable.types['defaults'].content; - var element = $.editable.types[settings.type].element - || $.editable.types['defaults'].element; - var reset = $.editable.types[settings.type].reset - || $.editable.types['defaults'].reset; - var callback = settings.callback || function() { }; - var onedit = settings.onedit || function() { }; - var onsubmit = settings.onsubmit || function() { }; - var onreset = settings.onreset || function() { }; - var onerror = settings.onerror || reset; - + var plugin = $.editable.types[settings.type].plugin || function() {}; + var submit = $.editable.types[settings.type].submit || function() {}; + var buttons = $.editable.types[settings.type].buttons || $.editable.types['defaults'].buttons; + var content = $.editable.types[settings.type].content || $.editable.types['defaults'].content; + var element = $.editable.types[settings.type].element || $.editable.types['defaults'].element; + var reset = $.editable.types[settings.type].reset || $.editable.types['defaults'].reset; + var callback = settings.callback || function() {}; + var onedit = settings.onedit || function() {}; + var onsubmit = settings.onsubmit || function() {}; + var onreset = settings.onreset || function() {}; + var onerror = settings.onerror || reset; + /* Show tooltip. */ if (settings.tooltip) { $(this).attr('title', settings.tooltip); } - - settings.autowidth = 'auto' == settings.width; + + settings.autowidth = 'auto' == settings.width; settings.autoheight = 'auto' == settings.height; - + return this.each(function() { - + /* Save this to self because this changes when scope changes. */ - var self = this; - + var self = this; + /* Inlined block elements lose their width and height after first edit. */ /* Save them for later use as workaround. */ - var savedwidth = $(self).width(); + var savedwidth = $(self).width(); var savedheight = $(self).height(); /* Save so it can be later used by $.editable('destroy') */ $(this).data('event.editable', settings.event); - + /* If element is empty add something clickable (if requested) */ if (!$.trim($(this).html())) { $(this).html(settings.placeholder); } - + $(this).bind(settings.event, function(e) { - + /* Abort if element is disabled. */ if (true === $(this).data('disabled.editable')) { return; } - + /* Prevent throwing an exeption if edit field is clicked again. */ if (self.editing) { return; } - + /* Abort if onedit hook returns false. */ if (false === onedit.apply(this, [settings, self])) { - return; + return; } - + /* Prevent default action and bubbling. */ e.preventDefault(); e.stopPropagation(); - + /* Remove tooltip. */ if (settings.tooltip) { $(self).removeAttr('title'); } - + /* Figure out how wide and tall we are, saved width and height. */ /* Workaround for http://dev.jquery.com/ticket/2190 */ if (0 == $(self).width()) { - settings.width = savedwidth; + settings.width = savedwidth; settings.height = savedheight; } else { if (settings.width != 'none') { - settings.width = - settings.autowidth ? $(self).width() : settings.width; + settings.width = + settings.autowidth ? $(self).width() : settings.width; } if (settings.height != 'none') { - settings.height = + settings.height = settings.autoheight ? $(self).height() : settings.height; } } - + /* Remove placeholder text, replace is here because of IE. */ - if ($(this).html().toLowerCase().replace(/(;|"|\/)/g, '') == + if ($(this).html().toLowerCase().replace(/(;|"|\/)/g, '') == settings.placeholder.toLowerCase().replace(/(;|"|\/)/g, '')) { - $(this).html(''); + $(this).html(''); } - - self.editing = true; - self.revert = $(self).html(); + + self.editing = true; + self.revert = $(self).html(); $(self).html(''); /* Create the form object. */ var form = $('
'); - + /* Apply css or style or both. */ if (settings.cssclass) { if ('inherit' == settings.cssclass) { @@ -190,7 +192,7 @@ if ('inherit' == settings.style) { form.attr('style', $(self).attr('style')); /* IE needs the second line or display wont be inherited. */ - form.css('display', $(self).css('display')); + form.css('display', $(self).css('display')); } else { form.attr('style', settings.style); } @@ -201,7 +203,7 @@ /* Set input content via POST, GET, given data or existing value. */ var input_content; - + if (settings.loadurl) { var t = setTimeout(function() { input.disabled = true; @@ -210,21 +212,22 @@ var loaddata = {}; loaddata[settings.id] = self.id; + loaddata[settings.loadpar] = $(self).data('loadpar'); if ($.isFunction(settings.loaddata)) { $.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings])); } else { $.extend(loaddata, settings.loaddata); } $.ajax({ - type : settings.loadtype, - url : settings.loadurl, - data : loaddata, - async : false, - success: function(result) { - window.clearTimeout(t); - input_content = result; - input.disabled = false; - } + type: settings.loadtype, + url: settings.loadurl, + data: loaddata, + async: false, + success: function(result) { + window.clearTimeout(t); + input_content = result; + input.disabled = false; + } }); } else if (settings.data) { input_content = settings.data; @@ -232,18 +235,18 @@ input_content = settings.data.apply(self, [self.revert, settings]); } } else { - input_content = self.revert; + input_content = self.revert; } content.apply(form, [input_content, settings, self]); input.attr('name', settings.name); - + /* Add buttons to the form. */ buttons.apply(form, [settings, self]); - + /* Add created form to self. */ $(self).append(form); - + /* Attach 3rd party plugin if requested. */ plugin.apply(form, [settings, self]); @@ -254,7 +257,7 @@ if (settings.select) { input.select(); } - + /* discard changes if pressing esc */ input.keydown(function(e) { if (e.keyCode == 27) { @@ -286,110 +289,111 @@ }); } else { input.blur(function(e) { - /* TODO: maybe something here */ + /* TODO: maybe something here */ }); } form.submit(function(e) { - if (t) { + if (t) { clearTimeout(t); } /* Do no submit. */ - e.preventDefault(); - + e.preventDefault(); + /* Call before submit hook. */ - /* If it returns false abort submitting. */ - if (false !== onsubmit.apply(form, [settings, self])) { + /* If it returns false abort submitting. */ + if (false !== onsubmit.apply(form, [settings, self])) { /* Custom inputs call before submit hook. */ /* If it returns false abort submitting. */ - if (false !== submit.apply(form, [settings, self])) { - - /* Check if given target is function */ - if ($.isFunction(settings.target)) { - var str = settings.target.apply(self, [input.val(), settings]); - $(self).html(str); - self.editing = false; - callback.apply(self, [self.innerHTML, settings]); - /* TODO: this is not dry */ - if (!$.trim($(self).html())) { - $(self).html(settings.placeholder); - } - } else { - /* Add edited content and id of edited element to POST. */ - var submitdata = {}; - submitdata[settings.name] = input.val(); - submitdata[settings.id] = self.id; - /* Add extra data to be POST:ed. */ - if ($.isFunction(settings.submitdata)) { - $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings])); - } else { - $.extend(submitdata, settings.submitdata); - } - - /* Quick and dirty PUT support. */ - if ('PUT' == settings.method) { - submitdata['_method'] = 'put'; - } - - /* Show the saving indicator. */ - $(self).html(settings.indicator); - - /* Defaults for ajaxoptions. */ - var ajaxoptions = { - type : 'POST', - data : submitdata, - dataType: 'html', - url : settings.target, - success : function(result, status) { - if (ajaxoptions.dataType == 'html') { - $(self).html(result); - } - self.editing = false; - callback.apply(self, [result, settings]); - if (!$.trim($(self).html())) { - $(self).html(settings.placeholder); - } - }, - error : function(xhr, status, error) { - onerror.apply(form, [settings, self, xhr]); - } - }; - - /* Override with what is given in settings.ajaxoptions. */ - $.extend(ajaxoptions, settings.ajaxoptions); - $.ajax(ajaxoptions); - + if (false !== submit.apply(form, [settings, self])) { + + /* Check if given target is function */ + if ($.isFunction(settings.target)) { + var str = settings.target.apply(self, [input.val(), settings]); + $(self).html(str); + self.editing = false; + callback.apply(self, [self.innerHTML, settings]); + /* TODO: this is not dry */ + if (!$.trim($(self).html())) { + $(self).html(settings.placeholder); + } + } else { + /* Add edited content and id of edited element to POST. */ + var submitdata = {}; + submitdata[settings.name] = input.val(); + submitdata[settings.id] = self.id; + submitdata[settings.params] = $(self).data('params'); + /* Add extra data to be POST:ed. */ + if ($.isFunction(settings.submitdata)) { + $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings])); + } else { + $.extend(submitdata, settings.submitdata); + } + + /* Quick and dirty PUT support. */ + if ('PUT' == settings.method) { + submitdata['_method'] = 'put'; + } + + /* Show the saving indicator. */ + $(self).html(settings.indicator); + + /* Defaults for ajaxoptions. */ + var ajaxoptions = { + type: 'POST', + data: submitdata, + dataType: 'html', + url: settings.target, + success: function(result, status) { + if (ajaxoptions.dataType == 'html') { + $(self).html(result); + } + self.editing = false; + callback.apply(self, [result, settings]); + if (!$.trim($(self).html())) { + $(self).html(settings.placeholder); + } + }, + error: function(xhr, status, error) { + onerror.apply(form, [settings, self, xhr]); + } + }; + + /* Override with what is given in settings.ajaxoptions. */ + $.extend(ajaxoptions, settings.ajaxoptions); + $.ajax(ajaxoptions); + } } } - + /* Show tooltip again. */ $(self).attr('title', settings.tooltip); - + return false; }); }); - + /* Privileged methods */ this.reset = function(form) { /* Prevent calling reset twice when blurring. */ if (this.editing) { /* Before reset hook, if it returns false abort reseting. */ - if (false !== onreset.apply(form, [settings, self])) { + if (false !== onreset.apply(form, [settings, self])) { $(self).html(self.revert); - self.editing = false; + self.editing = false; if (!$.trim($(self).html())) { $(self).html(settings.placeholder); } /* Show tooltip again. */ if (settings.tooltip) { - $(self).attr('title', settings.tooltip); + $(self).attr('title', settings.tooltip); } - } + } } - }; + }; }); }; @@ -398,18 +402,18 @@ $.editable = { types: { defaults: { - element : function(settings, original) { - var input = $(''); + element: function(settings, original) { + var input = $(''); $(this).append(input); - return(input); + return (input); }, - content : function(string, settings, original) { + content: function(string, settings, original) { $(':input:first', this).val(string); }, - reset : function(settings, original) { - original.reset(this); + reset: function(settings, original) { + original.reset(this); }, - buttons : function(settings, original) { + buttons: function(settings, original) { var form = this; if (settings.submit) { /* If given html string use that. */ @@ -419,10 +423,10 @@ form.submit(); } }); - /* Otherwise use button with given string as text. */ + /* Otherwise use button with given string as text. */ } else { var submit = $(''); - submit.html(settings.submit); + submit.html(settings.submit); } $(this).append(submit); } @@ -430,7 +434,7 @@ /* If given html string use that. */ if (settings.cancel.match(/>$/)) { var cancel = $(settings.cancel); - /* otherwise use button with given string as text */ + /* otherwise use button with given string as text */ } else { var cancel = $(''); cancel.html(settings.cancel); @@ -439,9 +443,9 @@ $(cancel).click(function(event) { if ($.isFunction($.editable.types[settings.type].reset)) { - var reset = $.editable.types[settings.type].reset; + var reset = $.editable.types[settings.type].reset; } else { - var reset = $.editable.types['defaults'].reset; + var reset = $.editable.types['defaults'].reset; } reset.apply(form, [settings, original]); return false; @@ -450,19 +454,23 @@ } }, text: { - element : function(settings, original) { + element: function(settings, original) { var input = $(''); - if (settings.width != 'none') { input.attr('width', settings.width); } - if (settings.height != 'none') { input.attr('height', settings.height); } + if (settings.width != 'none') { + input.attr('width', settings.width); + } + if (settings.height != 'none') { + input.attr('height', settings.height); + } /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */ //input[0].setAttribute('autocomplete','off'); - input.attr('autocomplete','off'); + input.attr('autocomplete', 'off'); $(this).append(input); - return(input); + return (input); } }, textarea: { - element : function(settings, original) { + element: function(settings, original) { var textarea = $(''); if (settings.rows) { textarea.attr('rows', settings.rows); @@ -475,21 +483,21 @@ textarea.width(settings.width); } $(this).append(textarea); - return(textarea); + return (textarea); } }, select: { - element : function(settings, original) { + element: function(settings, original) { var select = $(''); $(this).append(select); - return(select); + return (select); }, - content : function(data, settings, original) { + content: function(data, settings, original) { /* If it is string assume it is json. */ - if (String == data.constructor) { - eval ('var json = ' + data); + if (String == data.constructor) { + eval('var json = ' + data); } else { - /* Otherwise assume it is a hash already. */ + /* Otherwise assume it is a hash already. */ var json = data; } for (var key in json) { @@ -498,15 +506,15 @@ } if ('selected' == key) { continue; - } + } var option = $('').val(key).append(json[key]); - $('select', this).append(option); - } - /* Loop option again to set selected. IE needed this... */ + $('select', this).append(option); + } + /* Loop option again to set selected. IE needed this... */ $('select', this).children().each(function() { - if ($(this).val() == json['selected'] || + if ($(this).val() == json['selected'] || $(this).text() == $.trim(original.revert)) { - $(this).attr('selected', 'selected'); + $(this).attr('selected', 'selected'); } }); /* Submit on change if no submit button defined. */ @@ -528,18 +536,20 @@ /* Publicly accessible defaults. */ $.fn.editable.defaults = { - name : 'value', - id : 'id', - type : 'text', - width : 'auto', - height : 'auto', - event : 'click.editable', - onblur : 'cancel', - loadtype : 'GET', - loadtext : 'Loading...', + name: 'value', + id: 'id', + params: 'params', + loadpar: 'loadpar', + type: 'text', + width: 'auto', + height: 'auto', + event: 'click.editable', + onblur: 'cancel', + loadtype: 'GET', + loadtext: 'Loading...', placeholder: 'Click to edit', - loaddata : {}, - submitdata : {}, + loaddata: {}, + submitdata: {}, ajaxoptions: {} };