on_the_spot 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);