/* +-----------------------------------------------------------------------+ | Copyright (c) 2006-2007 Mika Tuupola, Dylan Verheul | | All rights reserved. | | | | Redistribution and use in source and binary forms, with or without | | modification, are permitted provided that the following conditions | | are met: | | | | o Redistributions of source code must retain the above copyright | | notice, this list of conditions and the following disclaimer. | | o Redistributions in binary form must reproduce the above copyright | | notice, this list of conditions and the following disclaimer in the | | documentation and/or other materials provided with the distribution.| | | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | | +-----------------------------------------------------------------------+ */ /* $Id: jquery.jeditable.js,v 1.41 2007/02/15 07:54:23 tuupola Exp $ */ /** * Modified by Xander for Grooveshark project * Changes: * "this" now refers to editable element and editable control holder * @param String options[editable_element] element that will become editable * @param String options[editable_control] element that will make editable_element editable on event */ /** * jQuery inplace editor plugin (version 1.1.1) * * Based on editable by Dylan Verheul * http://www.dyve.net/jquery/?editable * * @name jEditable * @type jQuery * @param String url POST URL to send edited content * @param Hash options additional options * @param String options[name] POST parameter name of edited content * @param String options[id] POST parameter name of edited div id * @param String options[type] text or textarea * @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' or height in pixels * @param Mixed options[width] 'auto' or width in pixels * @param String options[postload] POST URL to fetch content before editing * @param String options[getload] GET URL to fetch content before editing * @param String options[data] Or content given as paramameter. * @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[onblur] 'cancel', 'submit' or 'ignore' * @param String options[submit] submit button value, empty means no button * @param String options[cancel] cancel button value, empty means no button * */ jQuery.fn.editable = function(url, options) { /* prevent elem has no properties error */ if (this.length == 0) { return(this); }; var settings = { url : url, name : 'value', id : 'id', idval : null, type : 'text', /* width : 'auto', height : 'auto', */ width : '', height : '', event : 'click', onblur : 'cancel', dataType : 'json', editable_element : this, editable_control : this, input_class : 'editable_textarea', callfront : null, callback : null }; if(options) { jQuery.extend(settings, options); }; if (!settings.idval) { settings.idval = $(this).attr('id') } jQuery(this).attr('title', settings.tooltip); var editable_holder = this; // -=(gEditable) event (click) on control will activate editing now=- // jQuery(this).find(settings.editable_control)[settings.event]( function(e) { var editing = false; var revert = ''; var t = null; // timeout /* (gEditable) save editable element to self because this changes when scope changes */ var self = $(settings.editable_element, editable_holder) || editable_holder; /* prevent throwing an exeption if edit field is clicked again */ if (editing) { return; } /* figure out how wide and tall we are */ var width = ('auto' == settings.width) ? jQuery(self).css('width') : settings.width; var height = ('auto' == settings.height) ? jQuery(self).css('height') : settings.height; editing = true; var revert = jQuery(self).html(); function reset() { if (t) { clearTimeout(t); } $(self).html(revert); editing = false; }; var proceed = function( new_settings ) { settings = new_settings; // revert = settings.text || revert || ''; // jQuery(self).html(settings.text); self.innerHTML = ''; // -=Clean edited element=- // $(self).html(''); /* create the form object */ $(self).append("
"); var f = $('form', self); /* main input element */ var i; switch (settings.type) { case 'textarea': $(f).append(''); i = $('textarea', f); jQuery(i).addClass(settings.input_class); if (settings.rows) { $(i).attr('rows', settings.rows); } else { jQuery(i).css('height', height); } if (settings.cols) { $(i).attr('cols', settings.cols); } else { jQuery(i).css('width', width); } break; case 'select': $(f).append(''); i = $('select', f); jQuery(i).addClass(settings.input_class); break; default: $(f).append(''); i = $('input', f); $(i).attr('type', settings.type); $(i).addClass(settings.input_class); /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */ $(i).attr('autocomplete','off'); } /* set input content via POST, GET, given data or existing value */ /* this looks weird because it is for maintaining bc */ var url; var type; if (settings.getload) { url = settings.getload; type = 'GET'; } else if (settings.postload) { url = settings.postload; type = 'POST'; } if (url) { var data = {}; data[settings.id] = self.id; jQuery.ajax({ type : type, url : url, data : data, success: function(str) { $(i).val(str); } }); } else if (settings.data) { $(i).val(settings.data); } else { $(i).val(settings.text); } $(i).attr('name', settings.name); $(f).append(i); if (settings.submit) { $(f).append(""); } if (settings.cancel) { $(f).append(""); b = $('button', f); jQuery(b).click(function() { reset(); }); } $(i).focus(); /* discard changes if pressing esc */ jQuery(i).keydown(function(e) { if (e.keyCode == 27) { e.preventDefault(); reset(); } }); /* discard, submit or nothing with changes when clicking outside */ /* do nothing is usable when navigating with tab */ var t; if ('cancel' == settings.onblur) { jQuery(i).blur(function(e) { t = setTimeout(reset, 500) }); /* TODO: does not currently work */ } else if ('submit' == settings.onblur) { jQuery(i).blur(function(e) { jQuery(f).submit(); }); } else { jQuery(i).blur(function(e) { /* TODO: maybe something here */ }); } jQuery(f).submit(function(e) { if (t) { clearTimeout(t); } /* do no submit */ e.preventDefault(); /* add edited content and id of edited element to POST */ var p = {}; var name = $(i).attr('name') var value = jQuery(i).val(); p[name] = value; p[settings.id] = settings.idval || $(self).attr('id'); /* show the saving indicator */ jQuery(self).html(options.indicator); // jQuery(self).load(settings.url, p, function(str) { ajax_call = function() { jQuery.ajax({ 'url' : settings.url, 'dataType' : settings.dataType, 'type' : 'post', 'data' : p, 'processData' : true, 'success' : function( data, status ) { editing = false; self.editing = false; if (settings.callback) { // jQuery(self).html(value); settings.callback( data ); } else if (settings.dataType != 'json') { jQuery(self).html(data); } }, 'error' : function(XMLHttpRequest, textStatus, errorThrown) { error = textStatus || errorThrown; console.error('jquery.jeditable: '+error); console.warn('Please make sure properly formatted json object returned from url'); // this; // the options for this ajax request } }); } ajax_call(); return false; }); } // -=End of "proceed()" wrapper function=- // // -=Callfront=- // if (settings.callfront) { settings.text = revert; settings.callfront( settings, proceed ); } else { proceed(); } }); return(this); };