mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 15:23:29 -05:00
133 lines
No EOL
3.1 KiB
JavaScript
133 lines
No EOL
3.1 KiB
JavaScript
/* Copyright © 2011 by Neil Jenkins. Licensed under the MIT license. */
|
|
|
|
( function ( doc ) {
|
|
|
|
/*global document, window */
|
|
|
|
"use strict";
|
|
|
|
// ---
|
|
|
|
var needsReplacement = !doc.createTreeWalker;
|
|
|
|
// IE9 sometimes throws errors when calling TreeWalker#nextNode or
|
|
// TreeWalker#previousNode. No way to feature detect this.
|
|
if ( window.ie === 9 ) {
|
|
needsReplacement = true;
|
|
}
|
|
|
|
// Feature detect Opera bug in TreeWalker#previousNode
|
|
if ( !needsReplacement ) {
|
|
( function () {
|
|
var div = doc.createElement( 'div' ),
|
|
text = doc.createTextNode( '' );
|
|
|
|
div.appendChild( text );
|
|
|
|
var div1 = div.cloneNode( true ),
|
|
div2 = div.cloneNode( true ),
|
|
div3 = div.cloneNode( true ),
|
|
walker = doc.createTreeWalker( div, 1, function ( node ) {
|
|
return 1;
|
|
}, false );
|
|
div.appendChild( div1 );
|
|
div.appendChild( div2 );
|
|
div.appendChild( div3 );
|
|
walker.currentNode = div3;
|
|
if ( walker.previousNode() !== div2 ) {
|
|
needsReplacement = true;
|
|
}
|
|
}() );
|
|
}
|
|
|
|
if ( !needsReplacement ) { return; }
|
|
|
|
// ---
|
|
|
|
var typeToBitArray = {
|
|
// ELEMENT_NODE
|
|
1: 1,
|
|
// ATTRIBUTE_NODE
|
|
2: 2,
|
|
// TEXT_NODE
|
|
3: 4,
|
|
// COMMENT_NODE
|
|
8: 128,
|
|
// DOCUMENT_NODE
|
|
9: 256,
|
|
// DOCUMENT_FRAGMENT_NODE
|
|
11: 1024
|
|
};
|
|
|
|
var FILTER_ACCEPT = 1;
|
|
|
|
var TreeWalker = function ( root, nodeType, filter ) {
|
|
this.root = this.currentNode = root;
|
|
this.nodeType = nodeType;
|
|
this.filter = filter;
|
|
};
|
|
|
|
TreeWalker.prototype.nextNode = function () {
|
|
var current = this.currentNode,
|
|
root = this.root,
|
|
nodeType = this.nodeType,
|
|
filter = this.filter,
|
|
node;
|
|
while ( true ) {
|
|
node = current.firstChild;
|
|
while ( !node && current ) {
|
|
node = current.nextSibling;
|
|
if ( !node ) {
|
|
current = current.parentNode;
|
|
if ( current === root ) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !node ) {
|
|
return null;
|
|
}
|
|
if ( ( typeToBitArray[ node.nodeType ] & nodeType ) &&
|
|
filter( node ) === FILTER_ACCEPT ) {
|
|
this.currentNode = node;
|
|
return node;
|
|
}
|
|
|
|
current = node;
|
|
}
|
|
};
|
|
|
|
TreeWalker.prototype.previousNode = function () {
|
|
var current = this.currentNode,
|
|
root = this.root,
|
|
nodeType = this.nodeType,
|
|
filter = this.filter,
|
|
node;
|
|
while ( true ) {
|
|
if ( node === root ) {
|
|
return null;
|
|
}
|
|
node = current.previousSibling;
|
|
if ( node ) {
|
|
while ( current = node.lastChild ) {
|
|
node = current;
|
|
}
|
|
} else {
|
|
node = current.parentNode;
|
|
}
|
|
if ( ( typeToBitArray[ node.nodeType ] & nodeType ) &&
|
|
filter( node ) === FILTER_ACCEPT ) {
|
|
this.currentNode = node;
|
|
return node;
|
|
}
|
|
|
|
current = node;
|
|
}
|
|
};
|
|
|
|
doc.createTreeWalker = function ( root, nodeType, filter ) {
|
|
return new TreeWalker( root, nodeType, filter );
|
|
};
|
|
|
|
}( document ) ); |