diff --git a/src/editable-form/editable-form.css b/src/editable-form/editable-form.css index 0aacf5a..b5fb43d 100644 --- a/src/editable-form/editable-form.css +++ b/src/editable-form/editable-form.css @@ -88,4 +88,33 @@ font-size: 0.9em; text-decoration: none; text-align: right; -} \ No newline at end of file +} + +.editable-clear-x { + background: url('../img/clear.png') center center no-repeat; + display: block; + width: 13px; + height: 13px; + position: absolute; + right: 7px; + opacity: 0.6; + z-index: 100; +} + +.editable-clear-x:hover { + opacity: 1; +} + +/* +.editable-clear-x1 { + background: url('../img/clear.png') center center no-repeat; + display: inline-block; + zoom: 1; + *display: inline; + width: 13px; + height: 13px; + vertical-align: middle; + position: relative; + margin-left: -20px; +} +*/ \ No newline at end of file diff --git a/src/editable-form/editable-form.js b/src/editable-form/editable-form.js index c97c58d..17d67e5 100644 --- a/src/editable-form/editable-form.js +++ b/src/editable-form/editable-form.js @@ -64,8 +64,8 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc. //render input $.when(this.input.render()) .then($.proxy(function () { - //input - this.$form.find('div.editable-input').append(this.input.$input); + //insert input in form + this.$form.find('div.editable-input').append(this.input.$tpl); //automatically submit inputs when no buttons shown if(!this.options.showbuttons) { @@ -73,9 +73,9 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc. } //"clear" link - if(this.input.$clear) { - this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear)); - } +// if(this.input.$clear) { +// this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear)); +// } //append form to container this.$div.append(this.$form); @@ -83,6 +83,11 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc. //attach 'cancel' handler this.$form.find('.editable-cancel').click($.proxy(this.cancel, this)); + //call postrender to perform actions, required when input is in DOM + if(this.input.postrender) { + this.input.postrender(); + } + if(this.input.error) { this.error(this.input.error); this.$form.find('.editable-submit').attr('disabled', true); diff --git a/src/img/clear.png b/src/img/clear.png new file mode 100644 index 0000000..580b52a Binary files /dev/null and b/src/img/clear.png differ diff --git a/src/inputs-ext/address/address.js b/src/inputs-ext/address/address.js index 0fa31fd..c4f2b78 100644 --- a/src/inputs-ext/address/address.js +++ b/src/inputs-ext/address/address.js @@ -153,11 +153,11 @@ $(function(){ }); Address.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { - tpl: '<div><label><span>City: </span><input type="text" name="city" class="input-small"></label></div>'+ - '<div><label><span>Street: </span><input type="text" name="street" class="input-small"></label></div>'+ - '<div><label><span>Building: </span><input type="text" name="building" class="input-mini"></label></div>', + tpl: '<div class="editable-address"><label><span>City: </span><input type="text" name="city" class="input-small"></label></div>'+ + '<div class="editable-address"><label><span>Street: </span><input type="text" name="street" class="input-small"></label></div>'+ + '<div class="editable-address"><label><span>Building: </span><input type="text" name="building" class="input-mini"></label></div>', - inputclass: 'editable-address' + inputclass: '' }); $.fn.editabletypes.address = Address; diff --git a/src/inputs/abstract.js b/src/inputs/abstract.js index a258001..ec25001 100644 --- a/src/inputs/abstract.js +++ b/src/inputs/abstract.js @@ -20,9 +20,10 @@ To create your own input you can inherit from this class. **/ init: function(type, options, defaults) { this.type = type; - this.options = $.extend({}, defaults, options); - this.$input = null; - this.$clear = null; + this.options = $.extend({}, defaults, options); + this.$tpl = null; //whole tpl as jquery object + this.$input = null; //input as jquery object + this.$clear = null; //clear button this.error = null; }, @@ -32,14 +33,8 @@ To create your own input you can inherit from this class. @method render() **/ render: function() { - this.$input = $(this.options.tpl); - if(this.options.inputclass) { - this.$input.addClass(this.options.inputclass); - } - - if (this.options.placeholder) { - this.$input.attr('placeholder', this.options.placeholder); - } + this.$tpl = $(this.options.tpl); + this.$input = this.$tpl; }, /** diff --git a/src/inputs/checklist.js b/src/inputs/checklist.js index a78ea53..364eca5 100644 --- a/src/inputs/checklist.js +++ b/src/inputs/checklist.js @@ -44,8 +44,13 @@ $(function(){ })) .append($('<span>').text(' '+this.sourceData[i].text)); - $('<div>').append($label).appendTo(this.$input); + $('<div>').append($label).appendTo(this.$tpl); } + + this.$input = this.$tpl.find('input[type="checkbox"]'); + if(this.options.inputclass) { + this.$input.addClass(this.options.inputclass); + } }, value2str: function(value) { @@ -66,10 +71,9 @@ $(function(){ //set checked on required checkboxes value2input: function(value) { - var $checks = this.$input.find('input[type="checkbox"]'); - $checks.removeAttr('checked'); + this.$input.removeAttr('checked'); if($.isArray(value) && value.length) { - $checks.each(function(i, el) { + this.$input.each(function(i, el) { var $el = $(el); // cannot use $.inArray as it performs strict comparison $.each(value, function(j, val){ @@ -85,7 +89,7 @@ $(function(){ input2value: function() { var checked = []; - this.$input.find('input:checked').each(function(i, el) { + this.$input.filter(':checked').each(function(i, el) { checked.push($(el).val()); }); return checked; @@ -105,11 +109,11 @@ $(function(){ }, activate: function() { - this.$input.find('input[type="checkbox"]').first().focus(); + this.$input.first().focus(); }, autosubmit: function() { - this.$input.find('input[type="checkbox"]').on('keydown', function(e){ + this.$input.on('keydown', function(e){ if (e.which === 13) { $(this).closest('form').submit(); } @@ -122,14 +126,14 @@ $(function(){ @property tpl @default <div></div> **/ - tpl:'<div></div>', + tpl:'<div class="editable-checklist"></div>', /** @property inputclass @type string - @default editable-checklist + @default **/ - inputclass: 'editable-checklist', + inputclass: '', /** Separator of values when reading from 'data-value' string diff --git a/src/inputs/date/date.js b/src/inputs/date/date.js index 4d6d8b3..fe68def 100644 --- a/src/inputs/date/date.js +++ b/src/inputs/date/date.js @@ -60,14 +60,19 @@ $(function(){ render: function () { Date.superclass.render.call(this); this.$input.datepicker(this.options.datepicker); - + }, + + postrender: function() { + //"clear" link if(this.options.clear) { this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){ e.preventDefault(); e.stopPropagation(); this.clear(); }, this)); - } + + this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear)); + } }, value2html: function(value, element) { @@ -123,12 +128,12 @@ $(function(){ @property tpl @default <div></div> **/ - tpl:'<div></div>', + tpl:'<div class="editable-date well"></div>', /** @property inputclass - @default editable-date well + @default **/ - inputclass: 'editable-date well', + inputclass: '', /** Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br> Possible tokens are: <code>d, dd, m, mm, yy, yyyy</code> diff --git a/src/inputs/date/datefield.js b/src/inputs/date/datefield.js index dc9c8d6..fd9d495 100644 --- a/src/inputs/date/datefield.js +++ b/src/inputs/date/datefield.js @@ -14,44 +14,41 @@ Automatically shown in inline mode. $.extend(DateField.prototype, { render: function () { - this.$input = $(this.options.tpl); - this.$field = this.$input.find('input'); + this.$tpl = $(this.options.tpl); + this.$input = this.$tpl.find('input'); if(this.options.inputclass) { - this.$field.addClass(this.options.inputclass); + this.$input.addClass(this.options.inputclass); } if (this.options.placeholder) { - this.$field.attr('placeholder', this.options.placeholder); + this.$input.attr('placeholder', this.options.placeholder); } - this.$input.datepicker(this.options.datepicker); + this.$tpl.datepicker(this.options.datepicker); //need to disable original event handlers - this.$field.off('focus keydown'); + this.$input.off('focus keydown'); //update value of datepicker - this.$field.keyup($.proxy(function(){ - this.$input.removeData('date'); - this.$input.datepicker('update'); + this.$input.keyup($.proxy(function(){ + this.$tpl.removeData('date'); + this.$tpl.datepicker('update'); }, this)); }, value2input: function(value) { - this.$field.val(value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : ''); - this.$input.datepicker('update'); + this.$input.val(value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : ''); + this.$tpl.datepicker('update'); }, input2value: function() { - return this.html2value(this.$field.val()); + return this.html2value(this.$input.val()); }, activate: function() { - if(this.$field.is(':visible')) { - this.$field.focus(); - $.fn.editableutils.setCursorPosition(this.$field.get(0), this.$field.val().length); - } + $.fn.editabletypes.text.prototype.activate.call(this); }, autosubmit: function() { @@ -64,12 +61,12 @@ Automatically shown in inline mode. @property tpl @default **/ - tpl:'<div class="input-append date"><input class="input-small" type="text"/><span class="add-on"><i class="icon-th"></i></span></div>', + tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>', /** @property inputclass - @default '' + @default 'input-small' **/ - inputclass: '', + inputclass: 'input-small', /* datepicker config */ datepicker: { diff --git a/src/inputs/dateui/dateui.js b/src/inputs/dateui/dateui.js index 674a16e..cace358 100644 --- a/src/inputs/dateui/dateui.js +++ b/src/inputs/dateui/dateui.js @@ -52,15 +52,20 @@ $(function(){ render: function () { DateUI.superclass.render.call(this); this.$input.datepicker(this.options.datepicker); - + }, + + postrender: function() { + //"clear" link if(this.options.clear) { this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){ e.preventDefault(); e.stopPropagation(); this.clear(); }, this)); + + this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear)); } - }, + }, value2html: function(value, element) { var text = $.datepicker.formatDate(this.options.viewformat, value); @@ -134,12 +139,12 @@ $(function(){ @property tpl @default <div></div> **/ - tpl:'<div></div>', + tpl:'<div class="editable-date"></div>', /** @property inputclass - @default 'editable-date' + @default '' **/ - inputclass: 'editable-date', + inputclass: '', /** Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br> Full list of tokens: http://docs.jquery.com/UI/Datepicker/formatDate diff --git a/src/inputs/dateui/dateuifield.js b/src/inputs/dateui/dateuifield.js index d219484..d3e656d 100644 --- a/src/inputs/dateui/dateuifield.js +++ b/src/inputs/dateui/dateuifield.js @@ -14,9 +14,9 @@ Automatically shown in inline mode. $.extend(DateUIField.prototype, { render: function () { - $.fn.editabletypes.dateui.superclass.render.call(this); - this.$field = this.$input.find('input'); - this.$field.datepicker(this.options.datepicker); + this.$tpl = $(this.options.tpl); + this.$input = this.$tpl.find('input'); + this.$input.datepicker(this.options.datepicker); /* if(this.options.clear) { @@ -30,18 +30,15 @@ Automatically shown in inline mode. }, value2input: function(value) { - this.$field.val($.datepicker.formatDate(this.options.viewformat, value)); + this.$input.val($.datepicker.formatDate(this.options.viewformat, value)); }, input2value: function() { - return this.html2value(this.$field.val()); + return this.html2value(this.$input.val()); }, activate: function() { - if(this.$field.is(':visible')) { - this.$field.focus(); - $.fn.editableutils.setCursorPosition(this.$field.get(0), this.$field.val().length); - } + $.fn.editabletypes.text.prototype.activate.call(this); }, autosubmit: function() { diff --git a/src/inputs/html5types.js b/src/inputs/html5types.js index e71017f..7a55842 100644 --- a/src/inputs/html5types.js +++ b/src/inputs/html5types.js @@ -155,29 +155,29 @@ Range (inherit from number) $.fn.editableutils.inherit(Range, $.fn.editabletypes.number); $.extend(Range.prototype, { render: function () { - this.$input = $(this.options.tpl); - var $slider = this.$input.filter('input'); + this.$tpl = $(this.options.tpl); + this.$input = this.$tpl.filter('input'); if(this.options.inputclass) { - $slider.addClass(this.options.inputclass); + this.$input.addClass(this.options.inputclass); } if (this.options.min !== null) { - $slider.attr('min', this.options.min); + this.$input.attr('min', this.options.min); } if (this.options.max !== null) { - $slider.attr('max', this.options.max); + this.$input.attr('max', this.options.max); } if (this.options.step !== null) { - $slider.attr('step', this.options.step); + this.$input.attr('step', this.options.step); } - $slider.on('input', function(){ + this.$input.on('input', function(){ $(this).siblings('output').text($(this).val()); }); }, activate: function() { - this.$input.filter('input').focus(); + this.$input.focus(); } }); Range.defaults = $.extend({}, $.fn.editabletypes.number.defaults, { diff --git a/src/inputs/list.js b/src/inputs/list.js index e5b7ba9..5c87220 100644 --- a/src/inputs/list.js +++ b/src/inputs/list.js @@ -14,8 +14,9 @@ List - abstract class for inputs that have source option loaded from js array or $.extend(List.prototype, { render: function () { - List.superclass.render.call(this); var deferred = $.Deferred(); + this.$tpl = $(this.options.tpl); + this.$input = this.$tpl; //will be set in renderList this.error = null; this.sourceData = null; this.prependData = null; diff --git a/src/inputs/select.js b/src/inputs/select.js index b4d3048..c4120aa 100644 --- a/src/inputs/select.js +++ b/src/inputs/select.js @@ -35,9 +35,13 @@ $(function(){ } for(var i=0; i<this.sourceData.length; i++) { - this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text)); + this.$tpl.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text)); } + if(this.options.inputclass) { + this.$input.addClass(this.options.inputclass); + } + //enter submit this.$input.on('keydown.editable', function (e) { if (e.which === 13) { diff --git a/src/inputs/text.js b/src/inputs/text.js index dcde506..94eb8d3 100644 --- a/src/inputs/text.js +++ b/src/inputs/text.js @@ -23,11 +23,56 @@ $(function(){ $.fn.editableutils.inherit(Text, $.fn.editabletypes.abstractinput); $.extend(Text.prototype, { + render: function() { + Text.superclass.render.call(this); + + if (this.options.clear) { + this.$clear = $('<span class="editable-clear-x"></span>'); + this.$tpl = $('<div style="position: relative">') + .append(this.$input) + .append(this.$clear); + } + + if(this.options.inputclass) { + this.$input.addClass(this.options.inputclass); + } + + if (this.options.placeholder) { + this.$input.attr('placeholder', this.options.placeholder); + } + }, + + postrender: function() { + if (this.options.clear) { + var h = this.$input.parent().height() || 20; + this.$clear.css('top', (h - this.$clear.outerHeight()) / 2); + this.$input.keyup($.proxy(this.toggleClear, this)); + this.$clear.click($.proxy(function(){ + this.$clear.hide(); + this.$input.val('').focus(); + }, this)); + } + }, + activate: function() { if(this.$input.is(':visible')) { this.$input.focus(); $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length); + if(this.options.clear) { + this.toggleClear(); + } } + }, + + //show / hide clear button + toggleClear: function() { + if(!this.options.clear) return; + + if(this.$input.val()) { + this.$clear.show(); + } else { + this.$clear.hide(); + } } }); @@ -44,7 +89,12 @@ $(function(){ @type string @default null **/ - placeholder: null + placeholder: null, + + /** + Whether to show clear button / link or not + **/ + clear: true }); $.fn.editabletypes.text = Text; diff --git a/src/inputs/textarea.js b/src/inputs/textarea.js index 58b2a04..9b86f50 100644 --- a/src/inputs/textarea.js +++ b/src/inputs/textarea.js @@ -67,10 +67,7 @@ $(function(){ }, activate: function() { - if(this.$input.is(':visible')) { - $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length); - this.$input.focus(); - } + $.fn.editabletypes.text.prototype.activate.call(this); } });