Improve TreeWalker logic
MODIFY
js/views/cfi_navigation_logic.js
js/views/cfi_navigation_logic.js
@@ -1500,9 +1500,12 @@ var CfiNavigationLogic = function (options) {
var treeWalker = document.createTreeWalker(
this.getBodyElement(),
- NodeFilter.SHOW_ELEMENT,
+ NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
function(node) {
- if (isElementBlacklisted($(node)))
+ if (node.nodeType === Node.ELEMENT_NODE && isElementBlacklisted($(node)))
+ return NodeFilter.FILTER_REJECT;
+
+ if (node.nodeType === Node.TEXT_NODE && !isValidTextNode(node))
return NodeFilter.FILTER_REJECT;
var visibilityResult = checkVisibilityByRectangles($(node), true, visibleContentOffsets, frameDimensions);
@@ -1513,9 +1516,18 @@ var CfiNavigationLogic = function (options) {
while (treeWalker.nextNode()) {
var node = treeWalker.currentNode;
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ firstVisibleElement = node.parentNode;
+ textNode = node;
+ percentVisible = 100; // not really used, assume this value unless otherwise
+ break;
+ }
+
var hasChildElements = false;
var hasChildTextNodes = false;
- for (var i=0; i<node.childNodes.length; i++) {
+
+ for (var i = node.childNodes.length - 1; i >= 0; i--) {
var childNode = node.childNodes[i];
if (childNode.nodeType === Node.ELEMENT_NODE) {
hasChildElements = true;
@@ -1526,17 +1538,8 @@ var CfiNavigationLogic = function (options) {
}
// potentially stop tree traversal when first element hit with no child element nodes
- if (!hasChildElements) {
- // case 1: image
- if (node.nodeName.toLowerCase() === 'img') {
- firstVisibleElement = node;
- percentVisible = 100; // unused
- break;
- }
-
- // case 2: valid text node
- if (hasChildTextNodes) {
- for (var i=0; i<node.childNodes.length; ++i) {
+ if (!hasChildElements && hasChildTextNodes) {
+ for (var i=node.childNodes.length-1; i>=0; i--) {
var childNode = node.childNodes[i];
if (childNode.nodeType === Node.TEXT_NODE && isValidTextNode(childNode)) {
var visibilityResult = checkVisibilityByRectangles($(childNode), true, visibleContentOffsets, frameDimensions);
@@ -1548,11 +1551,13 @@ var CfiNavigationLogic = function (options) {
}
}
}
- if (firstVisibleElement)
+ } else if (!hasChildElements) {
+ firstVisibleElement = node;
+ percentVisible = 100;
+ textNode = null;
break;
}
}
- }
return {
element: firstVisibleElement,
@@ -1574,9 +1579,12 @@ var CfiNavigationLogic = function (options) {
var treeWalker = document.createTreeWalker(
this.getBodyElement(),
- NodeFilter.SHOW_ELEMENT,
+ NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
function(node) {
- if (isElementBlacklisted($(node)))
+ if (node.nodeType === Node.ELEMENT_NODE && isElementBlacklisted($(node)))
+ return NodeFilter.FILTER_REJECT;
+
+ if (node.nodeType === Node.TEXT_NODE && !isValidTextNode(node))
return NodeFilter.FILTER_REJECT;
var visibilityResult = checkVisibilityByRectangles($(node), true, visibleContentOffsets, frameDimensions);
@@ -1589,8 +1597,17 @@ var CfiNavigationLogic = function (options) {
do {
var node = treeWalker.currentNode;
+
+ if (node.nodeType === Node.TEXT_NODE) {
+ firstVisibleElement = node.parentNode;
+ textNode = node;
+ percentVisible = 100; // not really used, assume this value unless otherwise
+ break;
+ }
+
var hasChildElements = false;
var hasChildTextNodes = false;
+
for (var i = node.childNodes.length - 1; i >= 0; i--) {
var childNode = node.childNodes[i];
if (childNode.nodeType === Node.ELEMENT_NODE) {
@@ -1602,16 +1619,7 @@ var CfiNavigationLogic = function (options) {
}
// potentially stop tree traversal when first element hit with no child element nodes
- if (!hasChildElements) {
- // case 1: image
- if (node.nodeName.toLowerCase() === 'img') {
- firstVisibleElement = node;
- percentVisible = 100; // unused
- break;
- }
-
- // case 2: valid text node
- if (hasChildTextNodes) {
+ if (!hasChildElements && hasChildTextNodes) {
for (var i=node.childNodes.length-1; i>=0; i--) {
var childNode = node.childNodes[i];
if (childNode.nodeType === Node.TEXT_NODE && isValidTextNode(childNode)) {
@@ -1624,10 +1632,12 @@ var CfiNavigationLogic = function (options) {
}
}
}
- if (firstVisibleElement)
+ } else if (!hasChildElements) {
+ firstVisibleElement = node;
+ percentVisible = 100;
+ textNode = null;
break;
}
- }
} while (treeWalker.previousNode());
return {

Improve TreeWalker logic