diff --git a/CHANGELOG b/CHANGELOG index 6714ce2..8247a56 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,11 @@ +5.1.2 + - Ensuring disabled items don't close on close 5.0.1 - Reworked test infrastructure to use more robust setup and teardown using iframes 5.0.0 - Upgrading to latest version of plugin factory - Adding `destroy` method - - Removing `event` option in favour of internalizing a namespaced event + - Removing `event` option in favour of internalizing a namespaced event 4.1.2 - Moved gremlins.js dependency to devDependencies 4.1.1 diff --git a/bower.json b/bower.json index 238dc32..1168b28 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "bellows", - "version": "5.1.1", + "version": "5.1.2", "homepage": "https://github.com/mobify/bellows", "authors": [ "Mobify " diff --git a/dist/bellows.js b/dist/bellows.js index d266e57..3dedf15 100644 --- a/dist/bellows.js +++ b/dist/bellows.js @@ -33,7 +33,7 @@ Bellows.__super__.call(this, element, options, Bellows.DEFAULTS); } - Bellows.VERSION = '5.1.1'; + Bellows.VERSION = '5.1.2'; Bellows.DEFAULTS = { singleItemOpen: false, @@ -67,9 +67,9 @@ /** * Ghetto Event Delegation™ - Zepto doesn't support descendant selectors in event delegation, - so we compare against the closest bellows to ensure we are invoking - the event from a direct child, not a bellows child from a nested bellows. + Zepto doesn't support descendant selectors in event delegation, + so we compare against the closest bellows to ensure we are invoking + the event from a direct child, not a bellows child from a nested bellows. */ this.$bellows .on(events.CLICK, function(e) { @@ -118,6 +118,14 @@ return item; }, + _isOpen: function($item) { + return $item.hasClass(cssClasses.OPENED); + }, + + _isDisabled: function($item) { + return $item.hasClass(cssClasses.DISABLED); + }, + _wrapContent: function($items) { $items .find(selectors.ITEM_CONTENT) @@ -138,7 +146,7 @@ open: function($item) { $item = this._item($item); - if ($item.hasClass(cssClasses.OPENED) || $item.hasClass(cssClasses.DISABLED)) { + if (this._isOpen($item) || this._isDisabled($item)) { return; } @@ -149,7 +157,7 @@ this.closeAll(); } - this._trigger('open', { item: $item }); + this._trigger('open', {item: $item}); Velocity .animate($contentWrapper, 'slideDown', { @@ -168,7 +176,7 @@ plugin._setHeight(); - plugin._trigger('opened', { item: $item }); + plugin._trigger('opened', {item: $item}); } }); }, @@ -176,14 +184,14 @@ close: function($item) { $item = this._item($item); - if (!$item.hasClass(cssClasses.OPENED)) { + if (!this._isOpen($item) || this._isDisabled($item)) { return; } var plugin = this; var $contentWrapper = $item.find(selectors.ITEM_CONTENT_WRAPPER); - this._trigger('close', { item: $item }); + this._trigger('close', {item: $item}); Velocity .animate($contentWrapper, 'slideUp', { @@ -203,7 +211,7 @@ plugin._setHeight(); - plugin._trigger('closed', { item: $item }); + plugin._trigger('closed', {item: $item}); } }); }, diff --git a/dist/bellows.min.js b/dist/bellows.min.js index 7790d7c..c2fcbde 100644 --- a/dist/bellows.min.js +++ b/dist/bellows.min.js @@ -1,2 +1,2 @@ -/*! bellows 5.1.1 (https://github.com/mobify/bellows.git) */ -(function(e){if("function"==typeof define&&define.amd)define(["$","velocity","plugin"],e);else{var t=window.Zepto||window.jQuery;e(t,t.Velocity,window.Plugin)}})(function(e,t,i){function s(e,t){s.__super__.call(this,e,t,s.DEFAULTS)}var n={ITEM:"bellows__item",HEADER:"bellows__header",OPENED:"bellows--is-open",OPENING:"bellows--is-opening",CLOSING:"bellows--is-closing",DISABLED:"bellows--is-disabled"},o={ITEM_HEADER:"> .bellows__item > .bellows__header",ITEM_CONTENT_WRAPPER:"> .bellows__content-wrapper",ITEM_CONTENT:"> .bellows__item > .bellows__content"},l={CLICK:"click.bellows"};return s.VERSION="5.1.1",s.DEFAULTS={singleItemOpen:!1,duration:200,easing:"swing",open:e.noop,opened:e.noop,close:e.noop,closed:e.noop},i.create("bellows",s,{_init:function(t){this.$bellows=e(t),this._wrapContent(this.$bellows),this._bindEvents()},destroy:function(){this.$bellows.removeData(this.name).off(l.CLICK)},_bindEvents:function(){var t=this;this.$bellows.on(l.CLICK,function(i){var s=e(i.target),o=s.closest(".bellows");s.is("a")||s.parents("a").length||o[0]===t.$bellows[0]&&(s.hasClass(n.HEADER)||s.closest(".bellows__header").length)&&(i.preventDefault(),t.toggle(s.closest(".bellows__item")))})},_getHeight:function(e){return parseFloat(t.CSS.getPropertyValue(e[0],"height"))},_setHeight:function(e){this.$bellows.css("height",e||"")},_item:function(e){return"number"==typeof e&&(e=this.$bellows.find("."+n.ITEM).eq(e)),e},_wrapContent:function(e){e.find(o.ITEM_CONTENT).wrap('
').parents(".bellows__item:not(.bellows--is-open)").find(o.ITEM_CONTENT_WRAPPER).attr("aria-hidden",!0)},toggle:function(e){e=this._item(e),this[e.hasClass(n.OPENED)?"close":"open"](e)},open:function(e){if(e=this._item(e),!e.hasClass(n.OPENED)&&!e.hasClass(n.DISABLED)){var i=this,s=e.find(o.ITEM_CONTENT_WRAPPER);this.options.singleItemOpen&&this.closeAll(),this._trigger("open",{item:e}),t.animate(s,"slideDown",{begin:function(){i._setHeight(i._getHeight(i.$bellows)+i._getHeight(s)),e.addClass(n.OPENING)},duration:this.options.duration,easing:this.options.easing,complete:function(){e.removeClass(n.OPENING).addClass(n.OPENED).find(o.ITEM_CONTENT_WRAPPER).removeAttr("aria-hidden"),i._setHeight(),i._trigger("opened",{item:e})}})}},close:function(e){if(e=this._item(e),e.hasClass(n.OPENED)){var i=this,s=e.find(o.ITEM_CONTENT_WRAPPER);this._trigger("close",{item:e}),t.animate(s,"slideUp",{begin:function(){i._setHeight(i._getHeight(i.$bellows)),e.removeClass(n.OPENED).addClass(n.CLOSING)},duration:this.options.duration,easing:this.options.easing,complete:function(){e.removeClass(n.CLOSING).find(o.ITEM_CONTENT_WRAPPER).attr("aria-hidden",!0),i._setHeight(),i._trigger("closed",{item:e})}})}},toggleAll:function(){var t=this;this.$bellows.find("."+n.ITEM).each(function(){t.toggle(e(this))})},openAll:function(){var t=this;this.$bellows.find("."+n.ITEM+":not(."+n.OPENED+")").each(function(){t.open(e(this))})},closeAll:function(){var t=this;this.$bellows.find("."+n.OPENED).each(function(){t.close(e(this))})},add:function(t,i){var s=e("
");e(t).appendTo(s),i&&this.$bellows.empty(),this._wrapContent(s),this.$bellows.append(s.children())}}),e("[data-bellows]").bellows(),e}); \ No newline at end of file +/*! bellows 5.1.2 (https://github.com/mobify/bellows.git) */ +(function(e){if("function"==typeof define&&define.amd)define(["$","velocity","plugin"],e);else{var t=window.Zepto||window.jQuery;e(t,t.Velocity,window.Plugin)}})(function(e,t,i){function s(e,t){s.__super__.call(this,e,t,s.DEFAULTS)}var n={ITEM:"bellows__item",HEADER:"bellows__header",OPENED:"bellows--is-open",OPENING:"bellows--is-opening",CLOSING:"bellows--is-closing",DISABLED:"bellows--is-disabled"},o={ITEM_HEADER:"> .bellows__item > .bellows__header",ITEM_CONTENT_WRAPPER:"> .bellows__content-wrapper",ITEM_CONTENT:"> .bellows__item > .bellows__content"},l={CLICK:"click.bellows"};return s.VERSION="5.1.2",s.DEFAULTS={singleItemOpen:!1,duration:200,easing:"swing",open:e.noop,opened:e.noop,close:e.noop,closed:e.noop},i.create("bellows",s,{_init:function(t){this.$bellows=e(t),this._wrapContent(this.$bellows),this._bindEvents()},destroy:function(){this.$bellows.removeData(this.name).off(l.CLICK)},_bindEvents:function(){var t=this;this.$bellows.on(l.CLICK,function(i){var s=e(i.target),o=s.closest(".bellows");s.is("a")||s.parents("a").length||o[0]===t.$bellows[0]&&(s.hasClass(n.HEADER)||s.closest(".bellows__header").length)&&(i.preventDefault(),t.toggle(s.closest(".bellows__item")))})},_getHeight:function(e){return parseFloat(t.CSS.getPropertyValue(e[0],"height"))},_setHeight:function(e){this.$bellows.css("height",e||"")},_item:function(e){return"number"==typeof e&&(e=this.$bellows.find("."+n.ITEM).eq(e)),e},_isOpen:function(e){return e.hasClass(n.OPENED)},_isDisabled:function(e){return e.hasClass(n.DISABLED)},_wrapContent:function(e){e.find(o.ITEM_CONTENT).wrap('
').parents(".bellows__item:not(.bellows--is-open)").find(o.ITEM_CONTENT_WRAPPER).attr("aria-hidden",!0)},toggle:function(e){e=this._item(e),this[e.hasClass(n.OPENED)?"close":"open"](e)},open:function(e){if(e=this._item(e),!this._isOpen(e)&&!this._isDisabled(e)){var i=this,s=e.find(o.ITEM_CONTENT_WRAPPER);this.options.singleItemOpen&&this.closeAll(),this._trigger("open",{item:e}),t.animate(s,"slideDown",{begin:function(){i._setHeight(i._getHeight(i.$bellows)+i._getHeight(s)),e.addClass(n.OPENING)},duration:this.options.duration,easing:this.options.easing,complete:function(){e.removeClass(n.OPENING).addClass(n.OPENED).find(o.ITEM_CONTENT_WRAPPER).removeAttr("aria-hidden"),i._setHeight(),i._trigger("opened",{item:e})}})}},close:function(e){if(e=this._item(e),this._isOpen(e)&&!this._isDisabled(e)){var i=this,s=e.find(o.ITEM_CONTENT_WRAPPER);this._trigger("close",{item:e}),t.animate(s,"slideUp",{begin:function(){i._setHeight(i._getHeight(i.$bellows)),e.removeClass(n.OPENED).addClass(n.CLOSING)},duration:this.options.duration,easing:this.options.easing,complete:function(){e.removeClass(n.CLOSING).find(o.ITEM_CONTENT_WRAPPER).attr("aria-hidden",!0),i._setHeight(),i._trigger("closed",{item:e})}})}},toggleAll:function(){var t=this;this.$bellows.find("."+n.ITEM).each(function(){t.toggle(e(this))})},openAll:function(){var t=this;this.$bellows.find("."+n.ITEM+":not(."+n.OPENED+")").each(function(){t.open(e(this))})},closeAll:function(){var t=this;this.$bellows.find("."+n.OPENED).each(function(){t.close(e(this))})},add:function(t,i){var s=e("
");e(t).appendTo(s),i&&this.$bellows.empty(),this._wrapContent(s),this.$bellows.append(s.children())}}),e("[data-bellows]").bellows(),e}); \ No newline at end of file diff --git a/package.json b/package.json index c9a1a51..caf944b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type" : "git", "url" : "https://github.com/mobify/bellows.git" }, - "version": "5.1.1", + "version": "5.1.2", "description": "A mobile first accordion UI plugin", "devDependencies": { "grunt": "~0.4.x", diff --git a/src/js/bellows.js b/src/js/bellows.js index e234c23..ba2bc91 100644 --- a/src/js/bellows.js +++ b/src/js/bellows.js @@ -67,9 +67,9 @@ /** * Ghetto Event Delegation™ - Zepto doesn't support descendant selectors in event delegation, - so we compare against the closest bellows to ensure we are invoking - the event from a direct child, not a bellows child from a nested bellows. + Zepto doesn't support descendant selectors in event delegation, + so we compare against the closest bellows to ensure we are invoking + the event from a direct child, not a bellows child from a nested bellows. */ this.$bellows .on(events.CLICK, function(e) { @@ -118,6 +118,14 @@ return item; }, + _isOpen: function($item) { + return $item.hasClass(cssClasses.OPENED); + }, + + _isDisabled: function($item) { + return $item.hasClass(cssClasses.DISABLED); + }, + _wrapContent: function($items) { $items .find(selectors.ITEM_CONTENT) @@ -138,7 +146,7 @@ open: function($item) { $item = this._item($item); - if ($item.hasClass(cssClasses.OPENED) || $item.hasClass(cssClasses.DISABLED)) { + if (this._isOpen($item) || this._isDisabled($item)) { return; } @@ -149,7 +157,7 @@ this.closeAll(); } - this._trigger('open', { item: $item }); + this._trigger('open', {item: $item}); Velocity .animate($contentWrapper, 'slideDown', { @@ -168,7 +176,7 @@ plugin._setHeight(); - plugin._trigger('opened', { item: $item }); + plugin._trigger('opened', {item: $item}); } }); }, @@ -176,14 +184,14 @@ close: function($item) { $item = this._item($item); - if (!$item.hasClass(cssClasses.OPENED)) { + if (!this._isOpen($item) || this._isDisabled($item)) { return; } var plugin = this; var $contentWrapper = $item.find(selectors.ITEM_CONTENT_WRAPPER); - this._trigger('close', { item: $item }); + this._trigger('close', {item: $item}); Velocity .animate($contentWrapper, 'slideUp', { @@ -203,7 +211,7 @@ plugin._setHeight(); - plugin._trigger('closed', { item: $item }); + plugin._trigger('closed', {item: $item}); } }); }, diff --git a/tests/fixtures/open-disabled-item.html b/tests/fixtures/open-disabled-item.html new file mode 100644 index 0000000..de0aa67 --- /dev/null +++ b/tests/fixtures/open-disabled-item.html @@ -0,0 +1,4 @@ +
+
Header
+
Content
+
diff --git a/tests/unit/plugin.js b/tests/unit/plugin.js index 98dcf4d..c59557c 100644 --- a/tests/unit/plugin.js +++ b/tests/unit/plugin.js @@ -3,8 +3,9 @@ define([ 'text!fixtures/bellows.html', 'text!fixtures/items.html', 'text!fixtures/item.html', - 'text!fixtures/disableditem.html' -], function(testSandbox, fixture, items, item, disabledItem) { + 'text!fixtures/disableditem.html', + 'text!fixtures/open-disabled-item.html' +], function(testSandbox, fixture, items, item, disabledItem, openDisabledItem) { var Bellows; var $element; var $; @@ -180,7 +181,7 @@ define([ }, closed: function(e, ui) { closeCount++; - + if (closeCount === 2) { expect($element.find('.bellows__item:not(.bellows--is-open)')).to.have.length(2); done(); @@ -251,7 +252,7 @@ define([ }); describe('disabling a bellows item', function() { - it('does not open item when header clicked', function(done) { + it('does not open item when header clicked', function() { $element.bellows(); var $disabledItem = $(disabledItem); @@ -262,12 +263,24 @@ define([ .find('.bellows__header') .trigger('click'); - setTimeout(function() { - expect($disabledItem.hasClass('bellows--is-disabled')).to.be.true; - expect($disabledItem.hasClass('bellows--is-open')).to.be.false; - done(); - }); + expect($disabledItem.hasClass('bellows--is-disabled')).to.be.true; + expect($disabledItem.hasClass('bellows--is-open')).to.be.false; + }); + + it('does not close item when header clicked', function() { + $element.bellows(); + + var $openDisabledItem = $(openDisabledItem); + + $element.bellows('add', $openDisabledItem); + + $openDisabledItem + .find('.bellows__header') + .trigger('click'); + + expect($openDisabledItem.hasClass('bellows--is-disabled')).to.be.true; + expect($openDisabledItem.hasClass('bellows--is-open')).to.be.true; }); }); }); -}); \ No newline at end of file +});