Skip to content

Commit

Permalink
Merge pull request #6 from PolymerLabs/nodewalk
Browse files Browse the repository at this point in the history
Add DOM querying capabilities
  • Loading branch information
dfreedm committed Mar 16, 2015
2 parents 6244c98 + 38fbaf8 commit 363fda9
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 7 deletions.
51 changes: 45 additions & 6 deletions dom5.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ function hasAttribute(element, name) {
return getAttributeIndex(element, name) !== -1;
}

/**
* @returns {string|null} The string value of attribute `name`, or `null`.
*/
function getAttribute(element, name) {
var i = getAttributeIndex(element, name);
if (i > -1) {
Expand Down Expand Up @@ -124,14 +127,21 @@ function isElement(node) {
return node.nodeName === node.tagName;
}

function query(node, predicate) {
if (isElement(node) && predicate(node)) {
/**
* Walk the tree down from `node`, applying the `predicate` function.
* Return the first node that matches the given predicate.
*
* @returns {Node} `null` if no node matches, parse5 node object if a node
* matches
*/
function nodeWalk(node, predicate) {
if (predicate(node)) {
return node;
}
var match = null;
if (node.childNodes) {
for (var i = 0; i < node.childNodes.length; i++) {
match = query(node.childNodes[i], predicate);
match = nodeWalk(node.childNodes[i], predicate);
if (match) {
break;
}
Expand All @@ -140,28 +150,57 @@ function query(node, predicate) {
return match;
}

function queryAll(node, predicate, matches) {
/**
* Walk the tree down from `node`, applying the `predicate` function.
* All nodes matching the predicate function from `node` to leaves will be
* returned.
*
* @returns {Array[Node]}
*/
function nodeWalkAll(node, predicate, matches) {
if (!matches) {
matches = [];
}
if (isElement(node) && predicate(node)) {
if (predicate(node)) {
matches.push(node);
}
if (node.childNodes) {
for (var i = 0; i < node.childNodes.length; i++) {
queryAll(node.childNodes[i], predicate, matches);
nodeWalkAll(node.childNodes[i], predicate, matches);
}
}
return matches;
}

/**
* Equivalent to `nodeWalk`, but only matches elements
*
* @returns {Element}
*/
function query(node, predicate) {
var elementPredicate = AND(isElement, predicate);
return nodeWalk(node, elementPredicate);
}

/**
* Equivalent to `nodeWalkAll`, but only matches elements
*
* @return {Array[Element]}
*/
function queryAll(node, predicate, matches) {
var elementPredicate = AND(isElement, predicate);
return nodeWalkAll(node, elementPredicate, matches);
}

module.exports = {
getAttribute: getAttribute,
hasAttribute: hasAttribute,
setAttribute: setAttribute,
isElement: isElement,
query: query,
queryAll: queryAll,
nodeWalk: nodeWalk,
nodeWalkAll: nodeWalkAll,
predicates: {
hasClass: hasClass,
hasAttr: hasAttr,
Expand Down
49 changes: 48 additions & 1 deletion test/dom5_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ suite('dom5', function() {
'<dom-module id="my-el">',
'<template>',
'<img src="foo.jpg">',
'<a href="next-page.html">',
'<a href="next-page.html">Anchor</a>',
'sample element',
'<!-- comment node -->',
'</template>',
'</dom-module>',
'<script>Polymer({is: "my-el"})</script>'
Expand All @@ -227,6 +229,33 @@ suite('dom5', function() {
doc = parser.parse(docText);
});

test('nodeWalk', function() {
var textNode = function(node) {
if (node.nodeName === '#text') {
return node.value === '\nsample element\n';
}
return false;
};

var comment = function(node) {
return node.nodeName === '#comment';
};

// doc -> body -> dom-module -> template -> template.content
var templateContent = doc.childNodes[1].childNodes[1].childNodes[0]
.childNodes[1].childNodes[0];

// 'sample element' text node
var expected = templateContent.childNodes[4];
var actual = dom5.nodeWalk(doc, textNode);
assert.equal(expected, actual);

// <!-- comment node -->
expected = templateContent.childNodes[5];
actual = dom5.nodeWalk(templateContent, comment);
assert.equal(expected, actual);
});

test('query', function() {
var fn = dom5.predicates.AND(
dom5.predicates.hasTagName('link'),
Expand All @@ -238,6 +267,24 @@ suite('dom5', function() {
assert.equal(expected, actual);
});

test('nodeWalkAll', function() {
var empty = function(node) {
if (node.nodeName === '#text') {
return !/\S/.test(node.value);
}
return false;
};

// serialize to count for inserted <head> and <body>
var serializedDoc = (new Parse5.Serializer()).serialize(doc);
// subtract one to get "gap" number
var expected = serializedDoc.split('\n').length - 1;
// add two for normalized text node "\nsample text\n"
var actual = dom5.nodeWalkAll(doc, empty).length + 2;

assert.equal(expected, actual);
});

test('queryAll', function() {
var fn = dom5.predicates.AND(
dom5.predicates.OR(
Expand Down

0 comments on commit 363fda9

Please sign in to comment.