1
0
Эх сурвалжийг харах

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

Thibaut Courouble 8 жил өмнө
parent
commit
0e134dabdb

+ 0 - 1
assets/javascripts/app/app.coffee

@@ -250,7 +250,6 @@
         bind:               !!Function::bind
         pushState:          !!history.pushState
         matchMedia:         !!window.matchMedia
-        classList:          !!document.body.classList
         insertAdjacentHTML: !!document.body.insertAdjacentHTML
         defaultPrevented:     document.createEvent('CustomEvent').defaultPrevented is false
         cssGradients:         supportsCssGradients()

+ 240 - 0
assets/javascripts/vendor/classlist.js

@@ -0,0 +1,240 @@
+/*
+ * classList.js: Cross-browser full element.classList implementation.
+ * 1.1.20170427
+ *
+ * By Eli Grey, http://eligrey.com
+ * License: Dedicated to the public domain.
+ *   See https://github.com/eligrey/classList.js/blob/master/LICENSE.md
+ */
+
+/*global self, document, DOMException */
+
+/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
+
+if ("document" in self) {
+
+// Full polyfill for browsers with no classList support
+// Including IE < Edge missing SVGElement.classList
+if (!("classList" in document.createElement("_"))
+  || document.createElementNS && !("classList" in document.createElementNS("http://www.w3.org/2000/svg","g"))) {
+
+(function (view) {
+
+"use strict";
+
+if (!('Element' in view)) return;
+
+var
+    classListProp = "classList"
+  , protoProp = "prototype"
+  , elemCtrProto = view.Element[protoProp]
+  , objCtr = Object
+  , strTrim = String[protoProp].trim || function () {
+    return this.replace(/^\s+|\s+$/g, "");
+  }
+  , arrIndexOf = Array[protoProp].indexOf || function (item) {
+    var
+        i = 0
+      , len = this.length
+    ;
+    for (; i < len; i++) {
+      if (i in this && this[i] === item) {
+        return i;
+      }
+    }
+    return -1;
+  }
+  // Vendors: please allow content code to instantiate DOMExceptions
+  , DOMEx = function (type, message) {
+    this.name = type;
+    this.code = DOMException[type];
+    this.message = message;
+  }
+  , checkTokenAndGetIndex = function (classList, token) {
+    if (token === "") {
+      throw new DOMEx(
+          "SYNTAX_ERR"
+        , "An invalid or illegal string was specified"
+      );
+    }
+    if (/\s/.test(token)) {
+      throw new DOMEx(
+          "INVALID_CHARACTER_ERR"
+        , "String contains an invalid character"
+      );
+    }
+    return arrIndexOf.call(classList, token);
+  }
+  , ClassList = function (elem) {
+    var
+        trimmedClasses = strTrim.call(elem.getAttribute("class") || "")
+      , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
+      , i = 0
+      , len = classes.length
+    ;
+    for (; i < len; i++) {
+      this.push(classes[i]);
+    }
+    this._updateClassName = function () {
+      elem.setAttribute("class", this.toString());
+    };
+  }
+  , classListProto = ClassList[protoProp] = []
+  , classListGetter = function () {
+    return new ClassList(this);
+  }
+;
+// Most DOMException implementations don't allow calling DOMException's toString()
+// on non-DOMExceptions. Error's toString() is sufficient here.
+DOMEx[protoProp] = Error[protoProp];
+classListProto.item = function (i) {
+  return this[i] || null;
+};
+classListProto.contains = function (token) {
+  token += "";
+  return checkTokenAndGetIndex(this, token) !== -1;
+};
+classListProto.add = function () {
+  var
+      tokens = arguments
+    , i = 0
+    , l = tokens.length
+    , token
+    , updated = false
+  ;
+  do {
+    token = tokens[i] + "";
+    if (checkTokenAndGetIndex(this, token) === -1) {
+      this.push(token);
+      updated = true;
+    }
+  }
+  while (++i < l);
+
+  if (updated) {
+    this._updateClassName();
+  }
+};
+classListProto.remove = function () {
+  var
+      tokens = arguments
+    , i = 0
+    , l = tokens.length
+    , token
+    , updated = false
+    , index
+  ;
+  do {
+    token = tokens[i] + "";
+    index = checkTokenAndGetIndex(this, token);
+    while (index !== -1) {
+      this.splice(index, 1);
+      updated = true;
+      index = checkTokenAndGetIndex(this, token);
+    }
+  }
+  while (++i < l);
+
+  if (updated) {
+    this._updateClassName();
+  }
+};
+classListProto.toggle = function (token, force) {
+  token += "";
+
+  var
+      result = this.contains(token)
+    , method = result ?
+      force !== true && "remove"
+    :
+      force !== false && "add"
+  ;
+
+  if (method) {
+    this[method](token);
+  }
+
+  if (force === true || force === false) {
+    return force;
+  } else {
+    return !result;
+  }
+};
+classListProto.toString = function () {
+  return this.join(" ");
+};
+
+if (objCtr.defineProperty) {
+  var classListPropDesc = {
+      get: classListGetter
+    , enumerable: true
+    , configurable: true
+  };
+  try {
+    objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+  } catch (ex) { // IE 8 doesn't support enumerable:true
+    // adding undefined to fight this issue https://github.com/eligrey/classList.js/issues/36
+    // modernie IE8-MSW7 machine has IE8 8.0.6001.18702 and is affected
+    if (ex.number === undefined || ex.number === -0x7FF5EC54) {
+      classListPropDesc.enumerable = false;
+      objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
+    }
+  }
+} else if (objCtr[protoProp].__defineGetter__) {
+  elemCtrProto.__defineGetter__(classListProp, classListGetter);
+}
+
+}(self));
+
+}
+
+// There is full or partial native classList support, so just check if we need
+// to normalize the add/remove and toggle APIs.
+
+(function () {
+  "use strict";
+
+  var testElement = document.createElement("_");
+
+  testElement.classList.add("c1", "c2");
+
+  // Polyfill for IE 10/11 and Firefox <26, where classList.add and
+  // classList.remove exist but support only one argument at a time.
+  if (!testElement.classList.contains("c2")) {
+    var createMethod = function(method) {
+      var original = DOMTokenList.prototype[method];
+
+      DOMTokenList.prototype[method] = function(token) {
+        var i, len = arguments.length;
+
+        for (i = 0; i < len; i++) {
+          token = arguments[i];
+          original.call(this, token);
+        }
+      };
+    };
+    createMethod('add');
+    createMethod('remove');
+  }
+
+  testElement.classList.toggle("c3", false);
+
+  // Polyfill for IE 10 and Firefox <24, where classList.toggle does not
+  // support the second argument.
+  if (testElement.classList.contains("c3")) {
+    var _toggle = DOMTokenList.prototype.toggle;
+
+    DOMTokenList.prototype.toggle = function(token, force) {
+      if (1 in arguments && !this.contains(token) === !force) {
+        return force;
+      } else {
+        return _toggle.call(this, token);
+      }
+    };
+
+  }
+
+  testElement = null;
+}());
+
+}