polyfills.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. // This file can be removed, when we stop supporting IE11.
  3. // Polyfill for .before()
  4. // from: https://github.com/jserz/js_piece/blob/master/DOM/ChildNode/before()/before().md
  5. // Copyright (c) 2016-present, jszhou
  6. // MIT License
  7. (function (arr) {
  8. arr.forEach(function (item) {
  9. if (item.hasOwnProperty('before')) {
  10. return;
  11. }
  12. Object.defineProperty(item, 'before', {
  13. configurable: true,
  14. enumerable: true,
  15. writable: true,
  16. value: function before() {
  17. var argArr = Array.prototype.slice.call(arguments),
  18. docFrag = document.createDocumentFragment();
  19. argArr.forEach(function (argItem) {
  20. var isNode = argItem instanceof Node;
  21. docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem)));
  22. });
  23. this.parentNode.insertBefore(docFrag, this);
  24. }
  25. });
  26. });
  27. })([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
  28. // Polyfill for .startsWith()
  29. // from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill
  30. if (!String.prototype.startsWith) {
  31. Object.defineProperty(String.prototype, 'startsWith', {
  32. value: function(search, pos) {
  33. pos = !pos || pos < 0 ? 0 : +pos;
  34. return this.substring(pos, pos + search.length) === search;
  35. }
  36. });
  37. }
  38. // Polyfill for .matches()
  39. // from: https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
  40. if (!Element.prototype.matches) {
  41. Element.prototype.matches = Element.prototype.msMatchesSelector ||
  42. Element.prototype.webkitMatchesSelector;
  43. }
  44. // Polyfill for iterable Set (IE11)
  45. // from: https://stackoverflow.com/a/45686452/3057764
  46. if (new Set([0]).size === 0) {
  47. //constructor doesn't take an iterable as an argument - thanks IE
  48. const BuiltinSet = Set;
  49. Set = function Set(iterable) {
  50. const set = new BuiltinSet();
  51. if (iterable) {
  52. iterable.forEach(set.add, set);
  53. }
  54. return set;
  55. };
  56. Set.prototype = BuiltinSet.prototype;
  57. Set.prototype.constructor = Set;
  58. }
  59. // Polyfill for using :scope in querySelector/querySelectorAll
  60. // from: https://github.com/lazd/scopedQuerySelectorShim
  61. // Copyright (C) 2015 Larry Davis
  62. // This software may be modified and distributed under the terms of the BSD license.
  63. (function() {
  64. if (!HTMLElement.prototype.querySelectorAll) {
  65. throw new Error("rootedQuerySelectorAll: This polyfill can only be used with browsers that support querySelectorAll");
  66. }
  67. // A temporary element to query against for elements not currently in the DOM
  68. // We'll also use this element to test for :scope support
  69. var container = document.createElement("div");
  70. // Check if the browser supports :scope
  71. try {
  72. // Browser supports :scope, do nothing
  73. container.querySelectorAll(":scope *");
  74. } catch (e) {
  75. // Match usage of scope
  76. var scopeRE = /^\s*:scope/gi;
  77. // Overrides
  78. function overrideNodeMethod(prototype, methodName) {
  79. // Store the old method for use later
  80. var oldMethod = prototype[methodName];
  81. // Override the method
  82. prototype[methodName] = function(query) {
  83. var nodeList, gaveId = false, gaveContainer = false;
  84. if (query.match(scopeRE)) {
  85. // Remove :scope
  86. query = query.replace(scopeRE, "");
  87. if (!this.parentNode) {
  88. // Add to temporary container
  89. container.appendChild(this);
  90. gaveContainer = true;
  91. }
  92. parentNode = this.parentNode;
  93. if (!this.id) {
  94. // Give temporary ID
  95. this.id = "rootedQuerySelector_id_" + new Date().getTime();
  96. gaveId = true;
  97. }
  98. // Find elements against parent node
  99. nodeList = oldMethod.call(parentNode, "#" + this.id + " " + query);
  100. // Reset the ID
  101. if (gaveId) {
  102. this.id = "";
  103. }
  104. // Remove from temporary container
  105. if (gaveContainer) {
  106. container.removeChild(this);
  107. }
  108. return nodeList;
  109. } else {
  110. // No immediate child selector used
  111. return oldMethod.call(this, query);
  112. }
  113. };
  114. }
  115. // Browser doesn't support :scope, add polyfill
  116. overrideNodeMethod(HTMLElement.prototype, "querySelector");
  117. overrideNodeMethod(HTMLElement.prototype, "querySelectorAll");
  118. }
  119. })();
  120. /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */