Skip to content

Commit

Permalink
CoffeeScript-ed the XPath patches.
Browse files Browse the repository at this point in the history
  • Loading branch information
assaf committed Jan 5, 2011
1 parent 0ddf4ab commit 9b7666d
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 76 deletions.
76 changes: 0 additions & 76 deletions src/zombie/jsdom_patches.coffee
Expand Up @@ -127,79 +127,3 @@ core.HTMLDocument.prototype.fixQueue = ->
item.err = err
item.data = data
item.check()

# compareDocumentPosition
# -----------------------

# compareDocumentPosition is buggy on JS DOM. When it finds a common ancestor,
# it tries to find the compared nodes as ancestor children but this is not
# necessarily true. The proper behavior is to check the first child for that
# ancestor that is a parent to each node.

`
// Compare Document Position
var DOCUMENT_POSITION_DISCONNECTED = core.Node.prototype.DOCUMENT_POSITION_DISCONNECTED = 0x01;
var DOCUMENT_POSITION_PRECEDING = core.Node.prototype.DOCUMENT_POSITION_PRECEDING = 0x02;
var DOCUMENT_POSITION_FOLLOWING = core.Node.prototype.DOCUMENT_POSITION_FOLLOWING = 0x04;
var DOCUMENT_POSITION_CONTAINS = core.Node.prototype.DOCUMENT_POSITION_CONTAINS = 0x08;
var DOCUMENT_POSITION_CONTAINED_BY = core.Node.prototype.DOCUMENT_POSITION_CONTAINED_BY = 0x10;
var DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = core.Node.prototype.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;

core.Node.prototype.compareDocumentPosition = function compareDocumentPosition( otherNode ) {
if( !(otherNode instanceof core.Node) ) {
throw Error("Comparing position against non-Node values is not allowed")
}
var thisOwner, otherOwner;

if( this.nodeType === this.DOCUMENT_NODE)
thisOwner = this
else
thisOwner = this.ownerDocument

if( otherNode.nodeType === this.DOCUMENT_NODE)
otherOwner = otherNode
else
otherOwner = otherNode.ownerDocument

if( this === otherNode ) return 0
if( this === otherNode.ownerDocument ) return DOCUMENT_POSITION_FOLLOWING + DOCUMENT_POSITION_CONTAINED_BY
if( this.ownerDocument === otherNode ) return DOCUMENT_POSITION_PRECEDING + DOCUMENT_POSITION_CONTAINS
if( thisOwner !== otherOwner ) return DOCUMENT_POSITION_DISCONNECTED

// Text nodes for attributes does not have a _parentNode. So we need to find them as attribute child.
if( this.nodeType === this.ATTRIBUTE_NODE && this._childNodes && this._childNodes.indexOf(otherNode) !== -1)
return DOCUMENT_POSITION_FOLLOWING + DOCUMENT_POSITION_CONTAINED_BY

if( otherNode.nodeType === this.ATTRIBUTE_NODE && otherNode._childNodes && otherNode._childNodes.indexOf(this) !== -1)
return DOCUMENT_POSITION_PRECEDING + DOCUMENT_POSITION_CONTAINS

var point = this
var parents = [ ]
var previous = null
while( point ) {
if( point == otherNode ) return DOCUMENT_POSITION_PRECEDING + DOCUMENT_POSITION_CONTAINS
parents.push( point )
point = point._parentNode
}
point = otherNode
previous = null
while( point ) {
if( point == this ) return DOCUMENT_POSITION_FOLLOWING + DOCUMENT_POSITION_CONTAINED_BY
var location_index = parents.indexOf( point )
if( location_index !== -1) {
var smallest_common_ancestor = parents[ location_index ]
var this_index = smallest_common_ancestor._childNodes.indexOf( parents[location_index - 1] )
var other_index = smallest_common_ancestor._childNodes.indexOf( previous )
if( this_index > other_index ) {
return DOCUMENT_POSITION_PRECEDING
}
else {
return DOCUMENT_POSITION_FOLLOWING
}
}
previous = point
point = point._parentNode
}
return DOCUMENT_POSITION_DISCONNECTED
};
`
70 changes: 70 additions & 0 deletions src/zombie/xpath.coffee
Expand Up @@ -24,3 +24,73 @@ core.HTMLDocument.prototype.evaluate = (expr, node, nsResolver, type, result)->
value = a.compareDocumentPosition(b)
value == 2 || value == 8 || value == 10 ? -1 : 1
result


# compareDocumentPosition
# -----------------------

# compareDocumentPosition is buggy on JS DOM. When it finds a common ancestor,
# it tries to find the compared nodes as ancestor children but this is not
# necessarily true. The proper behavior is to check the first child for that
# ancestor that is a parent to each node.


# Compare Document Position
DOCUMENT_POSITION_DISCONNECTED = core.Node.prototype.DOCUMENT_POSITION_DISCONNECTED = 0x01
DOCUMENT_POSITION_PRECEDING = core.Node.prototype.DOCUMENT_POSITION_PRECEDING = 0x02
DOCUMENT_POSITION_FOLLOWING = core.Node.prototype.DOCUMENT_POSITION_FOLLOWING = 0x04
DOCUMENT_POSITION_CONTAINS = core.Node.prototype.DOCUMENT_POSITION_CONTAINS = 0x08
DOCUMENT_POSITION_CONTAINED_BY = core.Node.prototype.DOCUMENT_POSITION_CONTAINED_BY = 0x10
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = core.Node.prototype.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20

core.Node.prototype.compareDocumentPosition = (otherNode)->
if !(otherNode instanceof core.Node)
throw Error("Comparing position against non-Node values is not allowed")

if this.nodeType == this.DOCUMENT_NODE
thisOwner = this
else
thisOwner = this.ownerDocument

if otherNode.nodeType == this.DOCUMENT_NODE
otherOwner = otherNode
else
otherOwner = otherNode.ownerDocument

if this == otherNode then return 0
if this == otherNode.ownerDocument then return DOCUMENT_POSITION_FOLLOWING + DOCUMENT_POSITION_CONTAINED_BY
if this.ownerDocument == otherNode then return DOCUMENT_POSITION_PRECEDING + DOCUMENT_POSITION_CONTAINS
if thisOwner != otherOwner then return DOCUMENT_POSITION_DISCONNECTED

# Text nodes for attributes does not have a _parentNode. So we need to find them as attribute child.
if this.nodeType == this.ATTRIBUTE_NODE && this._childNodes && this._childNodes.indexOf(otherNode) != -1
return DOCUMENT_POSITION_FOLLOWING + DOCUMENT_POSITION_CONTAINED_BY

if otherNode.nodeType == this.ATTRIBUTE_NODE && otherNode._childNodes && otherNode._childNodes.indexOf(this) != -1
return DOCUMENT_POSITION_PRECEDING + DOCUMENT_POSITION_CONTAINS

point = this
parents = [ ]
previous = null
while point
if point == otherNode
return DOCUMENT_POSITION_PRECEDING + DOCUMENT_POSITION_CONTAINS
parents.push point
point = point._parentNode
point = otherNode
previous = null
while point
if point == this
return DOCUMENT_POSITION_FOLLOWING + DOCUMENT_POSITION_CONTAINED_BY
location_index = parents.indexOf(point)
if location_index != -1
smallest_common_ancestor = parents[ location_index ]
this_index = smallest_common_ancestor._childNodes.indexOf( parents[location_index - 1] )
other_index = smallest_common_ancestor._childNodes.indexOf( previous )
if this_index > other_index
return DOCUMENT_POSITION_PRECEDING
else
return DOCUMENT_POSITION_FOLLOWING
previous = point
point = point._parentNode
return DOCUMENT_POSITION_DISCONNECTED

0 comments on commit 9b7666d

Please sign in to comment.