Created
July 19, 2011 17:09
-
-
Save boof/1093111 to your computer and use it in GitHub Desktop.
[WIP] Pure JavaScript implementation of "Document Object Model Traversal".
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(window, document) { | |
if ( !window.NodeFilter ) { | |
var NodeFilter = function() {}; | |
NodeFilter.FILTER_ACCEPT = 1; | |
NodeFilter.FILTER_REJECT = 2; | |
NodeFilter.FILTER_SKIP = 3; | |
NodeFilter.SHOW_ALL = 0xFFFFFFFF; | |
NodeFilter.SHOW_ELEMENT = 0x00000001; | |
NodeFilter.SHOW_ATTRIBUTE = 0x00000002; | |
NodeFilter.SHOW_TEXT = 0x00000004; | |
NodeFilter.SHOW_CDATA_SECTION = 0x00000008; | |
NodeFilter.SHOW_ENTITY_REFERENCE = 0x00000010; | |
NodeFilter.SHOW_ENTITY = 0x00000020; | |
NodeFilter.SHOW_PROCESSING_INSTRUCTION = 0x00000040; | |
NodeFilter.SHOW_COMMENT = 0x00000080; | |
NodeFilter.SHOW_DOCUMENT = 0x00000100; | |
NodeFilter.SHOW_DOCUMENT_TYPE = 0x00000200; | |
NodeFilter.SHOW_DOCUMENT_FRAGMENT = 0x00000400; | |
NodeFilter.SHOW_NOTATION = 0x00000800; | |
NodeFilter.prototype.acceptNode = function(n) { | |
return NodeFilter.FILTER_ACCEPT; | |
}; | |
window.NodeFilter = NodeFilter; | |
} | |
if ( !document.createTreeWalker ) { | |
/* | |
* http://codesearch.google.com/#OAMlx_jo-ck/src/third_party/WebKit/Source/WebCore/dom/TreeWalker.cpp | |
* http://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html | |
*/ | |
function TreeWalker(root, whatToShow, filter, entityReferenceExpansion) { | |
// RADAR | |
// This is imho not necessary 'cause IE<9 doesn't support overwriting | |
// property setters on non-DOM objects and other browsers have already | |
// TreeWalker support. | |
// Maybe TreeWalker can be implemented as DOM object? | |
// Note: For IE we use Object.defineProperty! | |
var currentNode; | |
this.__defineSetter__('currentNode', function(node) { | |
if ( node === null ) { throw( DOMException.NOT_SUPPORTED_ERR ); } | |
return currentNode = node; | |
}); | |
this.__defineGetter__('currentNode', function() { | |
return currentNode; | |
}); | |
this.parentNode = function() { | |
var node, filterResult = NodeFilter.FILTER_ACCEPT; | |
while ( node !== root ) { | |
node = this.currentNode.parentNode; | |
if ( !node ) { return null; } | |
if ( typeof(filter) == 'function' ) try { | |
filterResult = filter.acceptNode( node ); | |
} catch (e) { | |
return null; | |
} | |
if ( filterResult === NodeFilter.FILTER_ACCEPT ) { | |
return currentNode = node; | |
} | |
} | |
return null; | |
}; | |
this.firstChild = function() { | |
for (var node = node.firstChild, filterResult = NodeFilter.FILTER_ACCEPT; node;) { | |
if ( typeof(filter) == 'function' ) try { | |
filterResult = filter.acceptNode( node ); | |
} catch (e) { | |
return null; | |
} | |
switch ( filterResult ) { | |
case NodeFilter.FILTER_ACCEPT: return currentNode = node; | |
case NodeFilter.FILTER_SKIP: | |
if ( node.firstChild ) { | |
node = node.firstChild; | |
continue; | |
} | |
break; | |
case NodeFilter.FILTER_REJECT: break; | |
} | |
do { | |
if ( node.nextSibling ) { | |
node = node.nextSibling; | |
break; | |
} | |
node = node.parentNode; | |
if ( node === root || node === currentNode ) { | |
return null; | |
} | |
} while ( node ) | |
} | |
return null; | |
}; | |
this.lastChild = function() {}; | |
}; | |
(function(fn) { | |
fn.previousSibling = function() {}; | |
fn.nextSibling = function() {}; | |
fn.previousNode = function() { | |
var node; | |
node = this.previousSibling(); | |
if ( node ) { return this.lastChild() || node; } | |
node = this.parentNode(); | |
if ( node ) { return this.previousNode(); } | |
return node; | |
}; | |
fn.nextNode = function() { | |
var node; | |
node = this.firstChild() || this.nextSibling(); | |
if ( node ) { return node; } | |
node = this.parentNode(); | |
if ( node ) { return this.nextNode(); } | |
return node; | |
}; | |
})(TreeWalker.prototype) | |
document.createTreeWalker = TreeWalker; | |
} | |
})(window, document); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment