Permalink
Browse files

add contains tests for fragments and comment nodes

  • Loading branch information...
1 parent d4cffd7 commit 472f050adc68df35d58f8abafcaec2c4493c8e1a @msweeney msweeney committed Aug 17, 2012
View
28 build/dom-core/dom-core-debug.js
@@ -12,6 +12,19 @@ var NODE_TYPE = 'nodeType',
CONTAINS = 'contains',
COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
EMPTY_ARRAY = [],
+
+ // IE < 8 throws on node.contains(textNode)
+ supportsContainsTextNode = (function() {
+ var node = Y.config.doc.createElement('div'),
+ textNode = node.appendChild(Y.config.doc.createTextNode('')),
+ result = false;
+
+ try {
+ result = node.contains(textNode);
+ } catch(e) {}
+
+ return result;
+ })(),
/**
* The DOM utility provides a cross-browser abtraction layer
@@ -148,16 +161,19 @@ Y_DOM = {
if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
ret = false;
- } else if (element[CONTAINS]) {
- if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
+ } else if (element[CONTAINS] &&
+ // IE < 8 throws on node.contains(textNode) so fall back to brute.
+ // Falling back for other nodeTypes as well.
+ (needle[NODE_TYPE] === 1 || supportsContainsTextNode)) {
ret = element[CONTAINS](needle);
- } else {
- ret = Y_DOM._bruteContains(element, needle);
- }
- } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
+ } else if (element[COMPARE_DOCUMENT_POSITION]) {
+ // Match contains behavior (node.contains(node) === true).
+ // Needed for Firefox < 4.
if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) {
ret = true;
}
+ } else {
+ ret = Y_DOM._bruteContains(element, needle);
}
return ret;
View
2 build/dom-core/dom-core-min.js
@@ -1 +1 @@
-YUI.add("dom-core",function(e){var n="nodeType",c="ownerDocument",b="documentElement",a="defaultView",g="parentWindow",j="tagName",k="parentNode",i="previousSibling",l="nextSibling",h="contains",d="compareDocumentPosition",m=[],f={byId:function(p,o){return f.allById(p,o)[0]||null;},getId:function(o){var p;if(o.id&&!o.id.tagName&&!o.id.item){p=o.id;}else{if(o.attributes&&o.attributes.id){p=o.attributes.id.value;}}return p;},setId:function(o,p){if(o.setAttribute){o.setAttribute("id",p);}else{o.id=p;}},ancestor:function(p,q,s,r){var o=null;if(s){o=(!q||q(p))?p:null;}return o||f.elementByAxis(p,k,q,null,r);},ancestors:function(q,r,t,s){var p=q,o=[];while((p=f.ancestor(p,r,t,s))){t=false;if(p){o.unshift(p);if(s&&s(p)){return o;}}}return o;},elementByAxis:function(p,s,r,q,o){while(p&&(p=p[s])){if((q||p[j])&&(!r||r(p))){return p;}if(o&&o(p)){return null;}}return null;},contains:function(p,q){var o=false;if(!q||!p||!q[n]||!p[n]){o=false;}else{if(p[h]){if(e.UA.opera||q[n]===1){o=p[h](q);}else{o=f._bruteContains(p,q);}}else{if(p[d]){if(p===q||!!(p[d](q)&16)){o=true;}}}}return o;},inDoc:function(q,r){var p=false,o;if(q&&q.nodeType){(r)||(r=q[c]);o=r[b];if(o&&o.contains&&q.tagName){p=o.contains(q);}else{p=f.contains(o,q);}}return p;},allById:function(t,o){o=o||e.config.doc;var p=[],q=[],r,s;if(o.querySelectorAll){q=o.querySelectorAll('[id="'+t+'"]');}else{if(o.all){p=o.all(t);if(p){if(p.nodeName){if(p.id===t){q.push(p);p=m;}else{p=[p];}}if(p.length){for(r=0;s=p[r++];){if(s.id===t||(s.attributes&&s.attributes.id&&s.attributes.id.value===t)){q.push(s);}}}}}else{q=[f._getDoc(o).getElementById(t)];}}return q;},isWindow:function(o){return !!(o&&o.alert&&o.document);},_removeChildNodes:function(o){while(o.firstChild){o.removeChild(o.firstChild);}},siblings:function(r,q){var o=[],p=r;while((p=p[i])){if(p[j]&&(!q||q(p))){o.unshift(p);}}p=r;while((p=p[l])){if(p[j]&&(!q||q(p))){o.push(p);}}return o;},_bruteContains:function(o,p){while(p){if(o===p){return true;}p=p.parentNode;}return false;},_getRegExp:function(p,o){o=o||"";f._regexCache=f._regexCache||{};if(!f._regexCache[p+o]){f._regexCache[p+o]=new RegExp(p,o);}return f._regexCache[p+o];},_getDoc:function(o){var p=e.config.doc;if(o){p=(o[n]===9)?o:o[c]||o.document||e.config.doc;}return p;},_getWin:function(o){var p=f._getDoc(o);return p[a]||p[g]||e.config.win;},_batch:function(o,w,u,t,s,q){w=(typeof w==="string")?f[w]:w;var x,r=0,p,v;if(w&&o){while((p=o[r++])){x=x=w.call(f,p,u,t,s,q);if(typeof x!=="undefined"){(v)||(v=[]);v.push(x);}}}return(typeof v!=="undefined")?v:o;},generateID:function(o){var p=o.id;if(!p){p=e.stamp(o);o.id=p;}return p;}};e.DOM=f;},"@VERSION@",{requires:["oop","features"]});
+YUI.add("dom-core",function(e){var o="nodeType",c="ownerDocument",b="documentElement",a="defaultView",g="parentWindow",j="tagName",k="parentNode",i="previousSibling",l="nextSibling",h="contains",d="compareDocumentPosition",n=[],m=(function(){var q=e.config.doc.createElement("div"),s=q.appendChild(e.config.doc.createTextNode("")),p=false;try{p=q.contains(s);}catch(r){}return p;})(),f={byId:function(q,p){return f.allById(q,p)[0]||null;},getId:function(p){var q;if(p.id&&!p.id.tagName&&!p.id.item){q=p.id;}else{if(p.attributes&&p.attributes.id){q=p.attributes.id.value;}}return q;},setId:function(p,q){if(p.setAttribute){p.setAttribute("id",q);}else{p.id=q;}},ancestor:function(q,r,t,s){var p=null;if(t){p=(!r||r(q))?q:null;}return p||f.elementByAxis(q,k,r,null,s);},ancestors:function(r,s,u,t){var q=r,p=[];while((q=f.ancestor(q,s,u,t))){u=false;if(q){p.unshift(q);if(t&&t(q)){return p;}}}return p;},elementByAxis:function(q,t,s,r,p){while(q&&(q=q[t])){if((r||q[j])&&(!s||s(q))){return q;}if(p&&p(q)){return null;}}return null;},contains:function(q,r){var p=false;if(!r||!q||!r[o]||!q[o]){p=false;}else{if(q[h]&&(r[o]===1||m)){p=q[h](r);}else{if(q[d]){if(q===r||!!(q[d](r)&16)){p=true;}}else{p=f._bruteContains(q,r);}}}return p;},inDoc:function(r,s){var q=false,p;if(r&&r.nodeType){(s)||(s=r[c]);p=s[b];if(p&&p.contains&&r.tagName){q=p.contains(r);}else{q=f.contains(p,r);}}return q;},allById:function(u,p){p=p||e.config.doc;var q=[],r=[],s,t;if(p.querySelectorAll){r=p.querySelectorAll('[id="'+u+'"]');}else{if(p.all){q=p.all(u);if(q){if(q.nodeName){if(q.id===u){r.push(q);q=n;}else{q=[q];}}if(q.length){for(s=0;t=q[s++];){if(t.id===u||(t.attributes&&t.attributes.id&&t.attributes.id.value===u)){r.push(t);}}}}}else{r=[f._getDoc(p).getElementById(u)];}}return r;},isWindow:function(p){return !!(p&&p.alert&&p.document);},_removeChildNodes:function(p){while(p.firstChild){p.removeChild(p.firstChild);}},siblings:function(s,r){var p=[],q=s;while((q=q[i])){if(q[j]&&(!r||r(q))){p.unshift(q);}}q=s;while((q=q[l])){if(q[j]&&(!r||r(q))){p.push(q);}}return p;},_bruteContains:function(p,q){while(q){if(p===q){return true;}q=q.parentNode;}return false;},_getRegExp:function(q,p){p=p||"";f._regexCache=f._regexCache||{};if(!f._regexCache[q+p]){f._regexCache[q+p]=new RegExp(q,p);}return f._regexCache[q+p];},_getDoc:function(p){var q=e.config.doc;if(p){q=(p[o]===9)?p:p[c]||p.document||e.config.doc;}return q;},_getWin:function(p){var q=f._getDoc(p);return q[a]||q[g]||e.config.win;},_batch:function(p,x,v,u,t,r){x=(typeof x==="string")?f[x]:x;var y,s=0,q,w;if(x&&p){while((q=p[s++])){y=y=x.call(f,q,v,u,t,r);if(typeof y!=="undefined"){(w)||(w=[]);w.push(y);}}}return(typeof w!=="undefined")?w:p;},generateID:function(p){var q=p.id;if(!q){q=e.stamp(p);p.id=q;}return q;}};e.DOM=f;},"@VERSION@",{requires:["oop","features"]});
View
28 build/dom-core/dom-core.js
@@ -12,6 +12,19 @@ var NODE_TYPE = 'nodeType',
CONTAINS = 'contains',
COMPARE_DOCUMENT_POSITION = 'compareDocumentPosition',
EMPTY_ARRAY = [],
+
+ // IE < 8 throws on node.contains(textNode)
+ supportsContainsTextNode = (function() {
+ var node = Y.config.doc.createElement('div'),
+ textNode = node.appendChild(Y.config.doc.createTextNode('')),
+ result = false;
+
+ try {
+ result = node.contains(textNode);
+ } catch(e) {}
+
+ return result;
+ })(),
/**
* The DOM utility provides a cross-browser abtraction layer
@@ -148,16 +161,19 @@ Y_DOM = {
if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
ret = false;
- } else if (element[CONTAINS]) {
- if (Y.UA.opera || needle[NODE_TYPE] === 1) { // IE & SAF contains fail if needle not an ELEMENT_NODE
+ } else if (element[CONTAINS] &&
+ // IE < 8 throws on node.contains(textNode) so fall back to brute.
+ // Falling back for other nodeTypes as well.
+ (needle[NODE_TYPE] === 1 || supportsContainsTextNode)) {
ret = element[CONTAINS](needle);
- } else {
- ret = Y_DOM._bruteContains(element, needle);
- }
- } else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
+ } else if (element[COMPARE_DOCUMENT_POSITION]) {
+ // Match contains behavior (node.contains(node) === true).
+ // Needed for Firefox < 4.
if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) {
ret = true;
}
+ } else {
+ ret = Y_DOM._bruteContains(element, needle);
}
return ret;
View
13 src/dom/tests/unit/assets/dom-core-test.js
@@ -636,6 +636,12 @@ YUI.add('dom-core-test', function(Y) {
Assert.isFalse(Y.DOM.contains(document.body, node));
},
+ 'should be true for contained comment node': function() {
+ var node = document.createElement('div');
+ node.innerHTML = 'foo<!-- comment -->';
+ Assert.isTrue(Y.DOM.contains(node, node.firstChild.nextSibling));
+ },
+
'should return false for null input': function() {
var node = document.createElement('div');
document.body.appendChild(node);
@@ -650,6 +656,13 @@ YUI.add('dom-core-test', function(Y) {
'should return false for undefined input': function() {
Assert.isFalse(Y.DOM.contains(document.body));
Assert.isFalse(Y.DOM.contains());
+ },
+
+ 'fragment should contain child': function() {
+ var frag = document.createDocumentFragment(),
+ node = frag.appendChild(document.createElement('div'));
+
+ Assert.isTrue(Y.DOM.contains(frag, node));
}
}));

0 comments on commit 472f050

Please sign in to comment.