diff --git a/common.blocks/popup/_autoclosable/popup_autoclosable.deps.js b/common.blocks/popup/_autoclosable/popup_autoclosable.deps.js index 2460de966..36457a46b 100644 --- a/common.blocks/popup/_autoclosable/popup_autoclosable.deps.js +++ b/common.blocks/popup/_autoclosable/popup_autoclosable.deps.js @@ -1,8 +1,13 @@ -({ +[{ shouldDeps : [ + { mods : { target : 'anchor' } }, // should be removed after bem-pr and enb-specs will fix depsByTech { block : 'jquery', elems : { elem : 'event', mods : { type : 'pointer' } } }, { block : 'keyboard', elem : 'codes' }, 'ua', 'dom' ] -}) +}, +{ + tech : 'spec.js', + shouldDeps : { tech : 'js', mods : { target : 'anchor' } } +}] diff --git a/common.blocks/popup/_autoclosable/popup_autoclosable.js b/common.blocks/popup/_autoclosable/popup_autoclosable.js index 32469a211..040d124b1 100644 --- a/common.blocks/popup/_autoclosable/popup_autoclosable.js +++ b/common.blocks/popup/_autoclosable/popup_autoclosable.js @@ -38,7 +38,7 @@ provide(Popup.decl({ modName : 'autoclosable', modVal : true }, /** @lends popup }, _onDocPointerClick : function(e) { - if(this._owner && dom.contains(this._owner, $(e.target))) + if(this.hasMod('target', 'anchor') && dom.contains(this._anchor, $(e.target))) return; this._inPopupPointerPress? diff --git a/common.blocks/popup/_autoclosable/popup_autoclosable.spec.js b/common.blocks/popup/_autoclosable/popup_autoclosable.spec.js index fb0c14455..be73e1b2b 100644 --- a/common.blocks/popup/_autoclosable/popup_autoclosable.spec.js +++ b/common.blocks/popup/_autoclosable/popup_autoclosable.spec.js @@ -16,7 +16,7 @@ describe('popup_autoclosable', function() { describe('pointer reactions', function() { it('should be visible on click inside', function(done) { - var popup = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'); + var popup = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'); nextTick(function() { doPointerClick(popup.domElem); @@ -27,7 +27,7 @@ describe('popup_autoclosable', function() { }); it('should be hidden on click outside', function(done) { - var popup = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'); + var popup = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'); nextTick(function() { doPointerClick(rootDomElem); @@ -37,13 +37,13 @@ describe('popup_autoclosable', function() { }); }); - it('should not be hidden on owner click', function(done) { - var popupWithOwner = buildPopupWithOwner(rootDomElem, true), - ownerDomElem = popupWithOwner.ownerDomElem, + it('should not be hidden on anchor click', function(done) { + var popupWithOwner = buildPopupWithAnchor(rootDomElem, true), + anchorDomElem = popupWithOwner.anchorDomElem, popup = popupWithOwner.popup.setMod('visible'); nextTick(function() { - doPointerClick(ownerDomElem); + doPointerClick(anchorDomElem); popup.hasMod('visible').should.be.true; done(); @@ -51,10 +51,10 @@ describe('popup_autoclosable', function() { }); it('should not be hidden on click on child popup', function(done) { - var popup1 = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'), - popup2 = buildPopupWithOwner(popup1.domElem).popup.setMod('visible'), - popup3 = buildPopupWithOwner(popup2.domElem, true).popup.setMod('visible'), - popup4 = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'); + var popup1 = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'), + popup2 = buildPopupWithAnchor(popup1.domElem).popup.setMod('visible'), + popup3 = buildPopupWithAnchor(popup2.domElem, true).popup.setMod('visible'), + popup4 = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'); nextTick(function() { doPointerClick(popup3.domElem); @@ -77,15 +77,15 @@ describe('popup_autoclosable', function() { describe('on escape key reactions', function() { it('should be hidden on press escape', function() { - var popup = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'); + var popup = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'); rootDomElem.trigger($.Event('keydown', { keyCode : keyCodes.ESC })); popup.hasMod('visible').should.be.false; }); it('should hide popups in back order of its showing', function() { - var popup1 = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'), - popup2 = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'), - popup3 = buildPopupWithOwner(rootDomElem, true).popup.setMod('visible'), + var popup1 = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'), + popup2 = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'), + popup3 = buildPopupWithAnchor(rootDomElem, true).popup.setMod('visible'), event = $.Event('keydown', { keyCode : keyCodes.ESC }); rootDomElem.trigger(event); @@ -108,19 +108,23 @@ describe('popup_autoclosable', function() { provide(); -function buildPopupWithOwner(parentDomElem, isAutoclosable) { - var ownerDomElem = $(BEMHTML.apply({ +function buildPopupWithAnchor(parentDomElem, isAutoclosable) { + var anchorDomElem = $(BEMHTML.apply({ tag : 'span', - content : 'owner' + content : 'anchor' })).appendTo(parentDomElem); return { - ownerDomElem : ownerDomElem, + anchorDomElem : anchorDomElem, popup : BEMDOM.init( - $(BEMHTML.apply({ block : 'popup', content : 'content', mods : { autoclosable : isAutoclosable } })) + $(BEMHTML.apply({ + block : 'popup', + mods : { target : 'anchor', autoclosable : isAutoclosable }, + content : 'content' + })) .appendTo(parentDomElem)) - .bem('popup') - .setTarget(ownerDomElem) + .bem('popup') + .setAnchor(anchorDomElem) }; } diff --git a/common.blocks/popup/_target/popup_target.js b/common.blocks/popup/_target/popup_target.js index cded7f489..647b8b82d 100644 --- a/common.blocks/popup/_target/popup_target.js +++ b/common.blocks/popup/_target/popup_target.js @@ -96,8 +96,7 @@ provide(Popup.decl({ modName : 'target' }, /** @lends popup.prototype */{ _calcDrawingCss : function(drawingParams) { return { left : drawingParams.left, - top : drawingParams.top, - zIndex : this._zIndex + top : drawingParams.top }; }, diff --git a/common.blocks/popup/_target/popup_target_anchor.spec.js b/common.blocks/popup/_target/popup_target_anchor.spec.js new file mode 100644 index 000000000..3fdfa21b8 --- /dev/null +++ b/common.blocks/popup/_target/popup_target_anchor.spec.js @@ -0,0 +1,303 @@ +modules.define( + 'spec', + ['popup', 'i-bem__dom', 'jquery', 'BEMHTML'], + function(provide, Popup, BEMDOM, $, BEMHTML) { + +describe('popup', function() { + var popup, popupDomElem, popupParentDomElem, popupAnchorDomElem, + win = $(window), + winWidth = win.width(), + winHeight = win.height(), + UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL = 100, + POPUP_MAIN_OFFSET = 5; + + beforeEach(function() { + popupParentDomElem = $(BEMHTML.apply({ tag : 'div' })).appendTo('body'); + popupAnchorDomElem = $(BEMHTML.apply({ + tag : 'span', + content : 'anchor' + })).appendTo(popupParentDomElem); + popup = buildPopup( + popupParentDomElem, + { + block : 'popup', + mods : { target : 'anchor' }, + mainOffset : POPUP_MAIN_OFFSET, + content : 'content' + }); + popupDomElem = popup.domElem; + }); + + afterEach(function() { + BEMDOM.destruct(popupParentDomElem); + }); + + describe('setAnchor', function() { + it('should throw "Error" if no anchor set', function() { + popup.setMod.bind(popup, 'visible').should.to.throw(Error); + }); + + it('should consume DOM elem as a target', function() { + popup + .setAnchor(popupAnchorDomElem) + .setMod('visible'); + + var anchorOffset = popupAnchorDomElem.offset(), + popupOffset = popupDomElem.offset(); + + popupOffset.top.should.be.equal( + anchorOffset.top + popupAnchorDomElem.outerHeight() + popup.params.mainOffset, + 'invalid top'); + popupOffset.left.should.be.equal( + anchorOffset.left, + 'invalid left'); + }); + }); + + describe('directions', function() { + var margin = 10, + popupWidth = winWidth - POPUP_MAIN_OFFSET - margin, + popupHeight = winHeight - POPUP_MAIN_OFFSET - margin, + variants = [ + [margin, margin, 'bottom-left'], + [winWidth - popupWidth / 2, margin, 'bottom-center'], + [winWidth - margin, margin, 'bottom-right'], + [margin, winHeight - margin, 'top-left'], + [winWidth - popupWidth / 2, winHeight - margin, 'top-center'], + [winWidth - margin, winHeight - margin, 'top-right'], + [margin, winHeight - popupHeight + POPUP_MAIN_OFFSET / 2, 'right-top'], + [margin, winHeight - popupHeight / 2, 'right-center'], + [margin, winHeight - margin - POPUP_MAIN_OFFSET * 1.5, 'right-bottom'], + [winWidth - margin, winHeight - popupHeight, 'left-top'], + [winWidth - margin, winHeight - popupHeight / 2, 'left-center'], + [winWidth - margin, winHeight - margin - POPUP_MAIN_OFFSET * 1.5, 'left-bottom'] + ]; + + beforeEach(function() { + popup.domElem.css({ width : popupWidth, height : popupHeight }); + }); + + afterEach(function() { + popup.delMod('visible'); + }); + + describe('relative to anchor', function() { + beforeEach(function() { + popupAnchorDomElem.css({ + position : 'absolute', + width : 1, + height : 1, + display : 'block', + overflow : 'hidden' + }); + }); + + variants.forEach(function(data) { + it('should be opened in "' + data[2] + '" direction', function() { + popupAnchorDomElem.css({ left : data[0], top : data[1] }); + popup + .setAnchor(popupAnchorDomElem) + .setMod('visible') + .getMod('direction') + .should.be.equal(data[2]); + }); + }); + }); + }); + + describe('scroll reactions', function() { + it('should not be hidden on window scroll', function(done) { + var timeout = UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL + UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL / 2; + + popupParentDomElem.height(winHeight + 2 * popupAnchorDomElem.height()); + + popup + .setAnchor(popupAnchorDomElem) + .setMod('visible'); + + popupDomElem.css('display').should.not.be.equal('none'); + + win.scrollTop(popupAnchorDomElem.offset().top + popupAnchorDomElem.height()); + + setTimeout(function() { + popupDomElem.css('display').should.not.be.equal('none'); + done(); + }, timeout); + }); + + it('should be hidden in nested scrolled container', function(done) { + var timeout = UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL + UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL / 2, + anchorHeight = popupAnchorDomElem.height(); + + popupParentDomElem + .append('
') + .css({ + overflow : 'auto', + marginTop : 2 * anchorHeight, + height : 2 * anchorHeight + }); + + popup + .setAnchor(popupAnchorDomElem) + .setMod('visible'); + + popupDomElem.css('display').should.not.be.equal('none', 'wrong display on visible anchor'); + + popupParentDomElem.scrollTop(3 * anchorHeight); + + setTimeout(function() { + popupDomElem.css('display').should.be.equal('none', 'wrong display on hidden anchor'); + popupParentDomElem.scrollTop(0); + setTimeout(function() { + popupDomElem.css('display').should.not.be.equal( + 'none', + 'wrong display on restore anchor visibility'); + popupParentDomElem.scrollTop(0); + done(); + }, timeout); + }, timeout); + }); + }); + + describe('nested popups', function() { + var childPopup, childAnchorDomElem; + beforeEach(function() { + popup.setAnchor(popupAnchorDomElem); + childAnchorDomElem = $(BEMHTML.apply({ tag : 'span', content : 'child anchor' })) + .appendTo(popupDomElem); + childPopup = buildPopup( + popupDomElem, + { + block : 'popup', + mods : { target : 'anchor' }, + content : 'child content' + }).setAnchor(childAnchorDomElem); + }); + + it('should hide nested popups', function() { + popup.setMod('visible'); + childPopup.setMod('visible'); + popup.delMod('visible'); + childPopup.hasMod('visible').should.be.false; + }); + }); + + describe('z-index groups', function() { + beforeEach(function() { + popup.setAnchor(popupAnchorDomElem); + }); + + it('should be z-indexed in open order by default', function() { + var popup2 = buildPopup( + popupParentDomElem, + { + block : 'popup', + mods : { target : 'anchor' }, + content : 'content 2' + }).setAnchor(popupAnchorDomElem); + + popup2.setMod('visible'); + popup.setMod('visible'); + + Number(popup.domElem.css('z-index')) + .should.be.gt(Number(popup2.domElem.css('z-index'))); + }); + + it('should properly use zIndexGroupLevel param', function() { + var popup2 = buildPopup( + popupParentDomElem, + { + block : 'popup', + mods : { target : 'anchor' }, + zIndexGroupLevel : 1, + content : 'content 2' + }).setAnchor(popupAnchorDomElem); + + popup2.setMod('visible'); + popup.setMod('visible'); + + Number(popup.domElem.css('z-index')) + .should.be.lt(Number(popup2.domElem.css('z-index'))); + }); + + it('should properly use z-index-group blocks which may be in anchor parents', function() { + var zIndexGroup1 = $(BEMHTML.apply({ + block : 'z-index-group', + mods : { level : 1 }, + content : { tag : 'span', content : 'anchor 2' } + })).appendTo(popupParentDomElem), + popup2 = buildPopup( + zIndexGroup1, + { + block : 'popup', + mods : { target : 'anchor' }, + content : 'content 2' + }).setAnchor(zIndexGroup1.find('span:first')), + zIndexGroup2 = $(BEMHTML.apply({ + block : 'z-index-group', + mods : { level : 1 }, + content : { tag : 'span', content : 'anchor 3' } + })).appendTo(zIndexGroup1), + popup3 = buildPopup( + zIndexGroup2, + { + block : 'popup', + mods : { target : 'anchor' }, + content : 'content 3' + }).setAnchor(zIndexGroup2.find('span:first')); + + popup3.setMod('visible'); + popup2.setMod('visible'); + popup.setMod('visible'); + + Number(popup.domElem.css('z-index')) + .should.be.lt(Number(popup2.domElem.css('z-index'))); + + Number(popup2.domElem.css('z-index')) + .should.be.lt(Number(popup3.domElem.css('z-index'))); + }); + + it('should consider zIndexGroupLevel of parent popup', function() { + var popup2 = buildPopup( + popupParentDomElem, + { + block : 'popup', + mods : { target : 'anchor' }, + zIndexGroupLevel : 1, + content : { tag : 'span', content : 'anchor 2' } + }); + + popup.setMod('visible'); + popup2.setAnchor(popupAnchorDomElem).setMod('visible'); + + Number(popup.domElem.css('z-index')) + .should.be.lt(Number(popup2.domElem.css('z-index'))); + + popup.setAnchor(popup2.domElem.find('span:first')); + + Number(popup.domElem.css('z-index')) + .should.be.gt(Number(popup2.domElem.css('z-index'))); + }); + }); + + describe('destructing', function() { + it('should be destructed on anchor destruct', function() { + popup + .setAnchor(popupAnchorDomElem) + .setMod('visible'); + + BEMDOM.destruct(popupAnchorDomElem); + + popup.hasMod('js').should.be.false; + }); + }); +}); + +provide(); + +function buildPopup(parentDomElem, bemjson) { + return BEMDOM.init($(BEMHTML.apply(bemjson)).appendTo(parentDomElem)) + .bem('popup'); +} + +}); diff --git a/common.blocks/popup/_target/popup_target_position.spec.js b/common.blocks/popup/_target/popup_target_position.spec.js new file mode 100644 index 000000000..ae0270ea7 --- /dev/null +++ b/common.blocks/popup/_target/popup_target_position.spec.js @@ -0,0 +1,135 @@ +modules.define( + 'spec', + ['popup', 'i-bem__dom', 'jquery', 'BEMHTML'], + function(provide, Popup, BEMDOM, $, BEMHTML) { + +describe('popup', function() { + var popup, popupDomElem, popupParentDomElem, popupOwnerDomElem, + win = $(window), + winWidth = win.width(), + winHeight = win.height(), + POPUP_MAIN_OFFSET = 5; + + beforeEach(function() { + popupParentDomElem = $(BEMHTML.apply({ tag : 'div' })).appendTo('body'); + popupOwnerDomElem = $(BEMHTML.apply({ + tag : 'span', + content : 'owner' + })).appendTo(popupParentDomElem); + popup = buildPopup( + popupParentDomElem, + { + block : 'popup', + mods : { target : 'position' }, + mainOffset : POPUP_MAIN_OFFSET, + content : 'content' + }); + popupDomElem = popup.domElem; + }); + + afterEach(function() { + BEMDOM.destruct(popupParentDomElem); + }); + + describe('setPosition', function() { + it('should throw "Error" if no position set', function() { + popup.setMod.bind(popup, 'visible').should.to.throw(Error); + }); + + it('should consume x and y coordinates', function() { + var coords = { + top : 10, + left : 10 + }; + + popup + .setPosition(coords.top, coords.left) + .setMod('visible'); + + var popupOffset = popupDomElem.offset(); + popupOffset.top.should.be.equal(coords.top + popup.params.mainOffset); + popupOffset.left.should.be.equal(coords.left); + + BEMDOM.destruct(popupDomElem); + }); + }); + + describe('directions', function() { + var margin = 10, + popupWidth = winWidth - POPUP_MAIN_OFFSET - margin, + popupHeight = winHeight - POPUP_MAIN_OFFSET - margin, + variants = [ + [margin, margin, 'bottom-left'], + [winWidth - popupWidth / 2, margin, 'bottom-center'], + [winWidth - margin, margin, 'bottom-right'], + [margin, winHeight - margin, 'top-left'], + [winWidth - popupWidth / 2, winHeight - margin, 'top-center'], + [winWidth - margin, winHeight - margin, 'top-right'], + [margin, winHeight - popupHeight + POPUP_MAIN_OFFSET / 2, 'right-top'], + [margin, winHeight - popupHeight / 2, 'right-center'], + [margin, winHeight - margin - POPUP_MAIN_OFFSET * 1.5, 'right-bottom'], + [winWidth - margin, winHeight - popupHeight, 'left-top'], + [winWidth - margin, winHeight - popupHeight / 2, 'left-center'], + [winWidth - margin, winHeight - margin - POPUP_MAIN_OFFSET * 1.5, 'left-bottom'] + ]; + + beforeEach(function() { + popup.domElem.css({ width : popupWidth, height : popupHeight }); + }); + + afterEach(function() { + popup.delMod('visible'); + }); + + describe('relative to position', function() { + variants.forEach(function(data) { + it('should be opened in "' + data[2] + '" direction', function() { + popup + .setPosition(data[0], data[1]) + .setMod('visible') + .getMod('direction') + .should.be.equal(data[2]); + + BEMDOM.destruct(popupDomElem); + }); + }); + }); + }); + + describe('setContent and redraw', function() { + it('should be redrawed when content is changed', function() { + var size = Math.min(winWidth / 3, winHeight / 3); + popup + .setContent( + BEMHTML.apply({ + tag : 'div', + attrs : { style : 'width: ' + size + 'px; height: ' + size + 'px;' + } + })) + .setPosition(winWidth - size - 1, winHeight - size - popup.params.mainOffset) + .setMod('visible'); + + popup.getMod('direction').should.be.equal('bottom-left'); + + popup.setContent( + BEMHTML.apply({ + tag : 'div', + attrs : { style : 'width: ' + (size * 2) + 'px; height: ' + (size * 2) + 'px;' + } + })); + + popup.getMod('direction').should.be.equal('left-center'); + + BEMDOM.destruct(popupDomElem); + }); + }); +}); + +provide(); + +function buildPopup(parentDomElem, bemjson) { + return BEMDOM.init($(BEMHTML.apply(bemjson)).appendTo(parentDomElem)) + .bem('popup'); +} + +}); diff --git a/common.blocks/popup/popup.js b/common.blocks/popup/popup.js index 4ce6698f8..ed1be82d9 100644 --- a/common.blocks/popup/popup.js +++ b/common.blocks/popup/popup.js @@ -107,11 +107,13 @@ provide(BEMDOM.decl(this.name, /** @lends popup.prototype */{ _captureZIndex : function() { var level = this._zIndexGroupLevel === null? - this._zIndexGroupLevel = this._calcZIndexGroupLevel() : - this._zIndexGroupLevel; + this._zIndexGroupLevel = this._calcZIndexGroupLevel() : + this._zIndexGroupLevel, + zIndexes = visiblePopupsZIndexes[level] || (visiblePopupsZIndexes[level] = [(level + 1) * ZINDEX_FACTOR]), + prevZIndex = this._zIndex; - var zIndexes = visiblePopupsZIndexes[level] || (visiblePopupsZIndexes[level] = [(level + 1) * ZINDEX_FACTOR]); this._zIndex = zIndexes[zIndexes.push(zIndexes[zIndexes.length - 1] + 1) - 1]; + this._zIndex !== prevZIndex && this.domElem.css('z-index', this._zIndex); return this; }, diff --git a/common.blocks/popup/popup.spec.js b/common.blocks/popup/popup.spec.js index a1aef82a9..7d6f1a6fa 100644 --- a/common.blocks/popup/popup.spec.js +++ b/common.blocks/popup/popup.spec.js @@ -4,24 +4,15 @@ modules.define( function(provide, Popup, BEMDOM, $, BEMHTML) { describe('popup', function() { - var popup, popupDomElem, popupParentDomElem, popupOwnerDomElem, - win = $(window), - winWidth = win.width(), - winHeight = win.height(), - UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL = 100, - POPUP_MAIN_OFFSET = 5; + var popup, popupDomElem, popupParentDomElem; beforeEach(function() { popupParentDomElem = $(BEMHTML.apply({ tag : 'div' })).appendTo('body'); - popupOwnerDomElem = $(BEMHTML.apply({ - tag : 'span', - content : 'owner' - })).appendTo(popupParentDomElem); popup = buildPopup( popupParentDomElem, { block : 'popup', - mainOffset : POPUP_MAIN_OFFSET, + zIndexGroupLevel : 2, content : 'content' }); popupDomElem = popup.domElem; @@ -31,325 +22,28 @@ describe('popup', function() { BEMDOM.destruct(popupParentDomElem); }); - describe('setTarget', function() { - it('should throw "Error" if no target set', function() { - popup.setMod.bind(popup, 'visible').should.to.throw(Error); - }); - - it('should consume x and y coordinates as targets', function() { - var coords = { - top : 10, - left : 10 - }; - - popup - .setTarget(coords.top, coords.left) - .setMod('visible'); - - var popupOffset = popupDomElem.offset(); - popupOffset.top.should.be.equal(coords.top + popup.params.mainOffset); - popupOffset.left.should.be.equal(coords.left); - - BEMDOM.destruct(popupDomElem); - }); - - it('should consume DOM elem as a target', function() { - popup - .setTarget(popupOwnerDomElem) - .setMod('visible'); - - var ownerOffset = popupOwnerDomElem.offset(), - popupOffset = popupDomElem.offset(); - - popupOffset.top.should.be.equal( - ownerOffset.top + popupOwnerDomElem.outerHeight() + popup.params.mainOffset, - 'invalid top'); - popupOffset.left.should.be.equal( - ownerOffset.left, - 'invalid left'); - }); - }); - describe('attachment to body', function() { it('should be attached to body on first opening', function() { popup.domElem.parent()[0].should.be.eql(popupParentDomElem[0], 'misplaced on init'); - popup - .setTarget(0, 0) - .setMod('visible'); + popup.setMod('visible'); popup.domElem.parent()[0].should.be.eql($('body')[0], 'misplaced on visible'); - - BEMDOM.destruct(popupDomElem); - }); - }); - - describe('directions', function() { - var margin = 10, - popupWidth = winWidth - POPUP_MAIN_OFFSET - margin, - popupHeight = winHeight - POPUP_MAIN_OFFSET - margin, - variants = [ - [margin, margin, 'bottom-left'], - [winWidth - popupWidth / 2, margin, 'bottom-center'], - [winWidth - margin, margin, 'bottom-right'], - [margin, winHeight - margin, 'top-left'], - [winWidth - popupWidth / 2, winHeight - margin, 'top-center'], - [winWidth - margin, winHeight - margin, 'top-right'], - [margin, winHeight - popupHeight + POPUP_MAIN_OFFSET / 2, 'right-top'], - [margin, winHeight - popupHeight / 2, 'right-center'], - [margin, winHeight - margin - POPUP_MAIN_OFFSET * 1.5, 'right-bottom'], - [winWidth - margin, winHeight - popupHeight, 'left-top'], - [winWidth - margin, winHeight - popupHeight / 2, 'left-center'], - [winWidth - margin, winHeight - margin - POPUP_MAIN_OFFSET * 1.5, 'left-bottom'] - ]; - - beforeEach(function() { - popup.domElem.css({ width : popupWidth, height : popupHeight }); - }); - - afterEach(function() { - popup.delMod('visible'); - }); - - describe('relative to position', function() { - variants.forEach(function(data) { - it('should be opened in "' + data[2] + '" direction', function() { - popup - .setTarget(data[0], data[1]) - .setMod('visible') - .getMod('direction') - .should.be.equal(data[2]); - - BEMDOM.destruct(popupDomElem); - }); - }); - }); - - describe('relative to owner', function() { - beforeEach(function() { - popupOwnerDomElem.css({ - position : 'absolute', - width : 1, - height : 1, - display : 'block', - overflow : 'hidden' - }); - }); - - variants.forEach(function(data) { - it('should be opened in "' + data[2] + '" direction', function() { - popupOwnerDomElem.css({ left : data[0], top : data[1] }); - popup - .setTarget(popupOwnerDomElem) - .setMod('visible') - .getMod('direction') - .should.be.equal(data[2]); - }); - }); - }); - }); - - describe('scroll reactions', function() { - it('should not be hidden on window scroll', function(done) { - var timeout = UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL + UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL / 2; - - popupParentDomElem.height(winHeight + 2 * popupOwnerDomElem.height()); - - popup - .setTarget(popupOwnerDomElem) - .setMod('visible'); - - popupDomElem.css('display').should.not.be.equal('none'); - - win.scrollTop(popupOwnerDomElem.offset().top + popupOwnerDomElem.height()); - - setTimeout(function() { - popupDomElem.css('display').should.not.be.equal('none'); - done(); - }, timeout); - }); - - it('should be hidden in nested scrolled container', function(done) { - var timeout = UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL + UPDATE_TARGET_VISIBILITY_THROTTLING_INTERVAL / 2, - ownerHeight = popupOwnerDomElem.height(); - - popupParentDomElem - .append('
') - .css({ - overflow : 'auto', - marginTop : 2 * ownerHeight, - height : 2 * ownerHeight - }); - - popup - .setTarget(popupOwnerDomElem) - .setMod('visible'); - - popupDomElem.css('display').should.not.be.equal('none', 'wrong display on visible owner'); - - popupParentDomElem.scrollTop(3 * ownerHeight); - - setTimeout(function() { - popupDomElem.css('display').should.be.equal('none', 'wrong display on hidden owner'); - popupParentDomElem.scrollTop(0); - setTimeout(function() { - popupDomElem.css('display').should.not.be.equal( - 'none', - 'wrong display on restore owner visibility'); - popupParentDomElem.scrollTop(0); - done(); - }, timeout); - }, timeout); - }); - }); - - describe('setContent and redraw', function() { - it('should be redrawed when content is changed', function() { - var size = Math.min(winWidth / 3, winHeight / 3); - popup - .setContent( - BEMHTML.apply({ - tag : 'div', - attrs : { style : 'width: ' + size + 'px; height: ' + size + 'px;' - } - })) - .setTarget(winWidth - size - 1, winHeight - size - popup.params.mainOffset) - .setMod('visible'); - - popup.getMod('direction').should.be.equal('bottom-left'); - - popup.setContent( - BEMHTML.apply({ - tag : 'div', - attrs : { style : 'width: ' + (size * 2) + 'px; height: ' + (size * 2) + 'px;' - } - })); - - popup.getMod('direction').should.be.equal('left-center'); - BEMDOM.destruct(popupDomElem); }); }); - describe('nested popups', function() { - var childPopup, childOwnerDomElem; - beforeEach(function() { - popup.setTarget(popupOwnerDomElem); - childOwnerDomElem = $(BEMHTML.apply({ tag : 'span', content : 'child owner' })) - .appendTo(popupDomElem); - childPopup = buildPopup( - popupDomElem, - { block : 'popup', content : 'child content' }) - .setTarget(childOwnerDomElem); - }); - - it('should hide nested popups', function() { - popup.setMod('visible'); - childPopup.setMod('visible'); - popup.delMod('visible'); - childPopup.hasMod('visible').should.be.false; - }); - }); - - describe('z-index groups', function() { - beforeEach(function() { - popup.setTarget(popupOwnerDomElem); - }); - - it('should be z-indexed in open order by default', function() { - var popup2 = buildPopup( - popupParentDomElem, - { block : 'popup', content : 'content 2' }) - .setTarget(popupOwnerDomElem); - - popup2.setMod('visible'); - popup.setMod('visible'); - - Number(popup.domElem.css('z-index')) - .should.be.gt(Number(popup2.domElem.css('z-index'))); - }); - - it('should properly use zIndexGroupLevel param', function() { - var popup2 = buildPopup( - popupParentDomElem, - { block : 'popup', zIndexGroupLevel : 1, content : 'content 2' }) - .setTarget(popupOwnerDomElem); - - popup2.setMod('visible'); - popup.setMod('visible'); - - Number(popup.domElem.css('z-index')) - .should.be.lt(Number(popup2.domElem.css('z-index'))); - }); - - it('should properly use z-index-group blocks which may be in owner parents', function() { - var zIndexGroup1 = $(BEMHTML.apply({ - block : 'z-index-group', - mods : { level : 1 }, - content : { tag : 'span', content : 'owner 2' } - })).appendTo(popupParentDomElem), - popup2 = buildPopup( - zIndexGroup1, - { block : 'popup', content : 'content 2' }) - .setTarget(zIndexGroup1.find('span:first')), - zIndexGroup2 = $(BEMHTML.apply({ - block : 'z-index-group', - mods : { level : 1 }, - content : { tag : 'span', content : 'owner 3' } - })).appendTo(zIndexGroup1), - popup3 = buildPopup( - zIndexGroup2, - { block : 'popup', content : 'content 3' }) - .setTarget(zIndexGroup2.find('span:first')); - - popup3.setMod('visible'); - popup2.setMod('visible'); - popup.setMod('visible'); - - Number(popup.domElem.css('z-index')) - .should.be.lt(Number(popup2.domElem.css('z-index'))); - - Number(popup2.domElem.css('z-index')) - .should.be.lt(Number(popup3.domElem.css('z-index'))); - }); - - it('should consider zIndexGroupLevel of parent popup', function() { - var popup2 = buildPopup( - popupParentDomElem, - { block : 'popup', zIndexGroupLevel : 1, - content : { tag : 'span', content : 'owner 2' } }); - + describe('z-index', function() { + it('should properly calculate z-index', function() { popup.setMod('visible'); - popup2.setTarget(popupOwnerDomElem).setMod('visible'); - - Number(popup.domElem.css('z-index')) - .should.be.lt(Number(popup2.domElem.css('z-index'))); - - popup.setTarget(popup2.domElem.find('span:first')); - - Number(popup.domElem.css('z-index')) - .should.be.gt(Number(popup2.domElem.css('z-index'))); + Number(popupDomElem.css('z-index')).should.be.equal(3001); }); }); describe('destructing', function() { it('should be hidden on destruct', function() { - popup - .setTarget(popupOwnerDomElem) - .setMod('visible'); - + popup.setMod('visible'); BEMDOM.destruct(popupDomElem); - popup.hasMod('visible').should.be.false; }); - - it('should be destructed on owner destruct', function() { - popup - .setTarget(popupOwnerDomElem) - .setMod('visible'); - - BEMDOM.destruct(popupOwnerDomElem); - - popup.hasMod('js').should.be.false; - }); }); });