From 5b8f00d01b62734f5a128d5990dd177b4fd10f19 Mon Sep 17 00:00:00 2001 From: vitalets <noginsk@rambler.ru> Date: Thu, 29 Nov 2012 22:06:15 +0400 Subject: [PATCH] added toggle values dblclick and hover --- CHANGELOG.txt | 3 +- src/containers/editable-container.js | 13 +-- src/element/editable-element.js | 45 +++++++---- test/unit/common.js | 114 +++++++++++++++++---------- test/unit/text.js | 12 --- 5 files changed, 108 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a9260f3..62f3d74 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,9 +4,10 @@ X-editable changelog Version 1.1.1 wip ---------------------------- +[enh] added 'inputs-ext' directory with sample input 'address'. They will not be concatenated to main files (vitalets) [enh #13] 'onblur' option: to cancel, submit or ignore when user clicks outside the form (vitalets) [enh] 'ajaxOptions' parameter for advanced ajax configuration (vitalets) -[enh] success callback can return object to overwrite submitted value (vitalets) +[enh] 'success' callback can return object to overwrite submitted value (vitalets) Version 1.1.0 Nov 27, 2012 diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js index 56d7290..9072aa0 100644 --- a/src/containers/editable-container.js +++ b/src/containers/editable-container.js @@ -159,12 +159,12 @@ Applied as jQuery method. /** Shows container with form @method show() - @param {boolean} multi if true - other editable containers will not be closed. Default false. + @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true. **/ - show: function (multi) { + show: function (closeAll) { this.$element.addClass('editable-open'); - if(!multi) { - //close all open containers (except one) + if(closeAll !== false) { + //close all open containers (except this) this.closeOthers(this.$element[0]); } @@ -207,12 +207,13 @@ Applied as jQuery method. /** Toggles container visibility (show / hide) @method toggle() + @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true. **/ - toggle: function() { + toggle: function(closeAll) { if(this.tip && this.tip().is(':visible')) { this.hide(); } else { - this.show(); + this.show(closeAll); } }, diff --git a/src/element/editable-element.js b/src/element/editable-element.js index 6ce4e2d..8b07eb8 100644 --- a/src/element/editable-element.js +++ b/src/element/editable-element.js @@ -57,9 +57,9 @@ Makes editable any HTML element on the page. Applied as jQuery method. this.$element.addClass('editable'); //attach click handler. In disabled mode it just prevent default action (useful for links) - if(this.options.toggle === 'click') { + if(this.options.toggle !== 'manual') { this.$element.addClass('editable-click'); - this.$element.on('click.editable', $.proxy(this.click, this)); + this.$element.on(this.options.toggle + '.editable', $.proxy(this.activate, this)); } else { this.$element.attr('tabindex', -1); //do not stop focus on element when toggled manually } @@ -100,7 +100,7 @@ Makes editable any HTML element on the page. Applied as jQuery method. this.options.disabled = false; this.$element.removeClass('editable-disabled'); this.handleEmpty(); - if(this.options.toggle === 'click') { + if(this.options.toggle !== 'manual') { if(this.$element.attr('tabindex') === '-1') { this.$element.removeAttr('tabindex'); } @@ -178,22 +178,34 @@ Makes editable any HTML element on the page. Applied as jQuery method. } }, - click: function (e) { + activate: function (e) { e.preventDefault(); if(this.options.disabled) { return; } - //stop propagation bacause document listen any click to hide all editableContainers + /* + stop propagation not required anymore because in document click handler it checks event target + */ //e.stopPropagation(); - this.toggle(); + + if(this.options.toggle === 'mouseenter') { + //for hover only show container + this.show(); + } else { + /* + if toggle = click we should not close all other containers as they will be closed automatically in document click listener + */ + var closeAll = (this.options.toggle !== 'click'); + this.toggle(closeAll); + } }, /** Shows container with form @method show() - @param {boolean} multi if true - other editable containers will not be closed. Default false. + @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true. **/ - show: function (multi) { + show: function (closeAll) { if(this.options.disabled) { return; } @@ -213,13 +225,9 @@ Makes editable any HTML element on the page. Applied as jQuery method. } else if(this.container.tip().is(':visible')) { return; } - - //hide all other editable containers. Required to work correctly with toggle = manual - //temp - //$('.editable-container').find('.editable-cancel').click(); //show container - this.container.show(multi); + this.container.show(closeAll); }, /** @@ -240,12 +248,13 @@ Makes editable any HTML element on the page. Applied as jQuery method. /** Toggles container visibility (show / hide) @method toggle() + @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true. **/ - toggle: function() { + toggle: function(closeAll) { if(this.container && this.container.tip().is(':visible')) { this.hide(); } else { - this.show(); + this.show(closeAll); } }, @@ -462,9 +471,10 @@ Makes editable any HTML element on the page. Applied as jQuery method. **/ disabled: false, /** - How to toggle editable. Can be <code>click|manual</code>. + How to toggle editable. Can be <code>click|dblclick|mouseenter|manual</code>. When set to <code>manual</code> you should manually call <code>show/hide</code> methods of editable. - Note: if you are calling <code>show</code> on **click** event you need to apply <code>e.stopPropagation()</code> because container has behavior to hide on any click outside. + **Note**: if you call <code>show</code> or <code>toggle</code> inside **click** handler of some DOM element, + you need to apply <code>e.stopPropagation()</code> because containers are being closed on any click on document. @example $('#edit-button').click(function(e) { @@ -477,6 +487,7 @@ Makes editable any HTML element on the page. Applied as jQuery method. @default 'click' **/ toggle: 'click', + /** Text shown when element is empty. diff --git a/test/unit/common.js b/test/unit/common.js index 22e8da2..0edd2d8 100644 --- a/test/unit/common.js +++ b/test/unit/common.js @@ -89,39 +89,6 @@ ok(p.find(':contains("'+title+'")').length, 'title ok'); e.remove(); }); - /* - test("should close all other containers on click on editable", function () { - var e1 = $('<a href="#" data-pk="1" data-url="post.php" id="a">abc</a>').appendTo('#qunit-fixture').editable(), - e2 = $('<a href="#" data-pk="1" data-url="post.php" id="b">abcd</a>').appendTo('#qunit-fixture').editable(); - - e1.click() - var p1 = tip(e1); - ok(p1.is(':visible'), 'popover1 visible'); - - e2.click() - var p2 = tip(e2); - ok(p2.is(':visible'), 'popover2 visible'); - ok(!p1.is(':visible'), 'popover1 closed'); - - p2.find('button[type=button]').click(); - ok(!p2.is(':visible'), 'popover2 closed'); - }); - - 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'); - - e.click(); - var p = tip(e); - ok(p.is(':visible'), 'popover shown'); - - p.click(); - ok(p.is(':visible'), 'popover still shown'); - - e1.click(); - ok(!p.is(':visible'), 'popover closed'); - }); - */ test("onblur: cancel", function () { var oldValue = 'abc', @@ -160,7 +127,7 @@ e2.editable('hide'); ok(!p2.is(':visible'), 'popover2 closed'); - //call show method of another editable (multi = false) + //call show method of another editable, closeAll = true (default) e.click(); p = tip(e); ok(p.is(':visible'), 'popover1 visible'); @@ -173,12 +140,12 @@ e2.editable('hide'); ok(!p2.is(':visible'), 'popover2 closed'); - //call show method of another editable (multi = true) + //call show method of another editable, closeAll = false e.click(); p = tip(e); ok(p.is(':visible'), 'popover1 visible'); p.find('input').val(newValue); - e2.editable('show', true); + e2.editable('show', false); p2 = tip(e2); ok(p.is(':visible'), 'popover1 visible'); ok(p2.is(':visible'), 'popover2 visible'); @@ -226,7 +193,7 @@ e2.editable('hide'); ok(!p2.is(':visible'), 'popover2 closed'); - //call show method of another editable (multi = false) + //call show method of another editable, closeAll = true (default) e.click(); p = tip(e); ok(p.is(':visible'), 'popover1 visible'); @@ -239,12 +206,12 @@ e2.editable('hide'); ok(!p2.is(':visible'), 'popover2 closed'); - //call show method of another editable (multi = true) + //call show method of another editable, closeAll = false e.click(); p = tip(e); ok(p.is(':visible'), 'popover1 visible'); p.find('input').val(oldValue); - e2.editable('show', true); + e2.editable('show', false); p2 = tip(e2); ok(p.is(':visible'), 'popover1 visible'); ok(p2.is(':visible'), 'popover2 visible'); @@ -286,7 +253,7 @@ e2.editable('hide'); ok(!p2.is(':visible'), 'popover2 closed'); - //call show method of another editable (multi = false) + //call show method of another editable, closeAll = true (default) e2.editable('show'); p2 = tip(e2); ok(p.is(':visible'), 'popover1 still visible'); @@ -294,8 +261,8 @@ e2.editable('hide'); ok(!p2.is(':visible'), 'popover2 closed'); - //call show method of another editable (multi = true) - e2.editable('show', true); + //call show method of another editable, closeAll = false + e2.editable('show', false); p2 = tip(e2); ok(p.is(':visible'), 'popover1 still visible'); ok(p2.is(':visible'), 'popover2 visible'); @@ -317,7 +284,68 @@ ok(p.find('button').offset().left > p.find('.editable-input').offset().left + p.find('.editable-input').width(), 'buttons left ok'); d.remove(); - }); + }); + + test("toggle: manual", function () { + var e = $('<a href="#" id="a"></a>').appendTo('#qunit-fixture').editable({ + toggle: 'manual' + }); + + e.click(); + ok(!e.data('editableContainer'), 'popover not visible after click'); + e.editable('show'); + var p = tip(e); + ok(p.is(':visible'), 'shown manually'); + }); + + test("toggle: dblclick", function () { + var e = $('<a href="#" id="a"></a>').appendTo('#qunit-fixture').editable({ + toggle: 'dblclick' + }), + p, p2, + e2 = $('<a href="#" data-type="text" data-pk="1" data-url="post.php" id="b">abcd</a>').appendTo('#qunit-fixture').editable(); + + e.click(); + ok(!e.data('editableContainer'), 'popover not visible after click'); + + e2.click(); + p2 = tip(e2); + ok(p2.is(':visible'), 'popover2 visible'); + + e.dblclick(); + p = tip(e); + ok(p.is(':visible'), 'popover1 visible'); + ok(!p2.is(':visible'), 'popover2 closed'); + }); + + test("toggle: mouseenter", function () { + var e = $('<a href="#" id="a"></a>').appendTo('#qunit-fixture').editable({ + toggle: 'mouseenter' + }), + p, p2, + e2 = $('<a href="#" data-type="text" data-pk="1" data-url="post.php" id="b">abcd</a>').appendTo('#qunit-fixture').editable(); + + e.click(); + ok(!e.data('editableContainer'), 'popover not visible after click'); + + e.dblclick(); + ok(!e.data('editableContainer'), 'popover not visible after dblclick'); + + e2.click(); + p2 = tip(e2); + ok(p2.is(':visible'), 'popover2 visible'); + + e.mouseenter(); + ok(e.data('editableContainer'), 'container defined'); + p = tip(e); + ok(p.is(':visible'), 'popover1 visible'); + ok(!p2.is(':visible'), 'popover2 closed'); + + //hover once again --> container should stay open + e.hover(); + p = tip(e); + ok(p.is(':visible'), 'popover1 visible after second hover'); + }); //unfortunatly, testing this feature does not always work in browsers. Tested manually. /* diff --git a/test/unit/text.js b/test/unit/text.js index 8e56652..f7fc3e9 100644 --- a/test/unit/text.js +++ b/test/unit/text.js @@ -39,18 +39,6 @@ $(function () { p.find('button[type=button]').click(); ok(!p.is(':visible'), 'popover was removed'); }); - - test("option 'toggle' = manual", function () { - var e = $('<a href="#" id="a"></a>').appendTo('#qunit-fixture').editable({ - toggle: 'manual' - }); - - e.click(); - ok(!e.data().editableContainer, 'popover not visible after click'); - e.editable('show'); - var p = tip(e); - ok(p.is(':visible'), 'shown manually'); - }); asyncTest("should load correct value and save new entered text (and value)", function () { var v = 'ab<b>"',