diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js index c75cf01..8cc64c2 100644 --- a/src/containers/editable-container.js +++ b/src/containers/editable-container.js @@ -107,8 +107,30 @@ Applied as jQuery method. Hides container with form @method hide() **/ - hide: function() { + hide: function() { + if(!this.tip() || !this.tip().is(':visible')) { + return; + } this.call('hide'); + /** + Fired when container was hidden. It occurs on both save or cancel. + + @event hidden + @param {Object} event event object + **/ + this.$element.triggerHandler('hidden'); + }, + + /** + Toggles container visibility (show / hide) + @method toggle() + **/ + toggle: function() { + if(this.tip && this.tip().is(':visible')) { + this.hide(); + } else { + this.show(); + } }, /* @@ -119,12 +141,12 @@ Applied as jQuery method. //tbd in child class }, - cancel: function() { + cancel: function() { if(this.options.autohide) { this.hide(); } /** - Fired when form was cancelled + Fired when form was cancelled by user @event cancel @param {Object} event event object diff --git a/src/containers/editable-inline.js b/src/containers/editable-inline.js index fe0f17e..92c5455 100644 --- a/src/containers/editable-inline.js +++ b/src/containers/editable-inline.js @@ -41,12 +41,18 @@ }, hide: function () { + if(!this.tip() || !this.tip().is(':visible')) { + return; + } this.$form.hide(this.options.anim, $.proxy(function() { this.$element.show(); //return focus on element if (this.options.enablefocus) { this.$element.focus(); - } + } + + //trigger event + this.$element.triggerHandler('hidden'); }, this)); }, diff --git a/src/containers/editable-tooltip.js b/src/containers/editable-tooltip.js index 5f1463a..dcfa261 100644 --- a/src/containers/editable-tooltip.js +++ b/src/containers/editable-tooltip.js @@ -63,7 +63,11 @@ }, hide: function() { - this.call('close'); + if(!this.tip() || !this.tip().is(':visible')) { + return; + } + this.call('close'); + this.$element.triggerHandler('hidden'); }, setPosition: function() { diff --git a/src/editable-form/editable-form.js b/src/editable-form/editable-form.js index 8334286..8a975b0 100644 --- a/src/editable-form/editable-form.js +++ b/src/editable-form/editable-form.js @@ -167,6 +167,14 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'. //sending data to server $.when(this.save(newValueStr)) .done($.proxy(function(response) { + var error; + //call success callback. if it returns string --> show error + if(error = this.options.success.call(this, response, newValue)) { + this.error(error); + this.showForm(); + return; + } + //clear error message this.error(false); this.value = newValue; @@ -367,7 +375,20 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'. } } **/ - validate: null + validate: null, + /** + Success callback. Called when value successfully sent on server and response status = 200. + Can be used to process json response. If this function returns string - means error occured and string is shown as error message. + + @property success + @type function + @default null + @example + success: function(response, newValue) { + if(!response.success) return response.msg; + } + **/ + success: function(response, newValue) {} }; /* diff --git a/src/element/editable-element.js b/src/element/editable-element.js index 365e08c..ed282fd 100644 --- a/src/element/editable-element.js +++ b/src/element/editable-element.js @@ -220,7 +220,7 @@ Makes editable any HTML element on the page. Applied as jQuery method. if(!this.container) { var containerOptions = $.extend({}, this.options, { value: this.value, - autohide: false + autohide: false //element itsef will show/hide container }); this.$element.editableContainer(containerOptions); this.$element.on({ @@ -243,22 +243,22 @@ Makes editable any HTML element on the page. Applied as jQuery method. Hides container with form @method hide() **/ - hide: function () { - if(this.container && this.container.tip().is(':visible')) { + hide: function () { + if(this.container) { this.container.hide(); - - //return focus on element - if (this.options.enablefocus && this.options.toggle === 'click') { - this.$element.focus(); - } } + + //return focus on element + if (this.options.enablefocus && this.options.toggle === 'click') { + this.$element.focus(); + } }, /** Toggles container visibility (show / hide) @method toggle() **/ - toggle: function () { + toggle: function() { if(this.container && this.container.tip().is(':visible')) { this.hide(); } else { @@ -270,16 +270,6 @@ Makes editable any HTML element on the page. Applied as jQuery method. * called when form was submitted */ save: function(e, params) { - var error, form; - - //if sent to server, call success callback. if it return string --> show error - if((params.response !== undefined) && (error = this.options.success.call(this, params.response, params.newValue))) { - form = this.container.tip().find('form').parent().data('editableform'); - form.error(error); - form.showForm(); - return; - } - //if url is not user's function and value was not sent to server and value changed --> mark element with unsaved css. if(typeof this.options.url !== 'function' && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) { this.$element.addClass('editable-unsaved'); @@ -539,20 +529,7 @@ Makes editable any HTML element on the page. Applied as jQuery method. @type mixed @default element's text **/ - value: null, - /** - Success callback. Called when value successfully sent on server and response status = 200. - Can be used to process json response. If this function returns string - means error occured and string is shown as error message. - - @property success - @type function - @default null - @example - success: function(response, newValue) { - if(!response.success) return response.msg; - } - **/ - success: function(response, newValue) {} + value: null }; }(window.jQuery)); \ No newline at end of file diff --git a/test/unit/api.js b/test/unit/api.js index 10a7019..dfb24fb 100644 --- a/test/unit/api.js +++ b/test/unit/api.js @@ -179,8 +179,8 @@ $(function () { }); - asyncTest("events: shown / cancel", function () { - expect(2); + asyncTest("events: shown / cancel / hidden", function () { + expect(3); var val = '1', e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx); @@ -192,7 +192,12 @@ $(function () { e.on('cancel', function(event) { var editable = $(this).data('editable'); ok(true, 'cancel triggered'); - }); + }); + + e.on('hidden', function(event) { + var editable = $(this).data('editable'); + ok(true, 'hidden triggered'); + }); e.editable({ source: 'groups.php', @@ -209,7 +214,38 @@ $(function () { }, timeout); }, timeout); - }); + }); + + asyncTest("event: save / hidden", function () { + expect(2); + var val = '1', + e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx); + + e.on('save', function(event, params) { + var editable = $(this).data('editable'); + equal(params.newValue, 2, 'save triggered, value correct'); + }); + + e.on('hidden', function(event) { + var editable = $(this).data('editable'); + ok(true, 'hidden triggered'); + }); + + e.editable({ + source: 'groups.php', + }); + + e.click(); + var p = tip(e); + p.find('select').val(2); + p.find('form').submit(); + + setTimeout(function() { + p.find('button[type=button]').click(); + e.remove(); + start(); + }, timeout); + }); test("show/hide/toggle methods", function () { @@ -375,7 +411,7 @@ $(function () { }); - test("setValue", function () { + test("setValue method", function () { var e = $('<a href="#" data-name="name" data-type="select" data-url="post.php"></a>').appendTo('#qunit-fixture').editable({ value: 1, source: groups diff --git a/test/unit/common.js b/test/unit/common.js index fbbd10b..c6fd49e 100644 --- a/test/unit/common.js +++ b/test/unit/common.js @@ -107,7 +107,7 @@ ok(!p2.is(':visible'), 'popover2 closed'); }); - test("click outside popoover should hide it", function () { + test("click outside container should hide it", function () { var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo('#qunit-fixture').editable(), e1 = $('<div>').appendTo('body'); diff --git a/test/unit/text.js b/test/unit/text.js index 9081923..df70bda 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -186,13 +186,14 @@ $(function () { }, timeout); }); - asyncTest("should show error if success callback return string", function () { - var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable({ - success: function(data) { + asyncTest("should show error if success callback returns string", function () { + var newText = 'cd<e>;"', + e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable({ + success: function(response, newValue) { + equal(newValue, newText, 'value in success passed correctly'); return 'error'; } - }), - newText = 'cd<e>;"' + }); e.click() var p = tip(e); @@ -211,7 +212,7 @@ $(function () { start(); }, timeout); - }) + }); asyncTest("should submit all required params", function () { var e = $('<a href="#" data-pk="1" data-url="post-resp.php">abc</a>').appendTo(fx).editable({