PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/js/src/jquery.editInPlace.js

http://xtraupload.googlecode.com/
JavaScript | 306 lines | 223 code | 8 blank | 75 comment | 4 complexity | 05f5df94f58daf7b3539fc543b9e5294 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. +-----------------------------------------------------------------------+
  3. | Copyright (c) 2007 David Hauenstein |
  4. | All rights reserved. |
  5. | |
  6. | Redistribution and use in source and binary forms, with or without |
  7. | modification, are permitted provided that the following conditions |
  8. | are met: |
  9. | |
  10. | o Redistributions of source code must retain the above copyright |
  11. | notice, this list of conditions and the following disclaimer. |
  12. | o Redistributions in binary form must reproduce the above copyright |
  13. | notice, this list of conditions and the following disclaimer in the |
  14. | documentation and/or other materials provided with the distribution.|
  15. | |
  16. | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
  17. | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
  18. | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  19. | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
  20. | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  21. | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
  22. | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  23. | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  24. | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
  25. | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  26. | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
  27. | |
  28. +-----------------------------------------------------------------------+
  29. */
  30. /* $Id: jquery.inplace.js,v 0.9.9.2 2007/12/04 09:39:00 hauenstein Exp $ */
  31. /**
  32. * jQuery inplace editor plugin.
  33. *
  34. * Created by: David Hauenstein
  35. * http://www.davehauenstein.com/blog/
  36. *
  37. *
  38. * Nate Wiger (http://www.dangerrabbit.com) added callbacks, exposed
  39. * more settings, added required values and "selected" options,
  40. * and enabled compatibility with jQuery.noConflict() mode.
  41. * Thanks to Joe and Vaska for helping me get this working on jQuery 1.1
  42. * Thanks to Pranav (http://www.startupdunia.com/) for finding a scope bug (0.9.4 release)
  43. * Thanks to Simon for finding some extraneous code (0.9.5 release)
  44. *
  45. *
  46. * @name editInPlace
  47. * @type jQuery
  48. * @param Hash options additional options
  49. * @param String options[url] POST URL to send edited content
  50. * @param String options[params] paramters sent via the post request to the server; string; ex: name=dave&last_name=hauenstein
  51. * @param String options[field_type] can be: text, textarea, select; default: text
  52. * @param String options[select_options] this is a string seperated by commas for the dropdown options, if field_type is dropdown
  53. * @param String options[textarea_cols] number of columns textarea will have, if field_type is textarea; default: 25
  54. * @param String options[textarea_rows] number of rows textarea will have, if field_type is textarea; default: 10
  55. * @param String options[bg_over] background color of editable elements on HOVER
  56. * @param String options[bg_out] background color of editable elements on RESTORE from hover
  57. * @param String options[saving_text] text to be used when server is saving information; default: 'Saving...'
  58. * @param String options[saving_image] specify an image location instead of text while server is saving; default: uses saving text
  59. * @param String options[value_required] if set to true, the element will not be saved unless a value is entered
  60. * @param String options[element_id] name of parameter holding element_id; default: element_id
  61. * @param String options[update_value] name of parameter holding update_value; default: update_value
  62. * @param String options[original_html] name of parameter holding original_html; default: original_html
  63. * @param String options[save_button] image button tag to use as "Save" button
  64. * @param String options[cancel_button] image button tag to use as "Cancel" button
  65. * @param String options[callback] call function instead of submitting to url
  66. *
  67. */
  68. jQuery.fn.editInPlace = function(options) {
  69. //#######################################################################
  70. //DEFINE THE DEFAULT SETTINGS, SWITCH THEM WITH THE OPTIONS USER PROVIDES
  71. var settings = {
  72. url: "",
  73. params: "",
  74. field_type: "text",
  75. select_options: "",
  76. textarea_cols: "25",
  77. textarea_rows: "10",
  78. bg_over: "#ffc",
  79. bg_out: "transparent",
  80. saving_text: "Saving...",
  81. saving_image: "",
  82. default_text: "(Click here to add text)",
  83. select_text: "Choose new value",
  84. value_required: null,
  85. element_id: "element_id",
  86. update_value: "update_value",
  87. original_html: "original_html",
  88. save_button: '<input type="submit" class="inplace_save" value="Save"/>',
  89. cancel_button: '<input type="submit" class="inplace_cancel" value="Cancel"/>',
  90. callback: null,
  91. success: null,
  92. error: function(request){
  93. alert("Failed to save value: " + request.responseText || 'Unspecified Error');
  94. }
  95. };
  96. if(options) {
  97. jQuery.extend(settings, options);
  98. }
  99. //#######################################################################
  100. //preload the loading icon if it exists
  101. if(settings.saving_image != ""){
  102. var loading_image = new Image();
  103. loading_image.src = settings.saving_image;
  104. }
  105. //#######################################################################
  106. //THIS FUNCTION WILL TRIM WHITESPACE FROM BEFORE/AFTER A STRING
  107. String.prototype.trim = function() {
  108. return this.replace(/^\s+/, '')
  109. .replace(/\s+$/, '');
  110. };
  111. //#######################################################################
  112. //THIS FUNCTION WILL ESCAPE ANY HTML ENTITIES SO "Quoted Values" work
  113. String.prototype.escape_html = function() {
  114. return this.replace(/&/g, "&amp;")
  115. .replace(/</g, "&lt;")
  116. .replace(/>/g, "&gt;")
  117. .replace(/"/g, "&quot;");
  118. };
  119. //#######################################################################
  120. //CREATE THE INPLACE EDITOR
  121. return this.each(function(){
  122. if(jQuery(this).html() == "") jQuery(this).html(settings.default_text);
  123. var editing = false;
  124. //save the original element - for change of scope
  125. var original_element = jQuery(this);
  126. var click_count = 0;
  127. jQuery(this)
  128. .mouseover(function(){
  129. jQuery(this).css("background", settings.bg_over);
  130. })
  131. .mouseout(function(){
  132. jQuery(this).css("background", settings.bg_out);
  133. })
  134. .click(function(){
  135. click_count++;
  136. if(!editing)
  137. {
  138. editing = true;
  139. //save original text - for cancellation functionality
  140. var original_html = jQuery(this).html();
  141. var buttons_code = settings.save_button + ' ' + settings.cancel_button;
  142. //if html is our default text, clear it out to prevent saving accidentally
  143. if (original_html == settings.default_text) jQuery(this).html('');
  144. if (settings.field_type == "textarea")
  145. {
  146. var use_field_type = '<textarea name="inplace_value" class="inplace_field" rows="' + settings.textarea_rows +
  147. '" cols="' + settings.textarea_cols + '">' + jQuery(this).text().trim().escape_html() +
  148. '</textarea>';
  149. }
  150. else if(settings.field_type == "text")
  151. {
  152. var use_field_type = '<input type="text" name="inplace_value" class="inplace_field" value="' +
  153. jQuery(this).text().trim().escape_html() + '" />';
  154. }
  155. else if(settings.field_type == "select")
  156. {
  157. var optionsArray = settings.select_options.split(',');
  158. var use_field_type = '<select name="inplace_value" class="inplace_field"><option value="">' +
  159. settings.select_text + '</option>';
  160. for(var i=0; i<optionsArray.length; i++){
  161. var optionsValuesArray = optionsArray[i].split(':');
  162. var use_value = optionsValuesArray[1] || optionsValuesArray[0];
  163. var selected = use_value == original_html ? 'selected="selected" ' : '';
  164. use_field_type += '<option ' + selected + 'value="' + use_value.trim().escape_html() + '">' +
  165. optionsValuesArray[0].trim().escape_html() + '</option>';
  166. }
  167. use_field_type += '</select>';
  168. }
  169. //insert the new in place form after the element they click, then empty out the original element
  170. jQuery(this).html('<form class="inplace_form" style="display: inline; margin: 0; padding: 0;">' +
  171. use_field_type + ' ' + buttons_code + '</form>');
  172. }//END- if(!editing) -END
  173. if(click_count == 1)
  174. {
  175. //set the focus to the new input element
  176. original_element.children("form").children(".inplace_field").focus().select();
  177. //HIT ESC KEY
  178. $(document).keyup(function(event){
  179. if (event.keyCode == 27) {
  180. editing = false;
  181. click_count = 0;
  182. //put the original background color in
  183. original_element.css("background", settings.bg_out);
  184. //put back the original text
  185. original_element.html(original_html);
  186. return false;
  187. }
  188. });
  189. //CLICK CANCEL BUTTON functionality
  190. original_element.children("form").children(".inplace_cancel").click(function(){
  191. editing = false;
  192. click_count = 0;
  193. //put the original background color in
  194. original_element.css("background", settings.bg_out);
  195. //put back the original text
  196. original_element.html(original_html);
  197. return false;
  198. });
  199. //CLICK SAVE BUTTON functionality
  200. original_element.children("form").children(".inplace_save").click(function(){
  201. //put the original background color in
  202. original_element.css("background", settings.bg_out);
  203. var new_html = jQuery(this).parent().children(0).val();
  204. //set saving message
  205. if(settings.saving_image != ""){
  206. var saving_message = '<img src="' + settings.saving_image + '" alt="Saving..." />';
  207. } else {
  208. var saving_message = settings.saving_text;
  209. }
  210. //place the saving text/image in the original element
  211. original_element.html(saving_message);
  212. if(settings.params != ""){
  213. settings.params = "&" + settings.params;
  214. }
  215. if(settings.callback) {
  216. html = settings.callback(original_element.attr("id"), new_html, original_html, settings.params);
  217. editing = false;
  218. click_count = 0;
  219. if (html) {
  220. // put the newly updated info into the original element
  221. original_element.html(html || new_html);
  222. } else {
  223. // failure; put original back
  224. alert("Failed to save value: " + new_html);
  225. original_element.html(original_html);
  226. }
  227. } else if (settings.value_required && new_html == "") {
  228. editing = false;
  229. click_count = 0;
  230. original_element.html(original_html);
  231. alert("Error: You must enter a value to save this field");
  232. } else {
  233. jQuery.ajax({
  234. url: settings.url,
  235. type: "POST",
  236. data: settings.update_value + '=' + new_html + '&' + settings.element_id + '=' +
  237. original_element.attr("id") + settings.params +
  238. '&' + settings.original_html + '=' + original_html,
  239. dataType: "html",
  240. complete: function(request){
  241. editing = false;
  242. click_count = 0;
  243. },
  244. success: function(html){
  245. // if the text returned by the server is empty,
  246. // put a marker as text in the original element
  247. var new_text = html || settings.default_text;
  248. // put the newly updated info into the original element
  249. original_element.html(new_text);
  250. if (settings.success) settings.success(html, original_element);
  251. },
  252. error: function(request) {
  253. original_element.html(original_html);
  254. if (settings.error) settings.error(request, original_element);
  255. }
  256. });
  257. }
  258. return false;
  259. });
  260. }//END- if(click_count == 1) -END
  261. });
  262. });
  263. };