Elgg  Version 2.3
jquery.jeditable.js
Go to the documentation of this file.
1 /*
2  * Jeditable - jQuery in place edit plugin
3  *
4  * Copyright (c) 2006-2013 Mika Tuupola, Dylan Verheul
5  *
6  * Licensed under the MIT license:
7  * http://www.opensource.org/licenses/mit-license.php
8  *
9  * Project home:
10  * http://www.appelsiini.net/projects/jeditable
11  *
12  * Based on editable by Dylan Verheul <dylan_at_dyve.net>:
13  * http://www.dyve.net/jquery/?editable
14  *
15  */
16 
60 (function($) {
61 
62  $.fn.editable = function(target, options) {
63 
64  if ('disable' == target) {
65  $(this).data('disabled.editable', true);
66  return;
67  }
68  if ('enable' == target) {
69  $(this).data('disabled.editable', false);
70  return;
71  }
72  if ('destroy' == target) {
73  $(this)
74  .unbind($(this).data('event.editable'))
75  .removeData('disabled.editable')
76  .removeData('event.editable');
77  return;
78  }
79 
80  var settings = $.extend({}, $.fn.editable.defaults, {target:target}, options);
81 
82  /* setup some functions */
83  var plugin = $.editable.types[settings.type].plugin || function() { };
84  var submit = $.editable.types[settings.type].submit || function() { };
85  var buttons = $.editable.types[settings.type].buttons
86  || $.editable.types['defaults'].buttons;
87  var content = $.editable.types[settings.type].content
88  || $.editable.types['defaults'].content;
89  var element = $.editable.types[settings.type].element
90  || $.editable.types['defaults'].element;
91  var reset = $.editable.types[settings.type].reset
92  || $.editable.types['defaults'].reset;
93  var callback = settings.callback || function() { };
94  var onedit = settings.onedit || function() { };
95  var onsubmit = settings.onsubmit || function() { };
96  var onreset = settings.onreset || function() { };
97  var onerror = settings.onerror || reset;
98 
99  /* Show tooltip. */
100  if (settings.tooltip) {
101  $(this).attr('title', settings.tooltip);
102  }
103 
104  settings.autowidth = 'auto' == settings.width;
105  settings.autoheight = 'auto' == settings.height;
106 
107  return this.each(function() {
108 
109  /* Save this to self because this changes when scope changes. */
110  var self = this;
111 
112  /* Inlined block elements lose their width and height after first edit. */
113  /* Save them for later use as workaround. */
114  var savedwidth = $(self).width();
115  var savedheight = $(self).height();
116 
117  /* Save so it can be later used by $.editable('destroy') */
118  $(this).data('event.editable', settings.event);
119 
120  /* If element is empty add something clickable (if requested) */
121  if (!$.trim($(this).html())) {
122  $(this).html(settings.placeholder);
123  }
124 
125  $(this).bind(settings.event, function(e) {
126 
127  /* Abort if element is disabled. */
128  if (true === $(this).data('disabled.editable')) {
129  return;
130  }
131 
132  /* Prevent throwing an exeption if edit field is clicked again. */
133  if (self.editing) {
134  return;
135  }
136 
137  /* Abort if onedit hook returns false. */
138  if (false === onedit.apply(this, [settings, self])) {
139  return;
140  }
141 
142  /* Prevent default action and bubbling. */
143  e.preventDefault();
144  e.stopPropagation();
145 
146  /* Remove tooltip. */
147  if (settings.tooltip) {
148  $(self).removeAttr('title');
149  }
150 
151  /* Figure out how wide and tall we are, saved width and height. */
152  /* Workaround for http://dev.jquery.com/ticket/2190 */
153  if (0 == $(self).width()) {
154  settings.width = savedwidth;
155  settings.height = savedheight;
156  } else {
157  if (settings.width != 'none') {
158  settings.width =
159  settings.autowidth ? $(self).width() : settings.width;
160  }
161  if (settings.height != 'none') {
162  settings.height =
163  settings.autoheight ? $(self).height() : settings.height;
164  }
165  }
166 
167  /* Remove placeholder text, replace is here because of IE. */
168  if ($(this).html().toLowerCase().replace(/(;|"|\/)/g, '') ==
169  settings.placeholder.toLowerCase().replace(/(;|"|\/)/g, '')) {
170  $(this).html('');
171  }
172 
173  self.editing = true;
174  self.revert = $(self).html();
175  $(self).html('');
176 
177  /* Create the form object. */
178  var form = $('<form />');
179 
180  /* Apply css or style or both. */
181  if (settings.cssclass) {
182  if ('inherit' == settings.cssclass) {
183  form.attr('class', $(self).attr('class'));
184  } else {
185  form.attr('class', settings.cssclass);
186  }
187  }
188 
189  if (settings.style) {
190  if ('inherit' == settings.style) {
191  form.attr('style', $(self).attr('style'));
192  /* IE needs the second line or display wont be inherited. */
193  form.css('display', $(self).css('display'));
194  } else {
195  form.attr('style', settings.style);
196  }
197  }
198 
199  /* Add main input element to form and store it in input. */
200  var input = element.apply(form, [settings, self]);
201 
202  /* Set input content via POST, GET, given data or existing value. */
203  var input_content;
204 
205  if (settings.loadurl) {
206  var t = setTimeout(function() {
207  input.disabled = true;
208  content.apply(form, [settings.loadtext, settings, self]);
209  }, 100);
210 
211  var loaddata = {};
212  loaddata[settings.id] = self.id;
213  if ($.isFunction(settings.loaddata)) {
214  $.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));
215  } else {
216  $.extend(loaddata, settings.loaddata);
217  }
218  $.ajax({
219  type : settings.loadtype,
220  url : settings.loadurl,
221  data : loaddata,
222  async : false,
223  success: function(result) {
224  window.clearTimeout(t);
225  input_content = result;
226  input.disabled = false;
227  }
228  });
229  } else if (settings.data) {
230  input_content = settings.data;
231  if ($.isFunction(settings.data)) {
232  input_content = settings.data.apply(self, [self.revert, settings]);
233  }
234  } else {
235  input_content = self.revert;
236  }
237  content.apply(form, [input_content, settings, self]);
238 
239  input.attr('name', settings.name);
240 
241  /* Add buttons to the form. */
242  buttons.apply(form, [settings, self]);
243 
244  /* Add created form to self. */
245  $(self).append(form);
246 
247  /* Attach 3rd party plugin if requested. */
248  plugin.apply(form, [settings, self]);
249 
250  /* Focus to first visible form element. */
251  $(':input:visible:enabled:first', form).focus();
252 
253  /* Highlight input contents when requested. */
254  if (settings.select) {
255  input.select();
256  }
257 
258  /* discard changes if pressing esc */
259  input.keydown(function(e) {
260  if (e.keyCode == 27) {
261  e.preventDefault();
262  reset.apply(form, [settings, self]);
263  }
264  });
265 
266  /* Discard, submit or nothing with changes when clicking outside. */
267  /* Do nothing is usable when navigating with tab. */
268  var t;
269  if ('cancel' == settings.onblur) {
270  input.blur(function(e) {
271  /* Prevent canceling if submit was clicked. */
272  t = setTimeout(function() {
273  reset.apply(form, [settings, self]);
274  }, 500);
275  });
276  } else if ('submit' == settings.onblur) {
277  input.blur(function(e) {
278  /* Prevent double submit if submit was clicked. */
279  t = setTimeout(function() {
280  form.submit();
281  }, 200);
282  });
283  } else if ($.isFunction(settings.onblur)) {
284  input.blur(function(e) {
285  settings.onblur.apply(self, [input.val(), settings]);
286  });
287  } else {
288  input.blur(function(e) {
289  /* TODO: maybe something here */
290  });
291  }
292 
293  form.submit(function(e) {
294 
295  if (t) {
296  clearTimeout(t);
297  }
298 
299  /* Do no submit. */
300  e.preventDefault();
301 
302  /* Call before submit hook. */
303  /* If it returns false abort submitting. */
304  if (false !== onsubmit.apply(form, [settings, self])) {
305  /* Custom inputs call before submit hook. */
306  /* If it returns false abort submitting. */
307  if (false !== submit.apply(form, [settings, self])) {
308 
309  /* Check if given target is function */
310  if ($.isFunction(settings.target)) {
311  var str = settings.target.apply(self, [input.val(), settings]);
312  $(self).html(str);
313  self.editing = false;
314  callback.apply(self, [self.innerHTML, settings]);
315  /* TODO: this is not dry */
316  if (!$.trim($(self).html())) {
317  $(self).html(settings.placeholder);
318  }
319  } else {
320  /* Add edited content and id of edited element to POST. */
321  var submitdata = {};
322  submitdata[settings.name] = input.val();
323  submitdata[settings.id] = self.id;
324  /* Add extra data to be POST:ed. */
325  if ($.isFunction(settings.submitdata)) {
326  $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings]));
327  } else {
328  $.extend(submitdata, settings.submitdata);
329  }
330 
331  /* Quick and dirty PUT support. */
332  if ('PUT' == settings.method) {
333  submitdata['_method'] = 'put';
334  }
335 
336  /* Show the saving indicator. */
337  $(self).html(settings.indicator);
338 
339  /* Defaults for ajaxoptions. */
340  var ajaxoptions = {
341  type : 'POST',
342  data : submitdata,
343  dataType: 'html',
344  url : settings.target,
345  success : function(result, status) {
346  if (ajaxoptions.dataType == 'html') {
347  $(self).html(result);
348  }
349  self.editing = false;
350  callback.apply(self, [result, settings]);
351  if (!$.trim($(self).html())) {
352  $(self).html(settings.placeholder);
353  }
354  },
355  error : function(xhr, status, error) {
356  onerror.apply(form, [settings, self, xhr]);
357  }
358  };
359 
360  /* Override with what is given in settings.ajaxoptions. */
361  $.extend(ajaxoptions, settings.ajaxoptions);
362  $.ajax(ajaxoptions);
363 
364  }
365  }
366  }
367 
368  /* Show tooltip again. */
369  $(self).attr('title', settings.tooltip);
370 
371  return false;
372  });
373  });
374 
375  /* Privileged methods */
376  this.reset = function(form) {
377  /* Prevent calling reset twice when blurring. */
378  if (this.editing) {
379  /* Before reset hook, if it returns false abort reseting. */
380  if (false !== onreset.apply(form, [settings, self])) {
381  $(self).html(self.revert);
382  self.editing = false;
383  if (!$.trim($(self).html())) {
384  $(self).html(settings.placeholder);
385  }
386  /* Show tooltip again. */
387  if (settings.tooltip) {
388  $(self).attr('title', settings.tooltip);
389  }
390  }
391  }
392  };
393  });
394 
395  };
396 
397 
398  $.editable = {
399  types: {
400  defaults: {
401  element : function(settings, original) {
402  var input = $('<input type="hidden"></input>');
403  $(this).append(input);
404  return(input);
405  },
406  content : function(string, settings, original) {
407  $(':input:first', this).val(string);
408  },
409  reset : function(settings, original) {
410  original.reset(this);
411  },
412  buttons : function(settings, original) {
413  var form = this;
414  if (settings.submit) {
415  /* If given html string use that. */
416  if (settings.submit.match(/>$/)) {
417  var submit = $(settings.submit).click(function() {
418  if (submit.attr("type") != "submit") {
419  form.submit();
420  }
421  });
422  /* Otherwise use button with given string as text. */
423  } else {
424  var submit = $('<button type="submit" />');
425  submit.html(settings.submit);
426  }
427  $(this).append(submit);
428  }
429  if (settings.cancel) {
430  /* If given html string use that. */
431  if (settings.cancel.match(/>$/)) {
432  var cancel = $(settings.cancel);
433  /* otherwise use button with given string as text */
434  } else {
435  var cancel = $('<button type="cancel" />');
436  cancel.html(settings.cancel);
437  }
438  $(this).append(cancel);
439 
440  $(cancel).click(function(event) {
441  if ($.isFunction($.editable.types[settings.type].reset)) {
442  var reset = $.editable.types[settings.type].reset;
443  } else {
444  var reset = $.editable.types['defaults'].reset;
445  }
446  reset.apply(form, [settings, original]);
447  return false;
448  });
449  }
450  }
451  },
452  text: {
453  element : function(settings, original) {
454  var input = $('<input />');
455  if (settings.width != 'none') { input.width(settings.width); }
456  if (settings.height != 'none') { input.height(settings.height); }
457  /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
458  //input[0].setAttribute('autocomplete','off');
459  input.attr('autocomplete','off');
460  $(this).append(input);
461  return(input);
462  }
463  },
464  textarea: {
465  element : function(settings, original) {
466  var textarea = $('<textarea />');
467  if (settings.rows) {
468  textarea.attr('rows', settings.rows);
469  } else if (settings.height != "none") {
470  textarea.height(settings.height);
471  }
472  if (settings.cols) {
473  textarea.attr('cols', settings.cols);
474  } else if (settings.width != "none") {
475  textarea.width(settings.width);
476  }
477  $(this).append(textarea);
478  return(textarea);
479  }
480  },
481  select: {
482  element : function(settings, original) {
483  var select = $('<select />');
484  $(this).append(select);
485  return(select);
486  },
487  content : function(data, settings, original) {
488  /* If it is string assume it is json. */
489  if (String == data.constructor) {
490  eval ('var json = ' + data);
491  } else {
492  /* Otherwise assume it is a hash already. */
493  var json = data;
494  }
495  for (var key in json) {
496  if (!json.hasOwnProperty(key)) {
497  continue;
498  }
499  if ('selected' == key) {
500  continue;
501  }
502  var option = $('<option />').val(key).append(json[key]);
503  $('select', this).append(option);
504  }
505  /* Loop option again to set selected. IE needed this... */
506  $('select', this).children().each(function() {
507  if ($(this).val() == json['selected'] ||
508  $(this).text() == $.trim(original.revert)) {
509  $(this).attr('selected', 'selected');
510  }
511  });
512  /* Submit on change if no submit button defined. */
513  if (!settings.submit) {
514  var form = this;
515  $('select', this).change(function() {
516  form.submit();
517  });
518  }
519  }
520  }
521  },
522 
523  /* Add new input type */
524  addInputType: function(name, input) {
525  $.editable.types[name] = input;
526  }
527  };
528 
529  /* Publicly accessible defaults. */
530  $.fn.editable.defaults = {
531  name : 'value',
532  id : 'id',
533  type : 'text',
534  width : 'auto',
535  height : 'auto',
536  event : 'click.editable',
537  onblur : 'cancel',
538  loadtype : 'GET',
539  loadtext : 'Loading...',
540  placeholder: 'Click to edit',
541  loaddata : {},
542  submitdata : {},
543  ajaxoptions: {}
544  };
545 
546 })(jQuery);
fn editable defaults
elgg message elgg state error
Definition: admin.css.php:247
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the original
Definition: GPL-LICENSE.txt:43
line height
Definition: admin.css.php:82
function editable
html
Definition: admin.css.php:36
elgg form settings
Definition: admin.css.php:627
elgg button cancel
Definition: admin.css.php:590
elgg button submit
Definition: admin.css.php:578
list style type
Definition: admin.css.php:808
elgg river item form
select
Definition: admin.css.php:528
function elgg combo checkbox click(function(){if($(this).is(':checked')){$(this).prev().attr('disabled', true);$(this).prev().val('');}else{$(this).prev().attr('disabled', false);}})
elgg input text
Definition: admin.css.php:505
elgg isFunction
Check if the value is a function.
Definition: elgglib.js:64
min width
Definition: admin.css.php:166
elgg message elgg state success
Definition: admin.css.php:252
$site name
if(!$site) if(!($site instanceof ElggSite)) $site url
elgg table input[type=checkbox]
Definition: admin.css.php:404
elgg widget content
Definition: admin.css.php:1305
elgg widget placeholder
Definition: admin.css.php:1308