Permalink
Browse files

fixed old SCG classList and added new query and queryAll methods

  • Loading branch information...
1 parent 1d0b42b commit da653edcad9945bfe09c80d4f63db856c7293751 @WebReflection committed Apr 29, 2015
Showing with 339 additions and 232 deletions.
  1. +8 −0 .travis.yml
  2. +2 −1 README.md
  3. +1 −1 bower.json
  4. +1 −1 build/dom4.js
  5. +116 −83 build/dom4.max.js
  6. +1 −1 cdnjs.json
  7. +10 −2 package.json
  8. +116 −83 src/dom4.js
  9. +45 −60 test/dom4.js
  10. +39 −0 testrunner.js
View
@@ -0,0 +1,8 @@
+language: node_js
+node_js:
+ - 0.12
+git:
+ depth: 1
+branches:
+ only:
+ - master
View
@@ -5,7 +5,7 @@ DOM4
Many thanks to [cdnjs](http://www.cdnjs.com) for hosting this script. Following an example on how to include it.
```html
<script
- src="//cdnjs.cloudflare.com/ajax/libs/dom4/1.3.3/dom4.js"
+ src="//cdnjs.cloudflare.com/ajax/libs/dom4/1.4.0/dom4.js"
>/* DOM4 */</script>
```
@@ -26,6 +26,7 @@ The [implemented test](test/dom4.js) is conform to current specifications.
Other fixes/standardized behaviors include:
+ * **new** [Elements as Array subclass](http://www.w3.org/TR/2015/WD-dom-20150428/#elements), so that `el.query` is same as `el.querySelector` but `el.queryAll` replaces `Array.prototype.slice.call(el.querySelectorAll(css))`
* [classList](http://www.w3.org/TR/dom/#domtokenlist), with forced fixes for iOS 5.1 and Nokia ASHA Xpress Browser and early implementations
* [CustomEvent](http://www.w3.org/TR/dom/#customevent) constructor for all browsers down to IE8
* [Element#matches](http://www.w3.org/TR/dom/#dom-element-matches) utility to test elements against CSS selectors
View
@@ -1,7 +1,7 @@
{
"name": "DOM4",
"description": "new DOM Level 4 entries",
- "version": "1.3.3",
+ "version": "1.4.0",
"main": "build/dom4.max.js",
"ignore": [
"test",
View
@@ -1,2 +1,2 @@
/*! (C) WebReflection Mit Style License */
-(function(e){"use strict";function t(t){return typeof t=="string"?e.document.createTextNode(t):t}function n(n){if(n.length===1)return t(n[0]);for(var r=e.document.createDocumentFragment(),i=v.call(n),s=0;s<n.length;s++)r.appendChild(t(i[s]));return r}for(var r=Object.defineProperty||function(e,t,n){e.__defineGetter__(t,n.get)},i=[].indexOf||function(t){var n=this.length;while(n--)if(this[n]===t)break;return n},s,o,u,a,f=/^\s+|\s+$/g,l=/\s+/,c=" ",h=function(t,n){if(this.contains(t))n||this.remove(t);else if(n===undefined||n)n=!0,this.add(t);return!!n},p=(e.Element||e.Node||e.HTMLElement).prototype,d=["matches",p.matchesSelector||p.webkitMatchesSelector||p.khtmlMatchesSelector||p.mozMatchesSelector||p.msMatchesSelector||p.oMatchesSelector||function(t){var n=this.parentNode;return!!n&&-1<i.call(n.querySelectorAll(t),this)},"closest",function(t){var n=this,r;while((r=n&&n.matches)&&!n.matches(t))n=n.parentNode;return r?n:null},"prepend",function(){var t=this.firstChild,r=n(arguments);t?this.insertBefore(r,t):this.appendChild(r)},"append",function(){this.appendChild(n(arguments))},"before",function(){var t=this.parentNode;t&&t.insertBefore(n(arguments),this)},"after",function(){var t=this.parentNode,r=this.nextSibling,i=n(arguments);t&&(r?t.insertBefore(i,r):t.appendChild(i))},"replace",function(){this.replaceWith.apply(this,arguments)},"replaceWith",function(){var t=this.parentNode;t&&t.replaceChild(n(arguments),this)},"remove",function(){var t=this.parentNode;t&&t.removeChild(this)}],v=d.slice,m=d.length;m;m-=2)o=d[m-2],o in p||(p[o]=d[m-1]);document.createElement("a").matches("a")||(p[o]=function(e){return function(t){return e.call(this.parentNode?this:document.createDocumentFragment().appendChild(this),t)}}(p[o])),"classList"in document.documentElement?(a=document.createElement("div").classList,a.add("a","b","a"),"a b"!=a&&(p=a.constructor.prototype,"add"in p||(p=e.DOMTokenList.prototype),u=function(e){return function(){var t=0;while(t<arguments.length)e.call(this,arguments[t++])}},p.add=u(p.add),p.remove=u(p.remove),p.toggle=h)):(u=function(e){if(!e)throw"SyntaxError";if(l.test(e))throw"InvalidCharacterError";return e},a=function(e){var t=e.className,n=(typeof t=="object"?t.baseVal:t).replace(f,"");n.length&&d.push.apply(this,n.split(l)),this._=e},a.prototype={length:0,add:function(){for(var t=0,n;t<arguments.length;t++)n=arguments[t],this.contains(n)||d.push.call(this,o);this._.className=""+this},contains:function(e){return function(n){return m=e.call(this,o=u(n)),-1<m}}([].indexOf||function(e){m=this.length;while(m--&&this[m]!==e);return m}),item:function(t){return this[t]||null},remove:function(){for(var t=0,n;t<arguments.length;t++)n=arguments[t],this.contains(n)&&d.splice.call(this,m,1);this._.className=""+this},toggle:h,toString:function y(){return d.join.call(this,c)}},r(p,"classList",{get:function(){return new a(this)},set:function(){}})),"head"in document||r(document,"head",{get:function(){return s||(s=document.getElementsByTagName("head")[0])}});try{new e.CustomEvent("?")}catch(g){e.CustomEvent=function(e,t){function n(n,i){var s=document.createEvent(e);if(typeof n!="string")throw new Error("An event name must be provided");return e=="Event"&&(s.initCustomEvent=r),i==null&&(i=t),s.initCustomEvent(n,i.bubbles,i.cancelable,i.detail),s}function r(e,t,n,r){this.initEvent(e,t,n),this.detail=r}return n}(e.CustomEvent?"CustomEvent":"Event",{bubbles:!1,cancelable:!1,detail:null})}})(window);
+(function(e){"use strict";function t(e){return typeof e=="string"?a.createTextNode(e):e}function n(e){if(e.length===1)return t(e[0]);for(var n=a.createDocumentFragment(),r=S.call(e),i=0;i<e.length;i++)n.appendChild(t(r[i]));return n}for(var r,i,s,o,u,a=e.document,f=Object.defineProperty||function(e,t,n){e.__defineGetter__(t,n.get)},l=[].indexOf||function(t){var n=this.length;while(n--)if(this[n]===t)break;return n},c=function(e){if(!e)throw"SyntaxError";if(v.test(e))throw"InvalidCharacterError";return e},h=function(e){var t=e.className,n=typeof t=="object",r=(n?t.baseVal:t).replace(d,"");r.length&&E.push.apply(this,r.split(v)),this._isSVG=n,this._=e},p={get:function(){return new h(this)},set:function(){}},d=/^\s+|\s+$/g,v=/\s+/,m=" ",g="classList",y=function(t,n){if(this.contains(t))n||this.remove(t);else if(n===undefined||n)n=!0,this.add(t);return!!n},b=(e.Element||e.Node||e.HTMLElement).prototype,w=e.SVGElement,E=["matches",b.matchesSelector||b.webkitMatchesSelector||b.khtmlMatchesSelector||b.mozMatchesSelector||b.msMatchesSelector||b.oMatchesSelector||function(t){var n=this.parentNode;return!!n&&-1<l.call(n.querySelectorAll(t),this)},"closest",function(t){var n=this,r;while((r=n&&n.matches)&&!n.matches(t))n=n.parentNode;return r?n:null},"prepend",function(){var t=this.firstChild,r=n(arguments);t?this.insertBefore(r,t):this.appendChild(r)},"append",function(){this.appendChild(n(arguments))},"before",function(){var t=this.parentNode;t&&t.insertBefore(n(arguments),this)},"after",function(){var t=this.parentNode,r=this.nextSibling,i=n(arguments);t&&(r?t.insertBefore(i,r):t.appendChild(i))},"replace",function(){this.replaceWith.apply(this,arguments)},"replaceWith",function(){var t=this.parentNode;t&&t.replaceChild(n(arguments),this)},"remove",function(){var t=this.parentNode;t&&t.removeChild(this)},"query",function(t){return this.querySelector(t)},"queryAll",function(t){var n=this.querySelectorAll(t),r=n.length,i=new Array(r);while(r--)i[r]=n[r];return i}],S=E.slice,x=E.length;x;x-=2)i=E[x-2],i in b||(b[i]=E[x-1]);a.createElement("a").matches("a")||(b[i]=function(e){return function(t){return e.call(this.parentNode?this:a.createDocumentFragment().appendChild(this),t)}}(b[i])),h.prototype={length:0,add:function(){for(var t=0,n;t<arguments.length;t++)n=arguments[t],this.contains(n)||E.push.call(this,i);this._isSVG?this._.setAttribute("class",""+this):this._.className=""+this},contains:function(e){return function(n){return x=e.call(this,i=c(n)),-1<x}}([].indexOf||function(e){x=this.length;while(x--&&this[x]!==e);return x}),item:function(t){return this[t]||null},remove:function(){for(var t=0,n;t<arguments.length;t++)n=arguments[t],this.contains(n)&&E.splice.call(this,x,1);this._isSVG?this._.setAttribute("class",""+this):this._.className=""+this},toggle:y,toString:function N(){return E.join.call(this,m)}},w&&!(g in w.prototype)&&f(w.prototype,g,p),g in a.documentElement?(o=a.createElement("div")[g],o.add("a","b","a"),"a b"!=o&&(s=o.constructor.prototype,"add"in s||(s=e.TemporaryTokenList.prototype),u=function(e){return function(){var t=0;while(t<arguments.length)e.call(this,arguments[t++])}},s.add=u(s.add),s.remove=u(s.remove),s.toggle=y)):f(b,g,p),"head"in a||f(a,"head",{get:function(){return r||(r=a.getElementsByTagName("head")[0])}});try{new e.CustomEvent("?")}catch(T){e.CustomEvent=function(e,t){function n(n,i){var s=a.createEvent(e);if(typeof n!="string")throw new Error("An event name must be provided");return e=="Event"&&(s.initCustomEvent=r),i==null&&(i=t),s.initCustomEvent(n,i.bubbles,i.cancelable,i.detail),s}function r(e,t,n,r){this.initEvent(e,t,n),this.detail=r}return n}(e.CustomEvent?"CustomEvent":"Event",{bubbles:!1,cancelable:!1,detail:null})}})(window);
View
@@ -24,14 +24,14 @@ THE SOFTWARE.
/* jshint loopfunc: true, noempty: false*/
// http://www.w3.org/TR/dom/#element
function textNodeIfString(node) {
- return typeof node === 'string' ? window.document.createTextNode(node) : node;
+ return typeof node === 'string' ? document.createTextNode(node) : node;
}
function mutationMacro(nodes) {
if (nodes.length === 1) {
return textNodeIfString(nodes[0]);
}
for (var
- fragment = window.document.createDocumentFragment(),
+ fragment = document.createDocumentFragment(),
list = slice.call(nodes),
i = 0; i < nodes.length; i++
) {
@@ -40,6 +40,12 @@ THE SOFTWARE.
return fragment;
}
for(var
+ head,
+ property,
+ TemporaryPrototype,
+ TemporaryTokenList,
+ wrapVerifyToken,
+ document = window.document,
defineProperty = Object.defineProperty || function (object, property, descriptor) {
object.__defineGetter__(property, descriptor.get);
},
@@ -52,13 +58,40 @@ THE SOFTWARE.
}
return length;
},
- head,
- property,
- verifyToken,
- DOMTokenList,
+ // http://www.w3.org/TR/domcore/#domtokenlist
+ verifyToken = function (token) {
+ if (!token) {
+ throw 'SyntaxError';
+ } else if (spaces.test(token)) {
+ throw 'InvalidCharacterError';
+ }
+ return token;
+ },
+ DOMTokenList = function (node) {
+ var
+ className = node.className,
+ isSVG = typeof className === 'object',
+ value = (isSVG ? className.baseVal : className).replace(trim, '')
+ ;
+ if (value.length) {
+ properties.push.apply(
+ this,
+ value.split(spaces)
+ );
+ }
+ this._isSVG = isSVG;
+ this._ = node;
+ },
+ classListDescriptor = {
+ get: function get() {
+ return new DOMTokenList(this);
+ },
+ set: function(){}
+ },
trim = /^\s+|\s+$/g,
spaces = /\s+/,
SPACE = '\x20',
+ CLASS_LIST = 'classList',
toggle = function toggle(token, force) {
if (this.contains(token)) {
if (!force) {
@@ -72,6 +105,7 @@ THE SOFTWARE.
return !!force;
},
ElementPrototype = (window.Element || window.Node || window.HTMLElement).prototype,
+ SVGElement = window.SVGElement,
properties = [
'matches', (
ElementPrototype.matchesSelector ||
@@ -149,6 +183,18 @@ THE SOFTWARE.
if (parentNode) {
parentNode.removeChild(this);
}
+ },
+ 'query', function query(css) {
+ return this.querySelector(css);
+ },
+ 'queryAll', function queryAll(css) {
+ var
+ nl = this.querySelectorAll(css),
+ i = nl.length,
+ a = new Array(i)
+ ;
+ while (i--) a[i] = nl[i];
+ return a;
}
],
slice = properties.slice,
@@ -173,102 +219,89 @@ THE SOFTWARE.
};
}(ElementPrototype[property]);
}
- // http://www.w3.org/TR/dom/#domtokenlist
- // iOS 5.1 has completely screwed this property
- // classList in ElementPrototype is false
- // but it's actually there as getter
- if (!('classList' in document.documentElement)) {
- // http://www.w3.org/TR/domcore/#domtokenlist
- verifyToken = function (token) {
- if (!token) {
- throw 'SyntaxError';
- } else if (spaces.test(token)) {
- throw 'InvalidCharacterError';
- }
- return token;
- };
- DOMTokenList = function (node) {
- var
- className = node.className,
- value = (typeof className === 'object' ?
- className.baseVal : className).replace(trim, '')
- ;
- if (value.length) {
- properties.push.apply(
- this,
- value.split(spaces)
- );
- }
- this._ = node;
- };
- DOMTokenList.prototype = {
- length: 0,
- add: function add() {
- for(var j = 0, token; j < arguments.length; j++) {
- token = arguments[j];
- if(!this.contains(token)) {
- properties.push.call(this, property);
- }
+
+ // used to fix both old webkit and SVG
+ DOMTokenList.prototype = {
+ length: 0,
+ add: function add() {
+ for(var j = 0, token; j < arguments.length; j++) {
+ token = arguments[j];
+ if(!this.contains(token)) {
+ properties.push.call(this, property);
}
+ }
+ if (this._isSVG) {
+ this._.setAttribute('class', '' + this);
+ } else {
this._.className = '' + this;
- },
- contains: (function(indexOf){
- return function contains(token) {
- i = indexOf.call(this, property = verifyToken(token));
- return -1 < i;
- };
- }([].indexOf || function (token) {
- i = this.length;
- while(i-- && this[i] !== token){}
- return i;
- })),
- item: function item(i) {
- return this[i] || null;
- },
- remove: function remove() {
- for(var j = 0, token; j < arguments.length; j++) {
- token = arguments[j];
- if(this.contains(token)) {
- properties.splice.call(this, i, 1);
- }
+ }
+ },
+ contains: (function(indexOf){
+ return function contains(token) {
+ i = indexOf.call(this, property = verifyToken(token));
+ return -1 < i;
+ };
+ }([].indexOf || function (token) {
+ i = this.length;
+ while(i-- && this[i] !== token){}
+ return i;
+ })),
+ item: function item(i) {
+ return this[i] || null;
+ },
+ remove: function remove() {
+ for(var j = 0, token; j < arguments.length; j++) {
+ token = arguments[j];
+ if(this.contains(token)) {
+ properties.splice.call(this, i, 1);
}
+ }
+ if (this._isSVG) {
+ this._.setAttribute('class', '' + this);
+ } else {
this._.className = '' + this;
- },
- toggle: toggle,
- toString: function toString() {
- return properties.join.call(this, SPACE);
}
- };
- defineProperty(ElementPrototype, 'classList', {
- get: function get() {
- return new DOMTokenList(this);
- },
- set: function(){}
- });
+ },
+ toggle: toggle,
+ toString: function toString() {
+ return properties.join.call(this, SPACE);
+ }
+ };
+
+ if (SVGElement && !(CLASS_LIST in SVGElement.prototype)) {
+ defineProperty(SVGElement.prototype, CLASS_LIST, classListDescriptor);
+ }
+
+ // http://www.w3.org/TR/dom/#domtokenlist
+ // iOS 5.1 has completely screwed this property
+ // classList in ElementPrototype is false
+ // but it's actually there as getter
+ if (!(CLASS_LIST in document.documentElement)) {
+ defineProperty(ElementPrototype, CLASS_LIST, classListDescriptor);
} else {
// iOS 5.1 and Nokia ASHA do not support multiple add or remove
// trying to detect and fix that in here
- DOMTokenList = document.createElement('div').classList;
- DOMTokenList.add('a', 'b', 'a');
- if ('a\x20b' != DOMTokenList) {
+ TemporaryTokenList = document.createElement('div')[CLASS_LIST];
+ TemporaryTokenList.add('a', 'b', 'a');
+ if ('a\x20b' != TemporaryTokenList) {
// no other way to reach original methods in iOS 5.1
- ElementPrototype = DOMTokenList.constructor.prototype;
- if (!('add' in ElementPrototype)) {
+ TemporaryPrototype = TemporaryTokenList.constructor.prototype;
+ if (!('add' in TemporaryPrototype)) {
// ASHA double fails in here
- ElementPrototype = window.DOMTokenList.prototype;
+ TemporaryPrototype = window.TemporaryTokenList.prototype;
}
- verifyToken = function (original) {
+ wrapVerifyToken = function (original) {
return function () {
var i = 0;
while (i < arguments.length) {
original.call(this, arguments[i++]);
}
};
};
- ElementPrototype.add = verifyToken(ElementPrototype.add);
- ElementPrototype.remove = verifyToken(ElementPrototype.remove);
+ TemporaryPrototype.add = wrapVerifyToken(TemporaryPrototype.add);
+ TemporaryPrototype.remove = wrapVerifyToken(TemporaryPrototype.remove);
// toggle is broken too ^_^ ... let's fix it
- ElementPrototype.toggle = toggle;
+ TemporaryPrototype.toggle = toggle;
}
}
View
@@ -1,6 +1,6 @@
{
"name": "dom4",
- "version": "1.3.3",
+ "version": "1.4.0",
"description": "a fully tested and covered polyfill for new DOM Level 4 entries",
"homepage": "https://github.com/WebReflection/dom4",
"keywords": [
View
@@ -2,7 +2,7 @@
"name": "dom4",
"title": "DOM4",
"description": "a fully tested and covered polyfill for new DOM Level 4 entries",
- "version": "1.3.3",
+ "version": "1.4.0",
"main": "build/dom4.js",
"homepage": "https://github.com/WebReflection/dom4",
"author": {
@@ -26,8 +26,16 @@
"url": "https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt"
}
],
+ "scripts": {
+ "test": "phantomjs testrunner.js",
+ "web": "IP=0.0.0.0 node node_modules/polpetta"
+ },
"dependencies": {},
"devDependencies": {
- "wru": ">= 0.0.0"
+ "wru": "~0.2.x",
+ "uglify-js": "1.x",
+ "jshint": "~2.x",
+ "polpetta": "~0.3.x",
+ "phantomjs": "~1.x"
}
}
Oops, something went wrong.

0 comments on commit da653ed

Please sign in to comment.