History

Add classList polyfill for IE, which doesn't support it on SVG elements

Thibaut Courouble committed 9 years ago

Commit 0e134da1 parent 30dd32c2 files · +240 −1Browse files

Unified · Split

2 files
  1. assets/javascripts/app/app.coffee +0 −1
  2. assets/javascripts/vendor/classlist.js +240 −0
assets/javascripts/app/app.coffee+0−1
@@ -250,7 +250,6 @@ · 249 unmodified lines
250 bind: !!Function::bind250 bind: !!Function::bind
251 pushState: !!history.pushState251 pushState: !!history.pushState
252 matchMedia: !!window.matchMedia252 matchMedia: !!window.matchMedia
253 classList: !!document.body.classList
254 insertAdjacentHTML: !!document.body.insertAdjacentHTML253 insertAdjacentHTML: !!document.body.insertAdjacentHTML
255 defaultPrevented: document.createEvent('CustomEvent').defaultPrevented is false254 defaultPrevented: document.createEvent('CustomEvent').defaultPrevented is false
256 cssGradients: supportsCssGradients()255 cssGradients: supportsCssGradients()
assets/javascripts/vendor/classlist.js+240−0
@@ -0,0 +1,240 @@
1/*
2 * classList.js: Cross-browser full element.classList implementation.
3 * 1.1.20170427
4 *
5 * By Eli Grey, http://eligrey.com
6 * License: Dedicated to the public domain.
7 * See https://github.com/eligrey/classList.js/blob/master/LICENSE.md
8 */
9
10/*global self, document, DOMException */
11
12/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
13
14if ("document" in self) {
15
16// Full polyfill for browsers with no classList support
17// Including IE < Edge missing SVGElement.classList
18if (!("classList" in document.createElement("_"))
19 || document.createElementNS && !("classList" in document.createElementNS("http://www.w3.org/2000/svg","g"))) {
20
21(function (view) {
22
23"use strict";
24
25if (!('Element' in view)) return;
26
27var
28 classListProp = "classList"
29 , protoProp = "prototype"
30 , elemCtrProto = view.Element[protoProp]
31 , objCtr = Object
32 , strTrim = String[protoProp].trim || function () {
33 return this.replace(/^\s+|\s+$/g, "");
34 }
35 , arrIndexOf = Array[protoProp].indexOf || function (item) {
36 var
37 i = 0
38 , len = this.length
39 ;
40 for (; i < len; i++) {
41 if (i in this && this[i] === item) {
42 return i;
43 }
44 }
45 return -1;
46 }
47 // Vendors: please allow content code to instantiate DOMExceptions
48 , DOMEx = function (type, message) {
49 this.name = type;
50 this.code = DOMException[type];
51 this.message = message;
52 }
53 , checkTokenAndGetIndex = function (classList, token) {
54 if (token === "") {
55 throw new DOMEx(
56 "SYNTAX_ERR"
57 , "An invalid or illegal string was specified"
58 );
59 }
60 if (/\s/.test(token)) {
61 throw new DOMEx(
62 "INVALID_CHARACTER_ERR"
63 , "String contains an invalid character"
64 );
65 }
66 return arrIndexOf.call(classList, token);
67 }
68 , ClassList = function (elem) {
69 var
70 trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
71 , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
72 , i = 0
73 , len = classes.length
74 ;
75 for (; i < len; i++) {
76 this.push(classes[i]);
77 }
78 this._updateClassName = function () {
79 elem.setAttribute("class", this.toString());
80 };
81 }
82 , classListProto = ClassList[protoProp] = []
83 , classListGetter = function () {
84 return new ClassList(this);
85 }
86;
87// Most DOMException implementations don't allow calling DOMException's toString()
88// on non-DOMExceptions. Error's toString() is sufficient here.
89DOMEx[protoProp] = Error[protoProp];
90classListProto.item = function (i) {
91 return this[i] || null;
92};
93classListProto.contains = function (token) {
94 token += "";
95 return checkTokenAndGetIndex(this, token) !== -1;
96};
97classListProto.add = function () {
98 var
99 tokens = arguments
100 , i = 0
101 , l = tokens.length
102 , token
103 , updated = false
104 ;
105 do {
106 token = tokens[i] + "";
107 if (checkTokenAndGetIndex(this, token) === -1) {
108 this.push(token);
109 updated = true;
110 }
111 }
112 while (++i < l);
113
114 if (updated) {
115 this._updateClassName();
116 }
117};
118classListProto.remove = function () {
119 var
120 tokens = arguments
121 , i = 0
122 , l = tokens.length
123 , token
124 , updated = false
125 , index
126 ;
127 do {
128 token = tokens[i] + "";
129 index = checkTokenAndGetIndex(this, token);
130 while (index !== -1) {
131 this.splice(index, 1);
132 updated = true;
133 index = checkTokenAndGetIndex(this, token);
134 }
135 }
136 while (++i < l);
137
138 if (updated) {
139 this._updateClassName();
140 }
141};
142classListProto.toggle = function (token, force) {
143 token += "";
144
145 var
146 result = this.contains(token)
147 , method = result ?
148 force !== true && "remove"
149 :
150 force !== false && "add"
151 ;
152
153 if (method) {
154 this[method](token);
155 }
156
157 if (force === true || force === false) {
158 return force;
159 } else {
160 return !result;
161 }
162};
163classListProto.toString = function () {
164 return this.join(" ");
165};
166
167if (objCtr.defineProperty) {
168 var classListPropDesc = {
169 get: classListGetter
170 , enumerable: true
171 , configurable: true
172 };
173 try {
174 objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
175 } catch (ex) { // IE 8 doesn't support enumerable:true
176 // adding undefined to fight this issue https://github.com/eligrey/classList.js/issues/36
177 // modernie IE8-MSW7 machine has IE8 8.0.6001.18702 and is affected
178 if (ex.number === undefined || ex.number === -0x7FF5EC54) {
179 classListPropDesc.enumerable = false;
180 objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
181 }
182 }
183} else if (objCtr[protoProp].__defineGetter__) {
184 elemCtrProto.__defineGetter__(classListProp, classListGetter);
185}
186
187}(self));
188
189}
190
191// There is full or partial native classList support, so just check if we need
192// to normalize the add/remove and toggle APIs.
193
194(function () {
195 "use strict";
196
197 var testElement = document.createElement("_");
198
199 testElement.classList.add("c1", "c2");
200
201 // Polyfill for IE 10/11 and Firefox <26, where classList.add and
202 // classList.remove exist but support only one argument at a time.
203 if (!testElement.classList.contains("c2")) {
204 var createMethod = function(method) {
205 var original = DOMTokenList.prototype[method];
206
207 DOMTokenList.prototype[method] = function(token) {
208 var i, len = arguments.length;
209
210 for (i = 0; i < len; i++) {
211 token = arguments[i];
212 original.call(this, token);
213 }
214 };
215 };
216 createMethod('add');
217 createMethod('remove');
218 }
219
220 testElement.classList.toggle("c3", false);
221
222 // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
223 // support the second argument.
224 if (testElement.classList.contains("c3")) {
225 var _toggle = DOMTokenList.prototype.toggle;
226
227 DOMTokenList.prototype.toggle = function(token, force) {
228 if (1 in arguments && !this.contains(token) === !force) {
229 return force;
230 } else {
231 return _toggle.call(this, token);
232 }
233 };
234
235 }
236
237 testElement = null;
238}());
239
240}