Skip to content

Commit

Permalink
add util method for shadow children
Browse files Browse the repository at this point in the history
  • Loading branch information
notwaldorf committed Oct 6, 2015
1 parent 6ed836f commit 1e9110a
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 19 deletions.
33 changes: 28 additions & 5 deletions src/standard/utils.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
* payload.
* @param {Object=} options Object specifying options. These may include:
* `bubbles` (boolean, defaults to `true`),
* `cancelable` (boolean, defaults to false), and
* `cancelable` (boolean, defaults to false), and
* `node` on which to fire the event (HTMLElement, defaults to `this`).
* @return {CustomEvent} The new event that was fired.
*/
Expand Down Expand Up @@ -199,11 +199,11 @@

/**
* Removes an item from an array, if it exists.
*
* If the array is specified by path, a change notification is
*
* If the array is specified by path, a change notification is
* generated, so that observers, data bindings and computed
* properties watching that path can update.
*
* properties watching that path can update.
*
* If the array is passed directly, **no change
* notification is generated**.
*
Expand Down Expand Up @@ -306,6 +306,29 @@
}
}
return elt;
},

/**
* Checks whether an element is in this element's light DOM tree.
*
* @method isLightDescendant
* @param {HTMLElement=} node The element to be checked.

This comment has been minimized.

Copy link
@danbeam

danbeam Nov 24, 2015

Contributor

right now it seems that iron-behaviors are calling this from event handlers with, i.e.

/** @param {Event} e */
_tapHandler: function(e) {
  if (this.isLightDescendant(e.target)) {...}
},

unfortunately e.target can be an EventTarget and is not necessarily an HTMLElement or even Node (in some cases). examples:

document.addEventListener('click', function(e) {
  /* e.target is an EventTarget, Node, but not an HTMLElement. */
});

window.addEventListener('resize', function(e) {
  /* e.target is an EventTarget, but not a Node nor HTMLElement. */
});

do we want all call sites to be casting to Node or HTMLElement, or can this method be updated to take an EventTarget instead?

/cc @notwaldorf @rictic

This comment has been minimized.

Copy link
@danbeam

danbeam Nov 24, 2015

Contributor

sorry, I just noticed the type is {HTMLElement=}, does that mean this parameter is optional?

This comment has been minimized.

Copy link
@rictic

rictic Dec 5, 2015

Contributor

That does mean it's optional.

I think the right thing to do is to cast when you're accessing e.target. It's only because of the type of event you're dealing with that you know that it's an element and not window or an XHR or what have you.

* @return {Boolean} true if node is in this element's light DOM tree.
*/
isLightDescendant: function(node) {
return this.contains(node) &&
Polymer.dom(this).getOwnerRoot() === Polymer.dom(node).getOwnerRoot();
},

/**
* Checks whether an element is in this element's local DOM tree.
*
* @method isLocalDescendant
* @param {HTMLElement=} node The element to be checked.
* @return {Boolean} true if node is in this element's local DOM tree.
*/
isLocalDescendant: function(node) {
return this.root === Polymer.dom(node).getOwnerRoot();
}

});
Expand Down
78 changes: 66 additions & 12 deletions test/unit/utils-content.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<div></div>
<div></div>
</x-content>

<x-content-multi id="elt3">
<span></span>
<div></div>
Expand All @@ -37,41 +37,50 @@
<span></span>
</x-content-multi>

<x-content-mixed id="elt4">
<span></span>
<x-content></x-content>
</x-content-mixed>

<x-content-mixed id="elt5">
<x-content-mixed id="elt6"></x-content-mixed>
</x-content-mixed>

<script>

suite('content utils', function() {

var elt1 = document.querySelector('#elt1');
var elt2 = document.querySelector('#elt2');
var elt3 = document.querySelector('#elt3');

test('getContentChildNodes (empty)', function() {
var nodes = elt1.getContentChildNodes();
assert.equal(nodes.length, 1, 'should have 1 text node');
});

test('getContentChildren (empty)', function() {
var nodes = elt1.getContentChildren();
assert.equal(nodes.length, 0, 'should have no children');
});

test('getContentChildNodes', function() {
var nodes = elt2.getContentChildNodes();
assert.equal(nodes.length, 7, 'should have 7 nodes (text nodes + divs)');
});

test('getContentChildren', function() {
var nodes = elt2.getContentChildren();
assert.equal(nodes.length, 3, 'should have 3 divs');
});

test('getContentChildNodes with selector', function() {
var nodes = elt3.getContentChildNodes('[select=div]');
assert.equal(nodes.length, 3, 'should have 3 divs');
nodes = elt3.getContentChildNodes('[select=span]');
assert.equal(nodes.length, 4, 'should have 4 spans');
});

test('getContentChildren with selector', function() {
var nodes = elt3.getContentChildren('[select=div]');
assert.equal(nodes.length, 3, 'should have 3 divs');
Expand All @@ -88,10 +97,55 @@
var nodes = elt3.getContentChildren('[dne]');
assert.equal(nodes.length, 0, 'should find 0 nodes');
});


});

suite('isLight/Local descendant utils', function() {
var elt1 = document.querySelector('#elt1');
var elt4 = document.querySelector('#elt4');
var elt5 = document.querySelector('#elt5');
var elt6 = document.querySelector('#elt6');

test('isLightDescendant is true for light children', function() {
var span = elt4.querySelector('span');
var customElement = elt4.querySelector('x-content');
assert.isTrue(elt4.isLightDescendant(span));
assert.isTrue(elt4.isLightDescendant(customElement));
});

test('isLocalDescendant is false for light children', function() {
var span = elt4.querySelector('span');
var customElement = elt4.querySelector('x-content');
assert.isFalse(elt4.isLocalDescendant(span));
assert.isFalse(elt4.isLocalDescendant(customElement));
});

test('isLightDescendant is false for local children', function() {
assert.isFalse(elt4.isLightDescendant(elt4.localChild));
});

test('isLocalDescendant is true for local children', function() {
assert.isTrue(elt4.isLocalDescendant(elt4.localChild));
});

test('isLightDescendant is false for unrelated elements', function() {
assert.isFalse(elt4.isLightDescendant(elt1));
});

test('isLocalDescendant is false for unrelated elements', function() {
assert.isFalse(elt4.isLocalDescendant(elt1));
});

test('isLightDescendant is false for somebody else\'s local child', function() {
assert.isFalse(elt5.isLightDescendant(elt6.localChild));
});

test('isLocalDescendant is false for somebody else\'s local child', function() {
assert.isFalse(elt5.isLocalDescendant(elt6.localChild));
});
});

</script>

</body>
</html>
21 changes: 20 additions & 1 deletion test/unit/utils-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,23 @@
Polymer({
is: 'x-content-multi'
});
</script>
</script>

<dom-module id="x-content-mixed">

<template>
<content></content>
<x-content id="localChild"></x-content>
</template>

</dom-module>

<script>
Polymer({
is: 'x-content-mixed',

get localChild () {
return this.$.localChild;
}
});
</script>
2 changes: 1 addition & 1 deletion test/unit/utils.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<body>

<script>

HTMLImports.whenReady(function() {
Polymer({is: 'my-element'});
});
Expand Down

0 comments on commit 1e9110a

Please sign in to comment.