on_the_spot 1.1.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 370318b36103fa6ec091d79b7242dbc966526af7
4
- data.tar.gz: 68b85da5d3b5b5f8ad7de4a1487a5ec851b3f635
3
+ metadata.gz: b529c0ec359d065b5be58926383c947ecd89b40f
4
+ data.tar.gz: f4b5c500c36945091220524c621814e7f8129d2e
5
5
  SHA512:
6
- metadata.gz: 71d2138193d6da19a31f66a50e4e93be09976aa4299271047e1ee75aa93aa3d73ed4423167684258b0f754391a1817fe4687efe1b2bcfcc6370d9ad07ac91176
7
- data.tar.gz: 029d0d28b854371b7b15d91f8f14c380698076fc523aceb7d5426a6824511cd59185189a9f8c6c92c7bdcb48d509fe9fb27b5795c9f42e3749de69a3d300c9a7
6
+ metadata.gz: 54be6beb41950cdcb7de401b73ec1ab66ecd471960e06d4626818426ec1f942b51614b3fcca3a1c637e6f5d3ab501e3d3a5a8757bbd89d8e9238efd8e5a627cf
7
+ data.tar.gz: f749c615ed9b9a2e8ddc4af6f4498df88f4f357a26727d056590b77023a46b6eac01e6562679b72dc22e41e42aa9ef5a35ba298746975625a059c1203633535c
@@ -1,5 +1,5 @@
1
1
  rvm:
2
- - 1.9.3
3
- - 2.0.0
4
- - 2.2.1
5
- - rbx
2
+ - 2.2.10
3
+ - 2.3.7
4
+ - 2.4.1
5
+ - 2.4.2
data/Gemfile CHANGED
@@ -6,7 +6,7 @@ group :test do
6
6
  gem "jeweler"
7
7
  gem "json_pure"
8
8
  gem "rspec", ">= 2.6.0"
9
- gem "rails", ">=3.0.9"
9
+ gem "rails", "~> 4.2.0"
10
10
  gem 'test-unit-rails'
11
11
  gem "sqlite3-ruby", :require => "sqlite3" #gem "rcov"
12
12
  gem "simplecov", :require => false
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.1.2
@@ -0,0 +1,804 @@
1
+ /**
2
+ * @file Jeditable - jQuery in place edit plugin
3
+ * @home https://github.com/NicolasCARPi/jquery_jeditable
4
+ * @author Mika Tuupola, Dylan Verheul, Nicolas CARPi
5
+ * @copyright © 2006 Mika Tuupola, Dylan Verheul, Nicolas CARPi
6
+ * @licence MIT (see LICENCE file)
7
+ * @name Jquery-jeditable
8
+ * @type jQuery
9
+ *
10
+ * @param {String|Function} target - URL or Function to send edited content to. Can also be 'disable', 'enable', or 'destroy'
11
+ * @param {Object} [options] - Additional options
12
+ * @param {Object} [options.ajaxoptions] - jQuery Ajax options. See https://api.jquery.com/jQuery.ajax/
13
+ * @param {Function} [options.before] - Function to be executed before going into edit mode
14
+ * @param {Function} [options.callback] - function(result, settings, submitdata) Function to run after submitting edited content
15
+ * @param {String} [options.cancel] - Cancel button value, empty means no button
16
+ * @param {String} [options.cancelcssclass] - CSS class to apply to cancel button
17
+ * @param {Number} [options.cols] - Number of columns if using textarea
18
+ * @param {String} [options.cssclass] - CSS class to apply to input form; use 'inherit' to copy from parent
19
+ * @param {String} [options.inputcssclass] - CSS class to apply to input. 'inherit' to copy from parent
20
+ * @param {String|Function} [options.data] - Content loaded in the form
21
+ * @param {String} [options.event='click'] - jQuery event such as 'click' of 'dblclick'. See https://api.jquery.com/category/events/
22
+ * @param {String} [options.formid] - Give an id to the form that is produced
23
+ * @param {String|Number} [options.height='auto'] - Height of the element in pixels or 'auto' or 'none'
24
+ * @param {String} [options.id='id'] - POST parameter name of edited div id
25
+ * @param {String} [options.indicator] - Indicator html to show when saving
26
+ * @param {String} [options.label] - Label for the form
27
+ * @param {String} [options.list] - HTML5 attribute for text input. Will suggest from a datalist with id of the list option
28
+ * @param {String|Function} [options.loaddata] - Extra parameters to pass when fetching content before editing
29
+ * @param {String} [options.loadtext='Loading…'] - Text to display while loading external content
30
+ * @param {String} [options.loadtype='GET'] - Request type for loadurl (GET or POST)
31
+ * @param {String} [options.loadurl] - URL to fetch input content before editing
32
+ * @param {Number} [options.max] - Maximum value for number type
33
+ * @param {String} [options.maxlength] - The maximum number of character in the text field
34
+ * @param {String} [options.method] - Method to use to send edited content (POST or PUT)
35
+ * @param {Number} [options.min] - Mininum value for number type
36
+ * @param {Boolean} [options.multiple] - Allow multiple selections in a select input
37
+ * @param {String} [options.name='value'] - POST parameter name of edited content
38
+ * @param {String|Function} [options.onblur='cancel'] - Use 'cancel', 'submit', 'ignore' or function. If function returns false, the form is cancelled.
39
+ * @param {Function} [options.onedit] - function triggered upon edition; will cancel edition if it returns false
40
+ * @param {Function} [options.onerror] - function(settings, original, xhr) { ... } called on error
41
+ * @param {Function} [options.onreset] - function(settings, original) { ... } called before reset
42
+ * @param {Function} [options.onsubmit] - function(settings, original) { ... } called before submit
43
+ * @param {String} [options.pattern] - HTML5 attribute for text or URL input
44
+ * @param {String} [options.placeholder='Click to edit'] - Placeholder text or html to insert when element is empty
45
+ * @param {Number} [options.rows] - number of rows if using textarea
46
+ * @param {Boolean} [options.select] - When true text is selected
47
+ * @param {Function} [options.showfn]- Function that can animate the element when switching to edit mode
48
+ * @param {String} [options.size] - The size of the text field
49
+ * @param {Number} [options.step] - Step size for number type
50
+ * @param {String} [options.style] - Style to apply to input form; 'inherit' to copy from parent
51
+ * @param {String} [options.submit] - submit button value, empty means no button
52
+ * @param {String} [options.submitcssclass] - CSS class to apply to submit button
53
+ * @param {Object|Function} [options.submitdata] - Extra parameters to send when submitting edited content. function(revert, settings, submitdata)
54
+ * @param {String} [options.tooltip] - Tooltip text that appears on hover (via title attribute)
55
+ * @param {String} [options.type='text'] - text, textarea, select, email, number, url (or any 3rd party input type)
56
+ * @param {String|Number} [options.width='auto'] - The width of the element in pixels or 'auto' or 'none'
57
+ *
58
+ * @example <caption>Simple usage example:</caption>
59
+ * $(".editable").editable("save.php", {
60
+ * cancel : 'Cancel',
61
+ * submit : 'Save',
62
+ * tooltip : "Click to edit...",
63
+ * });
64
+ */
65
+ (function($) {
66
+
67
+ 'use strict';
68
+
69
+ // Keyboard accessibility/WAI-ARIA - allow users to navigate to an editable element using TAB/Shift+TAB
70
+ $.fn.editableAriaShim = function () {
71
+ this.attr({
72
+ role: 'button',
73
+ tabindex: 0
74
+ });
75
+ return this; // <-- object chaining.
76
+ };
77
+
78
+ // EDITABLE function
79
+ $.fn.editable = function(target, options) {
80
+
81
+ if ('disable' === target) {
82
+ $(this).data('disabled.editable', true);
83
+ return;
84
+ }
85
+ if ('enable' === target) {
86
+ $(this).data('disabled.editable', false);
87
+ return;
88
+ }
89
+ if ('destroy' === target) {
90
+ $(this)
91
+ .unbind($(this).data('event.editable'))
92
+ .removeData('disabled.editable')
93
+ .removeData('event.editable');
94
+ return;
95
+ }
96
+ var settings = $.extend({}, $.fn.editable.defaults, {target:target}, options);
97
+
98
+ /* setup some functions */
99
+ var plugin = $.editable.types[settings.type].plugin || function() { };
100
+ var submit = $.editable.types[settings.type].submit || function() { };
101
+ var buttons = $.editable.types[settings.type].buttons || $.editable.types.defaults.buttons;
102
+ var content = $.editable.types[settings.type].content || $.editable.types.defaults.content;
103
+ var element = $.editable.types[settings.type].element || $.editable.types.defaults.element;
104
+ var reset = $.editable.types[settings.type].reset || $.editable.types.defaults.reset;
105
+ var destroy = $.editable.types[settings.type].destroy || $.editable.types.defaults.destroy;
106
+ var callback = settings.callback || function() { };
107
+ var intercept = settings.intercept || function(s) { return s; };
108
+ var onedit = settings.onedit || function() { };
109
+ var onsubmit = settings.onsubmit || function() { };
110
+ var onreset = settings.onreset || function() { };
111
+ var onerror = settings.onerror || reset;
112
+ var before = settings.before || false;
113
+
114
+ // TOOLTIP
115
+ if (settings.tooltip) {
116
+ $(this).attr('title', settings.tooltip);
117
+ }
118
+
119
+ return this.each(function() {
120
+
121
+ /* Save this to self because this changes when scope changes. */
122
+ var self = this;
123
+
124
+ /* Save so it can be later used by $.editable('destroy') */
125
+ $(this).data('event.editable', settings.event);
126
+
127
+ /* If element is empty add something clickable (if requested) */
128
+ if (!$.trim($(this).html())) {
129
+ $(this).html(settings.placeholder);
130
+ }
131
+
132
+ if ('destroy' === target) {
133
+ destroy.apply($(this).find('form'), [settings, self]);
134
+ return;
135
+ }
136
+
137
+ // EVENT IS FIRED
138
+ $(this).bind(settings.event, function(e) {
139
+
140
+ /* Abort if element is disabled. */
141
+ if (true === $(this).data('disabled.editable')) {
142
+ return;
143
+ }
144
+
145
+ // do nothing if user press Tab again, just go to next element, not into edit mode
146
+ if (e.keyCode === 9) {
147
+ return;
148
+ }
149
+
150
+ /* Prevent throwing an exeption if edit field is clicked again. */
151
+ if (self.editing) {
152
+ return;
153
+ }
154
+
155
+ /* Abort if onedit hook returns false. */
156
+ if (false === onedit.apply(this, [settings, self, e])) {
157
+ return;
158
+ }
159
+
160
+ /* execute the before function if any was specified */
161
+ if (settings.before && jQuery.isFunction(settings.before)) {
162
+ settings.before();
163
+ } else if (settings.before && !jQuery.isFunction(settings.before)) {
164
+ throw "The 'before' option needs to be provided as a function!";
165
+ }
166
+
167
+ /* Prevent default action and bubbling. */
168
+ e.preventDefault();
169
+ e.stopPropagation();
170
+
171
+ /* Remove tooltip. */
172
+ if (settings.tooltip) {
173
+ $(self).removeAttr('title');
174
+ }
175
+
176
+ /* Remove placeholder text, replace is here because of IE. */
177
+ if ($(this).html().toLowerCase().replace(/(;|"|\/)/g, '') ===
178
+ settings.placeholder.toLowerCase().replace(/(;|"|\/)/g, '')) {
179
+ $(this).html('');
180
+ }
181
+
182
+ self.editing = true;
183
+ self.revert = $(self).text();
184
+ $(self).html('');
185
+
186
+ /* Create the form object. */
187
+ var form = $('<form />');
188
+
189
+ /* Apply css or style or both. */
190
+ if (settings.cssclass) {
191
+ if ('inherit' === settings.cssclass) {
192
+ form.attr('class', $(self).attr('class'));
193
+ } else {
194
+ form.attr('class', settings.cssclass);
195
+ }
196
+ }
197
+
198
+ if (settings.style) {
199
+ if ('inherit' === settings.style) {
200
+ form.attr('style', $(self).attr('style'));
201
+ /* IE needs the second line or display wont be inherited. */
202
+ form.css('display', $(self).css('display'));
203
+ } else {
204
+ form.attr('style', settings.style);
205
+ }
206
+ }
207
+
208
+ // add a label if it exists
209
+ if (settings.label) {
210
+ form.append('<label>' + settings.label + '</label>');
211
+ }
212
+
213
+ // add an ID to the form
214
+ if (settings.formid) {
215
+ form.attr('id', settings.formid);
216
+ }
217
+
218
+ /* Add main input element to form and store it in input. */
219
+ var input = element.apply(form, [settings, self]);
220
+
221
+ if (settings.inputcssclass) {
222
+ if ('inherit' === settings.inputcssclass) {
223
+ input.attr('class', $(self).attr('class'));
224
+ } else {
225
+ input.attr('class', settings.inputcssclass);
226
+ }
227
+ }
228
+
229
+ /* Set input content via POST, GET, given data or existing value. */
230
+ var input_content;
231
+
232
+ // timeout function
233
+ var t;
234
+ var is_submitting = false;
235
+
236
+ if (settings.loadurl) {
237
+ t = self.setTimeout(function() {
238
+ input.disabled = true;
239
+ }, 100);
240
+ $(self).html(settings.loadtext);
241
+
242
+ var loaddata = {};
243
+ loaddata[settings.id] = self.id;
244
+ if ($.isFunction(settings.loaddata)) {
245
+ $.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));
246
+ } else {
247
+ $.extend(loaddata, settings.loaddata);
248
+ }
249
+ $.ajax({
250
+ type : settings.loadtype,
251
+ url : settings.loadurl,
252
+ data : loaddata,
253
+ async: false,
254
+ cache : false,
255
+ success: function(result) {
256
+ self.clearTimeout(t);
257
+ input_content = result;
258
+ input.disabled = false;
259
+ }
260
+ });
261
+ } else if (settings.data) {
262
+ input_content = settings.data;
263
+ if ($.isFunction(settings.data)) {
264
+ input_content = settings.data.apply(self, [self.revert, settings]);
265
+ }
266
+ } else {
267
+ input_content = self.revert;
268
+ }
269
+ content.apply(form, [input_content, settings, self]);
270
+
271
+ input.attr('name', settings.name);
272
+
273
+ /* adjust the width of the element to account for the margin/padding/border */
274
+ if (settings.width !== 'none') {
275
+ var adj_width = settings.width - (input.outerWidth(true) - settings.width);
276
+ input.width(adj_width);
277
+ }
278
+
279
+ /* Add buttons to the form. */
280
+ buttons.apply(form, [settings, self]);
281
+
282
+ /* Add created form to self. */
283
+ if (settings.showfn && $.isFunction(settings.showfn)) {
284
+ form.hide();
285
+ }
286
+
287
+ // clear the loadtext that we put here before
288
+ $(self).html('');
289
+
290
+ $(self).append(form);
291
+
292
+ // execute the showfn
293
+ if (settings.showfn && $.isFunction(settings.showfn)) {
294
+ settings.showfn(form);
295
+ }
296
+
297
+ /* Attach 3rd party plugin if requested. */
298
+ plugin.apply(form, [settings, self]);
299
+
300
+ /* Focus to first visible form element. */
301
+ form.find(':input:visible:enabled:first').focus();
302
+
303
+ /* Highlight input contents when requested. */
304
+ if (settings.select) {
305
+ input.select();
306
+ }
307
+
308
+ /* discard changes if pressing esc */
309
+ input.keydown(function(e) {
310
+ if (e.keyCode === 27) {
311
+ e.preventDefault();
312
+ reset.apply(form, [settings, self]);
313
+ }
314
+ });
315
+
316
+ /* Discard, submit or nothing with changes when clicking outside. */
317
+ /* Do nothing is usable when navigating with tab. */
318
+ if ('cancel' === settings.onblur) {
319
+ input.blur(function(e) {
320
+ /* Prevent canceling if submit was clicked. */
321
+ t = self.setTimeout(function() {
322
+ reset.apply(form, [settings, self]);
323
+ }, 500);
324
+ });
325
+ } else if ('submit' === settings.onblur) {
326
+ input.blur(function(e) {
327
+ /* Prevent double submit if submit was clicked. */
328
+ console.log("BLUR submitting");
329
+ form.submit();
330
+ });
331
+ } else if ($.isFunction(settings.onblur)) {
332
+ input.blur(function(e) {
333
+ // reset the form if the onblur function returns false
334
+ if (false === settings.onblur.apply(self, [input.val(), settings, form])) {
335
+ reset.apply(form, [settings, self]);
336
+ }
337
+ });
338
+ }
339
+
340
+ form.submit(function(e) {
341
+ console.log("Form.submit");
342
+
343
+ /* Do no submit. */
344
+ e.preventDefault();
345
+ e.stopPropagation();
346
+
347
+ if (is_submitting) {
348
+ console.log("...we are already submitting .. stop!");
349
+ return false;
350
+ } else {
351
+ is_submitting = true;
352
+ }
353
+
354
+ if (t) {
355
+ self.clearTimeout(t);
356
+ }
357
+
358
+ /* Call before submit hook. */
359
+ /* If it returns false abort submitting. */
360
+ if (false !== onsubmit.apply(form, [settings, self])) {
361
+ /* Custom inputs call before submit hook. */
362
+ /* If it returns false abort submitting. */
363
+ if (false !== submit.apply(form, [settings, self])) {
364
+
365
+ /* Check if given target is function */
366
+ if ($.isFunction(settings.target)) {
367
+ /* Callback function to handle the target reponse */
368
+ var responseHandler = function(value) {
369
+ $(self).html(value);
370
+ self.editing = false;
371
+ callback.apply(self, [self.innerHTML, settings]);
372
+ if (!$.trim($(self).html())) {
373
+ $(self).html(settings.placeholder);
374
+ }
375
+ };
376
+ /* Call the user target function */
377
+ var userTarget = settings.target.apply(self, [input.val(), settings, responseHandler]);
378
+ /* Handle the target function return for compatibility */
379
+ if (false !== userTarget && undefined !== userTarget) {
380
+ responseHandler(userTarget);
381
+ }
382
+
383
+ } else {
384
+ /* Add edited content and id of edited element to POST. */
385
+ var submitdata = {};
386
+ submitdata[settings.name] = input.val();
387
+ submitdata[settings.id] = self.id;
388
+ /* Add extra data to be POST:ed. */
389
+ if ($.isFunction(settings.submitdata)) {
390
+ $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings, submitdata]));
391
+ } else {
392
+ $.extend(submitdata, settings.submitdata);
393
+ }
394
+
395
+ /* Quick and dirty PUT support. */
396
+ if ('PUT' === settings.method) {
397
+ submitdata._method = 'put';
398
+ }
399
+
400
+ // SHOW INDICATOR
401
+ $(self).html(settings.indicator);
402
+
403
+ /* Defaults for ajaxoptions. */
404
+ var ajaxoptions = {
405
+ type : 'POST',
406
+ data : submitdata,
407
+ dataType: 'html',
408
+ url : settings.target,
409
+ success : function(result, status) {
410
+
411
+ // INTERCEPT
412
+ result = intercept.apply(self, [result, status]);
413
+
414
+ if (ajaxoptions.dataType === 'html') {
415
+ $(self).html(result);
416
+ }
417
+ self.editing = false;
418
+ callback.apply(self, [result, settings, submitdata]);
419
+ if (!$.trim($(self).html())) {
420
+ $(self).html(settings.placeholder);
421
+ }
422
+ },
423
+ error : function(xhr, status, error) {
424
+ onerror.apply(form, [settings, self, xhr]);
425
+ }
426
+ };
427
+
428
+ /* Override with what is given in settings.ajaxoptions. */
429
+ $.extend(ajaxoptions, settings.ajaxoptions);
430
+ $.ajax(ajaxoptions);
431
+ }
432
+ }
433
+ }
434
+
435
+ /* Show tooltip again. */
436
+ $(self).attr('title', settings.tooltip);
437
+ return false;
438
+ });
439
+ });
440
+
441
+ // PRIVILEGED METHODS
442
+
443
+ // RESET
444
+ self.reset = function(form) {
445
+ /* Prevent calling reset twice when blurring. */
446
+ if (self.editing) {
447
+ /* Before reset hook, if it returns false abort reseting. */
448
+ if (false !== onreset.apply(form, [settings, self])) {
449
+ $(self).html(self.revert);
450
+ self.editing = false;
451
+ if (!$.trim($(self).html())) {
452
+ $(self).html(settings.placeholder);
453
+ }
454
+ /* Show tooltip again. */
455
+ if (settings.tooltip) {
456
+ $(self).attr('title', settings.tooltip);
457
+ }
458
+ }
459
+ }
460
+ };
461
+
462
+ // DESTROY
463
+ self.destroy = function(form) {
464
+ $(self)
465
+ .unbind($(self).data('event.editable'))
466
+ .removeData('disabled.editable')
467
+ .removeData('event.editable');
468
+
469
+ self.clearTimeouts();
470
+
471
+ if (self.editing) {
472
+ reset.apply(form, [settings, self]);
473
+ }
474
+ };
475
+
476
+ // CLEARTIMEOUT
477
+ self.clearTimeout = function(t) {
478
+ var timeouts = $(self).data('timeouts');
479
+ clearTimeout(t);
480
+ if(timeouts) {
481
+ var i = timeouts.indexOf(t);
482
+ if(i > -1) {
483
+ timeouts.splice(i, 1);
484
+ if(timeouts.length <= 0) {
485
+ $(self).removeData('timeouts');
486
+ }
487
+ } else {
488
+ console.warn('jeditable clearTimeout could not find timeout '+t);
489
+ }
490
+ }
491
+ };
492
+
493
+ // CLEAR ALL TIMEOUTS
494
+ self.clearTimeouts = function () {
495
+ var timeouts = $(self).data('timeouts');
496
+ if(timeouts) {
497
+ for(var i = 0, n = timeouts.length; i < n; ++i) {
498
+ clearTimeout(timeouts[i]);
499
+ }
500
+ timeouts.length = 0;
501
+ $(self).removeData('timeouts');
502
+ }
503
+ };
504
+
505
+ // SETTIMEOUT
506
+ self.setTimeout = function(callback, time) {
507
+ console.log("SELF :: setTimeout");
508
+ var timeouts = $(self).data('timeouts');
509
+ var t = setTimeout(function() {
510
+ callback();
511
+ self.clearTimeout(t);
512
+ }, time);
513
+ if(!timeouts) {
514
+ timeouts = [];
515
+ $(self).data('timeouts', timeouts);
516
+ }
517
+ timeouts.push(t);
518
+ return t;
519
+ };
520
+ });
521
+ };
522
+
523
+ var _supportInType = function (type) {
524
+ var i = document.createElement('input');
525
+ i.setAttribute('type', type);
526
+ return i.type !== 'text' ? type : 'text';
527
+ };
528
+
529
+
530
+ $.editable = {
531
+ types: {
532
+ defaults: {
533
+ element : function(settings, original) {
534
+ var input = $('<input type="hidden"></input>');
535
+ $(this).append(input);
536
+ return(input);
537
+ },
538
+ content : function(string, settings, original) {
539
+ $(this).find(':input:first').val(string);
540
+ },
541
+ reset : function(settings, original) {
542
+ original.reset(this);
543
+ },
544
+ destroy: function(settings, original) {
545
+ original.destroy(this);
546
+ },
547
+ buttons : function(settings, original) {
548
+ var form = this;
549
+ var submit;
550
+ if (settings.submit) {
551
+ /* If given html string use that. */
552
+ if (settings.submit.match(/>$/)) {
553
+ submit = $(settings.submit).click(function(e) {
554
+ e.stopPropagation();
555
+ e.preventDefault();
556
+ if (submit.attr('type') !== 'submit') {
557
+ console.log("submit button clicked ... ");
558
+ form.submit();
559
+ }
560
+ });
561
+ /* Otherwise use button with given string as text. */
562
+ } else {
563
+ submit = $('<button type="submit" />');
564
+ submit.html(settings.submit);
565
+ if (settings.submitcssclass) {
566
+ submit.addClass(settings.submitcssclass);
567
+ }
568
+ }
569
+ $(this).append(submit);
570
+ }
571
+ if (settings.cancel) {
572
+ var cancel;
573
+ /* If given html string use that. */
574
+ if (settings.cancel.match(/>$/)) {
575
+ cancel = $(settings.cancel);
576
+ /* otherwise use button with given string as text */
577
+ } else {
578
+ cancel = $('<button type="cancel" />');
579
+ cancel.html(settings.cancel);
580
+ if (settings.cancelcssclass) {
581
+ cancel.addClass(settings.cancelcssclass);
582
+ }
583
+ }
584
+ $(this).append(cancel);
585
+
586
+ $(cancel).click(function(event) {
587
+ var reset;
588
+ if ($.isFunction($.editable.types[settings.type].reset)) {
589
+ reset = $.editable.types[settings.type].reset;
590
+ } else {
591
+ reset = $.editable.types.defaults.reset;
592
+ }
593
+ reset.apply(form, [settings, original]);
594
+ return false;
595
+ });
596
+ }
597
+ }
598
+ },
599
+ text: {
600
+ element : function(settings, original) {
601
+ var input = $('<input />').attr({
602
+ autocomplete: 'off',
603
+ list: settings.list,
604
+ maxlength: settings.maxlength,
605
+ pattern: settings.pattern,
606
+ placeholder: settings.placeholder,
607
+ tooltip: settings.tooltip,
608
+ type: 'text'
609
+ });
610
+
611
+ if (settings.width !== 'none') {
612
+ input.css('width', settings.width);
613
+ }
614
+
615
+ if (settings.height !== 'none') {
616
+ input.css('height', settings.height);
617
+ }
618
+
619
+ if (settings.size) {
620
+ input.attr('size', settings.size);
621
+ }
622
+
623
+ if (settings.maxlength) {
624
+ input.attr('maxlength', settings.maxlength);
625
+ }
626
+
627
+ $(this).append(input);
628
+ return(input);
629
+ }
630
+ },
631
+
632
+ // TEXTAREA
633
+ textarea: {
634
+ element : function(settings, original) {
635
+ var textarea = $('<textarea></textarea>');
636
+ if (settings.rows) {
637
+ textarea.attr('rows', settings.rows);
638
+ } else if (settings.height !== 'none') {
639
+ textarea.height(settings.height);
640
+ }
641
+ if (settings.cols) {
642
+ textarea.attr('cols', settings.cols);
643
+ } else if (settings.width !== 'none') {
644
+ textarea.width(settings.width);
645
+ }
646
+
647
+ if (settings.maxlength) {
648
+ textarea.attr('maxlength', settings.maxlength);
649
+ }
650
+
651
+ $(this).append(textarea);
652
+ return(textarea);
653
+ }
654
+ },
655
+
656
+ // SELECT
657
+ select: {
658
+ element : function(settings, original) {
659
+ var select = $('<select />');
660
+
661
+ if (settings.multiple) {
662
+ select.attr('multiple', 'multiple');
663
+ }
664
+
665
+ $(this).append(select);
666
+ return(select);
667
+ },
668
+ content : function(data, settings, original) {
669
+ var json;
670
+ // If it is string assume it is json
671
+ if (String === data.constructor) {
672
+ json = JSON.parse(data);
673
+ } else {
674
+ // Otherwise assume it is a hash already
675
+ json = data;
676
+ }
677
+
678
+ // Create tuples for sorting
679
+ var tuples = [];
680
+ var key;
681
+ for (key in json) {
682
+ tuples.push([key, json[key]]); // Store: [key, value]
683
+ }
684
+ // sort it
685
+ //tuples.sort(function(a, b) {
686
+ // a = a[1];
687
+ // b = b[1];
688
+ // return a < b ? -1 : (a > b ? 1 : 0);
689
+ //});
690
+
691
+ // now add the options to our select
692
+ var option;
693
+ for (var i = 0; i < tuples.length; i++) {
694
+ key = tuples[i][0];
695
+ var value = tuples[i][1];
696
+
697
+ if (!json.hasOwnProperty(key)) {
698
+ continue;
699
+ }
700
+
701
+ if (key !== 'selected') {
702
+ option = $('<option />').val(key).append(value);
703
+ }
704
+
705
+ // add the selected prop if it's the same as original or if the key is 'selected'
706
+ if (json['selected'] === key || key === $.trim(original.revert)) {
707
+ $(option).prop('selected', value);
708
+ }
709
+
710
+ $(this).find('select').append(option);
711
+ }
712
+
713
+ // submit on change if no submit button defined
714
+ if (!settings.submit) {
715
+ var form = this;
716
+ $(this).find('select').change(function() {
717
+ form.submit();
718
+ });
719
+ }
720
+ }
721
+ },
722
+
723
+ // NUMBER
724
+ number: {
725
+ element: function (settings, original) {
726
+ var input = $('<input />').attr({
727
+ maxlength: settings.maxlength,
728
+ placeholder: settings.placeholder,
729
+ min : settings.min,
730
+ max : settings.max,
731
+ step: settings.step,
732
+ tooltip: settings.tooltip,
733
+ type: _supportInType('number')
734
+ });
735
+ if (settings.width !== 'none') {
736
+ input.css('width', settings.width);
737
+ }
738
+ $(this).append(input);
739
+ return input;
740
+ }
741
+ },
742
+
743
+ // EMAIL
744
+ email: {
745
+ element: function (settings, original) {
746
+ var input = $('<input />').attr({
747
+ maxlength: settings.maxlength,
748
+ placeholder: settings.placeholder,
749
+ tooltip: settings.tooltip,
750
+ type: _supportInType('email')
751
+ });
752
+ if (settings.width !== 'none') {
753
+ input.css('width', settings.width);
754
+ }
755
+ $(this).append(input);
756
+ return input;
757
+ }
758
+ },
759
+
760
+ // URL
761
+ url: {
762
+ element: function (settings, original) {
763
+ var input = $('<input />').attr({
764
+ maxlength: settings.maxlength,
765
+ pattern: settings.pattern,
766
+ placeholder: settings.placeholder,
767
+ tooltip: settings.tooltip,
768
+ type: _supportInType('url')
769
+ });
770
+ if (settings.width !== 'none') {
771
+ input.css('width', settings.width);
772
+ }
773
+ $(this).append(input);
774
+ return input;
775
+ }
776
+ }
777
+ },
778
+
779
+ // add new input type
780
+ addInputType: function(name, input) {
781
+ $.editable.types[name] = input;
782
+ }
783
+ };
784
+
785
+ /* Publicly accessible defaults. */
786
+ $.fn.editable.defaults = {
787
+ name : 'value',
788
+ id : 'id',
789
+ type : 'text',
790
+ width : 'auto',
791
+ height : 'auto',
792
+ // Keyboard accessibility - use mouse click OR press any key to enable editing
793
+ event : 'click.editable keydown.editable',
794
+ onblur : 'cancel',
795
+ tooltip : 'Click to edit',
796
+ loadtype : 'GET',
797
+ loadtext : 'Loading...',
798
+ placeholder: 'Click to edit',
799
+ loaddata : {},
800
+ submitdata : {},
801
+ ajaxoptions: {}
802
+ };
803
+
804
+ })(jQuery);