- From: Joseph Orbegoso Pea <notifications@github.com>
- Date: Tue, 29 Nov 2016 16:46:51 -0800
- To: w3c/webcomponents <webcomponents@noreply.github.com>
- Message-ID: <w3c/webcomponents/issues/611/263748417@github.com>
@hayato, check this out. Custom Elements in my library observe `slot` elements in order to mark those elements' shadowParent (i.e. the parent of the slot they are distributed to), and adds distributed children to a `shadowChildren` list of the parent the `slot`. On `slotchange` of a slot, this code is ran: ```js _handleDistributedChildren(slot) { const diff = this._getDistributedChildDifference(slot) for (const addedNode of diff.added) { // We do this because if the given slot is assigned to another // slot, then this logic will run again for the next slot on // that next slot's slotchange, so we remove the distributed // node from the previous shadowParent and add it to the next // one. If we don't do this, then the distributed node will // exist in multiple shadowChildren lists when there is an // assignedSlot list. For more info, see // https://github.com/w3c/webcomponents/issues/611 if (addedNode._shadowParent) addedNode._shadowParent._shadowChildren.delete(addedNode) addedNode._shadowParent = this this._shadowChildren.add(addedNode) } for (const removedNode of diff.removed) { removedNode._shadowParent = null this._shadowChildren.delete(removedNode) } } ``` where `_getDistributedChildDifference` returns an object containing `added` and `removed` properties which are lists of nodes that were distributed and undistributed, respectively, and looks like this: ```js _getDistributedChildDifference(slot) { let previousNodes if (this._slotElementsAssignedNodes.has(slot)) previousNodes = this._slotElementsAssignedNodes.get(slot) else previousNodes = [] const newNodes = slot.assignedNodes({flatten: true}) // save the newNodes to be used as the previousNodes for next time. this._slotElementsAssignedNodes.set(slot, newNodes) const diff = { removed: [], } for (let i=0, l=previousNodes.length; i<l; i+=1) { let oldNode = previousNodes[i] let newIndex = newNodes.indexOf(oldNode) // if it exists in the previousNodes but not the newNodes, then // the node was removed. if (!(newIndex >= 0)) { diff.removed.push(oldNode) } // otherwise the node wasn't added or removed. else { newNodes.splice(i, 1) } } // Remaining nodes in newNodes must have been added. diff.added = newNodes return diff } ``` When a chain of assigned slots exists (i.e. slot1 assigned to slot2, slot2 assigned to slot3, etc), then the that code will run multiple times, once per `slotchange` of each slot in the chain. Because there's not a way to get finally-distributed nodes, I have to guard against the fact that a previous slot in the chain might have added the distributed node to `shadowChildren` of the previous slot's parent. If there were a `distributedNodes()` method, then that defensive check would not be needed and the code would look like this: ```js _handleDistributedChildren(slot) { const diff = this._getDistributedChildDifference(slot) for (const addedNode of diff.added) { addedNode._shadowParent = this this._shadowChildren.add(addedNode) } for (const removedNode of diff.removed) { removedNode._shadowParent = null this._shadowChildren.delete(removedNode) } } ``` furthermore, this logic wouldn't have to fire once per slot if there was an event that only fired on finally-distributed children. Right now, if there is a chain of 4 slots across 4 shadow tree, then this logic will fire four times from shallowest to deepest slot. TLDR: I've gotten it to work, but it's ugly due to the fact that there's no possible way to know if the nodes returned from from `slot.assignedNodes({flatten: true})` are finally-distributed to the current slot or not, so instead I am relying on the fact that the `slotchange` event will fire from shallowest to deepest slot. Is that order ot `slotchange` events something I can rely on? Or is it just Chrome's behavior and could possibly be different in other browsers? -- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/w3c/webcomponents/issues/611#issuecomment-263748417
Received on Wednesday, 30 November 2016 00:47:28 UTC