diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 39cd0ca..a6434b8 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,7 @@ X-editable changelog Version 1.4.0 wip ---------------------------- +[bug] select: source loaded twice if sourceCache = false (vitalets) [enh] added `destroy` method, see #61 (vitalets) [enh] textarea: added `rows` property (vitalets) [enh #60] added wysihtml5 input (vitalets) diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js index 4e1f43d..7bc9f66 100644 --- a/src/containers/editable-container.js +++ b/src/containers/editable-container.js @@ -33,7 +33,7 @@ Applied as jQuery method. this.destroy(); }, this)); - //attach document handlers (once) + //attach document handler to close containers on click / escape if(!$(document).data('editable-handlers-attached')) { //close all on escape $(document).on('keyup.editable', function (e) { @@ -59,7 +59,7 @@ Applied as jQuery method. } } - //close all open containers (except one) + //close all open containers (except one - target) Popup.prototype.closeOthers(e.target); }); @@ -72,6 +72,7 @@ Applied as jQuery method. this.containerOptions = {}; this.formOptions = {}; var cDef = $.fn[this.containerName].defaults; + //keys defined in container defaults go to container, others go to form for(var k in this.options) { if(k in cDef) { this.containerOptions[k] = this.options[k]; @@ -90,9 +91,9 @@ Applied as jQuery method. this.$form = $('<div>') .editableform(this.formOptions) .on({ - save: $.proxy(this.save, this), - cancel: $.proxy(function(){ this.hide('cancel'); }, this), - nochange: $.proxy(function(){ this.hide('nochange'); }, this), + save: $.proxy(this.save, this), //click on submit button (value changed) + nochange: $.proxy(function(){ this.hide('nochange'); }, this), //click on submit button (value NOT changed) + cancel: $.proxy(function(){ this.hide('cancel'); }, this), //click on calcel button show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state) rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown rendered: $.proxy(function(){ diff --git a/src/editable-form/editable-form.js b/src/editable-form/editable-form.js index 22439c9..96269a1 100644 --- a/src/editable-form/editable-form.js +++ b/src/editable-form/editable-form.js @@ -21,8 +21,8 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc. EditableForm.prototype = { constructor: EditableForm, initInput: function() { //called once - //create input of specified type - this.input = $.fn.editableutils.createInput(this.options); + //take input from options or create new input instance + this.input = this.options.input || $.fn.editableutils.createInput(this.options); if(!this.input) { return; } diff --git a/src/element/editable-element.js b/src/element/editable-element.js index 9fcd880..651ef33 100644 --- a/src/element/editable-element.js +++ b/src/element/editable-element.js @@ -241,7 +241,8 @@ Makes editable any HTML element on the page. Applied as jQuery method. //init editableContainer: popover, tooltip, inline, etc.. if(!this.container) { var containerOptions = $.extend({}, this.options, { - value: this.value + value: this.value, + input: this.input //pass input to form (as it is already created) }); this.$element.editableContainer(containerOptions); this.$element.on("save.internal", $.proxy(this.save, this)); @@ -355,6 +356,9 @@ Makes editable any HTML element on the page. Applied as jQuery method. if(this.container) { this.container.destroy(); } + + this.$element.off("save.internal"); + this.$element.removeClass('editable'); this.$element.removeClass('editable-open'); this.$element.removeData('editable'); diff --git a/src/inputs/checklist.js b/src/inputs/checklist.js index f7ff23f..682e9a1 100644 --- a/src/inputs/checklist.js +++ b/src/inputs/checklist.js @@ -32,6 +32,9 @@ $(function(){ $.extend(Checklist.prototype, { renderList: function() { var $label, $div; + + this.$tpl.empty(); + if(!$.isArray(this.sourceData)) { return; } diff --git a/src/inputs/list.js b/src/inputs/list.js index c262109..f7a1545 100644 --- a/src/inputs/list.js +++ b/src/inputs/list.js @@ -17,8 +17,6 @@ List - abstract class for inputs that have source option loaded from js array or var deferred = $.Deferred(); this.error = null; - this.sourceData = null; - this.prependData = null; this.onSourceReady(function () { this.renderList(); deferred.resolve(); diff --git a/src/inputs/select.js b/src/inputs/select.js index f2f7875..f08b512 100644 --- a/src/inputs/select.js +++ b/src/inputs/select.js @@ -30,12 +30,14 @@ $(function(){ $.extend(Select.prototype, { renderList: function() { + this.$input.empty(); + if(!$.isArray(this.sourceData)) { return; } for(var i=0; i<this.sourceData.length; i++) { - this.$tpl.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text)); + this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text)); } this.setClass(); diff --git a/test/unit/select.js b/test/unit/select.js index d3462d5..1987a92 100644 --- a/test/unit/select.js +++ b/test/unit/select.js @@ -37,7 +37,15 @@ $(function () { equal(p.find('select').find('option').length, size, 'options loaded'); equal(p.find('select').val(), e.data('editable').value, 'selected value correct') ; p.find('.editable-cancel').click(); - ok(!p.is(':visible'), 'popover was removed'); + ok(!p.is(':visible'), 'popover was removed'); + + //open second time: items should not dublicate + e.click(); + + ok(p.find('select').length, 'select exists'); + equal(p.find('select').find('option').length, size, 'options loaded'); + equal(p.find('select').val(), e.data('editable').value, 'selected value correct') ; + e.remove(); start(); }, timeout); @@ -384,50 +392,58 @@ $(function () { asyncTest("sourceCache: false", function () { - var e = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="2" data-url="post.php" data-source="groups-cache-false.php">customer</a>').appendTo(fx).editable({ - sourceCache: false - }), - e1 = $('<a href="#" data-type="select" data-pk="1" id="name1" data-value="2" data-url="post.php" data-source="groups-cache-false.php">customer</a>').appendTo(fx).editable({ - sourceCache: false - }), - req = 0; - - $.mockjax({ + + $.mockjax({ url: 'groups-cache-false.php', response: function() { req++; this.responseText = groups; } - }); - - //click first - e.click(); - var p = tip(e); + }); + + var req = 0, + e = $('<a href="#" data-type="select" data-pk="1" data-name="name1" data-value="2" data-url="post.php" data-source="groups-cache-false.php"></a>').appendTo(fx).editable({ + sourceCache: false + }), + e1 = $('<a href="#" data-type="select" data-pk="1" id="name1" data-value="2" data-url="post.php" data-source="groups-cache-false.php">customer</a>').appendTo(fx).editable({ + sourceCache: false + }); setTimeout(function() { - ok(p.is(':visible'), 'popover visible'); - equal(p.find('select').find('option').length, size, 'options loaded'); - equal(req, 1, 'one request performed'); - - p.find('.editable-cancel').click(); - ok(!p.is(':visible'), 'popover was removed'); - - //click second - e1.click(); - p = tip(e1); + equal(req, 1, 'autotext request performed'); + + //click first + e.click(); setTimeout(function() { - ok(p.is(':visible'), 'popover2 visible'); + + var p = tip(e); + + ok(p.is(':visible'), 'popover visible'); equal(p.find('select').find('option').length, size, 'options loaded'); - equal(req, 2, 'second request performed'); + equal(req, 1, 'no additional request performed, loaded on autotext'); p.find('.editable-cancel').click(); - ok(!p.is(':visible'), 'popover was removed'); + ok(!p.is(':visible'), 'popover was removed'); - e.remove(); - e1.remove(); - start(); - }, timeout); + //click second + e1.click(); + p = tip(e1); + + setTimeout(function() { + ok(p.is(':visible'), 'popover2 visible'); + equal(p.find('select').find('option').length, size, 'options loaded'); + equal(req, 2, 'second request performed'); + + p.find('.editable-cancel').click(); + ok(!p.is(':visible'), 'popover was removed'); + + e.remove(); + e1.remove(); + start(); + + }, timeout); + }, timeout); }, timeout); });