Skip to content

Commit

Permalink
Merge pull request #541 from /issues/540@v2
Browse files Browse the repository at this point in the history
i-bem__dom: remove DOM before destructing BEM internals
  • Loading branch information
Vladimir Varankin committed Jun 4, 2014
2 parents cc83ee1 + 54b562c commit a23e405
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 50 deletions.
37 changes: 31 additions & 6 deletions common.blocks/i-bem/__dom/i-bem__dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ var undef,
*/
uniqIdToBlock = {},

/**
* Storage for DOM element's parent nodes
* @type Object
*/
domNodesToParents = {},

/**
* Storage for block parameters
* @type Object
Expand Down Expand Up @@ -196,6 +202,16 @@ function removeDomNodeFromBlock(block, domNode) {
block.domElem = block.domElem.not(domNode);
}

/**
* Fills DOM node's parent nodes to the storage
* @param {jQuery} domElem
*/
function storeDomNodeParents(domElem) {
domElem.each(function() {
domNodesToParents[identify(this)] = this.parentNode;
});
}

/**
* @class BEMDOM
* @description Base block for creating BEM blocks that have DOM representation
Expand Down Expand Up @@ -521,9 +537,8 @@ var DOM = BEM.decl('i-bem__dom',/** @lends BEMDOM.prototype */{
storage = liveEventCtxStorage[_this.__self._buildCtxEventName(e.type)],
ctxIds = {};

storage && _this.domElem.each(function() {
var ctx = this,
counter = storage.counter;
storage && _this.domElem.each(function(_, ctx) {
var counter = storage.counter;
while(ctx && counter) {
var ctxId = identify(ctx, true);
if(ctxId) {
Expand All @@ -540,7 +555,7 @@ var DOM = BEM.decl('i-bem__dom',/** @lends BEMDOM.prototype */{
}
ctxIds[ctxId] = true;
}
ctx = ctx.parentNode;
ctx = ctx.parentNode || domNodesToParents[ctxId];
}
});
},
Expand Down Expand Up @@ -912,7 +927,16 @@ var DOM = BEM.decl('i-bem__dom',/** @lends BEMDOM.prototype */{
* @param {Boolean} [excludeSelf=false] Exclude the main domElem
*/
destruct : function(ctx, excludeSelf) {
reverse.call(findDomElem(ctx, BEM_SELECTOR, excludeSelf)).each(function(i, domNode) {
var _ctx;
if(excludeSelf) {
storeDomNodeParents(_ctx = ctx.children());
ctx.empty();
} else {
storeDomNodeParents(_ctx = ctx);
ctx.remove();
}

reverse.call(findDomElem(_ctx, BEM_SELECTOR)).each(function(_, domNode) {
var params = getParams(domNode);
objects.each(params, function(blockParams) {
if(blockParams.uniqId) {
Expand All @@ -925,7 +949,8 @@ var DOM = BEM.decl('i-bem__dom',/** @lends BEMDOM.prototype */{
delete domElemToParams[identify(domNode)];
});

excludeSelf? ctx.empty() : ctx.remove();
// flush parent nodes storage that has been filled above
domNodesToParents = {};
},

/**
Expand Down
79 changes: 35 additions & 44 deletions common.blocks/i-bem/__dom/i-bem__dom.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,50 +365,6 @@ describe('i-bem__dom', function() {

delete DOM.blocks['imp-block'];
});

it('should not create new block instance during domElem destructing (#518)', function() {
var spyHandler = sinon.spy(),
block1;

DOM.decl('block1', {}, {
live : function() {
this.liveBindTo('elem1', 'click', function() {
spyHandler();
this.should.be.eql(block1);
});
}
});

DOM.decl('block2', {
onSetMod : {
js : {
'' : function() {
this.domElem.trigger('click');
}
}
}
});

var domElem = $(BEMHTML.apply({
block : 'block1',
js : true,
content : {
block : 'block2',
mix : { block : 'block1', elem : 'elem1' },
js : true
}
})).appendTo('body');

DOM.init(domElem);
block1 = domElem.bem('block1');

DOM.destruct(domElem);

spyHandler.should.have.been.called;

delete DOM.blocks['block2'];
delete DOM.blocks['block1'];
});
});

describe('DOM.update', function() {
Expand Down Expand Up @@ -872,6 +828,41 @@ describe('i-bem__dom', function() {
delete DOM.blocks['block'];
});

it('should propagate destructing event', function() {
var spy = sinon.spy();

DOM.decl('block1', {
onSetMod : {
'js' : {
'inited' : function() {
DOM.blocks['block2'].on(this.domElem, { modName : 'js', modVal : '' }, spy);
}
}
}
});

DOM.decl('block2');

var domElem = $(BEMHTML.apply({
block : 'block1',
content : {
block : 'block2'
}
})).appendTo('body');

DOM.init(domElem);

var block1 = domElem.bem('block1'),
block2 = block1.findBlockInside('block2');

DOM.destruct(block2.domElem);

spy.should.have.been.called;

delete DOM.blocks['block2'];
delete DOM.blocks['block1'];
});

describe('elems', function() {
it('should emit event on elem mod change with correct arguments', function() {
var spy1 = sinon.spy(),
Expand Down

0 comments on commit a23e405

Please sign in to comment.