UNPKG

lu2

Version:

Simple and flexible UI component library based on native HTML and JavaScript

1,536 lines (1,327 loc) 74.1 kB
/* eslint-disable require-jsdoc */ /** * @description 一些兼容IE浏览器的原生方法合集, * 大多数方法源自开源项目 * @author zhangxinxu(.com) * @created 2019-07-08 */ /* * classList.js: Cross-browser full element.classList implementation. * 1.2.20171210 * * 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'; var protoProp = 'prototype'; var elemCtrProto = view.Element[protoProp]; var objCtr = Object; var strTrim = String[protoProp].trim || function () { return this.replace(/^\s+|\s+$/g, ''); }; var arrIndexOf = Array[protoProp].indexOf || function (item) { var i = 0; var 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 var DOMEx = function (type, message) { this.name = type; this.code = DOMException[type]; this.message = message; }; var checkTokenAndGetIndex = function (classList, token) { if (token === '') { throw new DOMEx('SYNTAX_ERR', 'The token must not be empty.'); } if (/\s/.test(token)) { throw new DOMEx('INVALID_CHARACTER_ERR', 'The token must not contain space characters.'); } return arrIndexOf.call(classList, token); }; var ClassList = function (elem) { var trimmedClasses = strTrim.call(elem.getAttribute('class') || ''); var classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []; var i = 0; var len = classes.length; for (; i < len; i++) { this.push(classes[i]); } this._updateClassName = function () { elem.setAttribute('class', this.toString()); }; }; var classListProto = ClassList[protoProp] = []; var 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) { return ~checkTokenAndGetIndex(this, token + ''); }; classListProto.add = function () { var tokens = arguments; var i = 0; var l = tokens.length; var token; var updated = false; do { token = tokens[i] + ''; if (!~checkTokenAndGetIndex(this, token)) { this.push(token); updated = true; } } while (++i < l); if (updated) { this._updateClassName(); } }; classListProto.remove = function () { var tokens = arguments; var i = 0; var l = tokens.length; var token; var updated = false; var index; do { token = tokens[i] + ''; index = checkTokenAndGetIndex(this, token); while (~index) { this.splice(index, 1); updated = true; index = checkTokenAndGetIndex(this, token); } } while (++i < l); if (updated) { this._updateClassName(); } }; classListProto.toggle = function (token, force) { var result = this.contains(token); var method = result ? force !== true && 'remove' : force !== false && 'add'; if (method) { this[method](token); } if (force === true || force === false) { return force; } return !result; }; classListProto.replace = function (token, replacementToken) { var index = checkTokenAndGetIndex(token + ''); if (~index) { this.splice(index, 1, replacementToken); this._updateClassName(); } }; 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; var 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; } return _toggle.call(this, token); }; } // replace() polyfill if (!('replace' in document.createElement('_').classList)) { DOMTokenList.prototype.replace = function (token, replacementToken) { var tokens = this.toString().split(' '); var index = tokens.indexOf(token + ''); if (index * 1) { tokens = tokens.slice(index); this.remove.apply(this, tokens); this.add(replacementToken); this.add.apply(this, tokens.slice(1)); } }; } testElement = null; }()); } if (!document.documentElement.dataset) { Object.defineProperty(HTMLElement.prototype, 'dataset', { get: function () { var attrs = this.attributes; var obj = {}; for (var i = attrs.length - 1; i >= 0; i--) { obj[attrs[i].name] = attrs[i].value; } return obj; }, set: function () { } }); } /** * IE 11 - Edge 38 event.target是SVGElementInstance元素问题修复 * @param {[type]} [description] * @return {[type]} [description] */ if (window.SVGElementInstance) { SVGElementInstance.prototype.getAttribute = function (attributeName) { if (this.correspondingUseElement) { return this.correspondingUseElement.getAttribute(attributeName); } }; } /** * URL() and URLSearchParams() polyfill */ (function (global) { /** * Polyfill URLSearchParams * * Inspired from : https://github.com/WebReflection/url-search-params/blob/master/src/url-search-params.js */ var checkIfIteratorIsSupported = function () { try { return !!Symbol.iterator; } catch (error) { return false; } }; var iteratorSupported = checkIfIteratorIsSupported(); var createIterator = function (items) { var iterator = { next: function () { var value = items.shift(); return { done: value === void 0, value: value }; } }; if (iteratorSupported) { iterator[Symbol.iterator] = function () { return iterator; }; } return iterator; }; /** * Search param name and values should be encoded according to https://url.spec.whatwg.org/#urlencoded-serializing * encodeURIComponent() produces the same result except encoding spaces as `%20` instead of `+`. */ var serializeParam = function (value) { return encodeURIComponent(value).replace(/%20/g, '+'); }; var deserializeParam = function (value) { return decodeURIComponent(String(value).replace(/\+/g, ' ')); }; var polyfillURLSearchParams = function () { var URLSearchParams = function (searchString) { Object.defineProperty(this, '_entries', { writable: true, value: {} }); var typeofSearchString = typeof searchString; if (typeofSearchString === 'undefined') { // do nothing } else if (typeofSearchString === 'string') { if (searchString !== '') { this._fromString(searchString); } } else if (searchString instanceof URLSearchParams) { var _this = this; searchString.forEach(function (value, name) { _this.append(name, value); }); } else if ((searchString !== null) && (typeofSearchString === 'object')) { if (Object.prototype.toString.call(searchString) === '[object Array]') { for (var i = 0; i < searchString.length; i++) { var entry = searchString[i]; if ((Object.prototype.toString.call(entry) === '[object Array]') || (entry.length !== 2)) { this.append(entry[0], entry[1]); } else { throw new TypeError('Expected [string, any] as entry at index ' + i + ' of URLSearchParams\'s input'); } } } else if (searchString instanceof FormData && searchString._data) { for (var keyData in searchString._data) { if (searchString._data.hasOwnProperty(keyData)) { this.append(keyData, searchString._data[keyData]); } } } else { for (var key in searchString) { if (searchString.hasOwnProperty(key)) { this.append(key, searchString[key]); } } } } else { throw new TypeError('Unsupported input\'s type for URLSearchParams'); } }; var proto = URLSearchParams.prototype; proto.append = function (name, value) { if (name in this._entries) { this._entries[name].push(String(value)); } else { this._entries[name] = [String(value)]; } }; proto['delete'] = function (name) { delete this._entries[name]; }; proto.get = function (name) { return (name in this._entries) ? this._entries[name][0] : null; }; proto.getAll = function (name) { return (name in this._entries) ? this._entries[name].slice(0) : []; }; proto.has = function (name) { return (name in this._entries); }; proto.set = function (name, value) { this._entries[name] = [String(value)]; }; proto.forEach = function (callback, thisArg) { var entries; for (var name in this._entries) { if (this._entries.hasOwnProperty(name)) { entries = this._entries[name]; for (var i = 0; i < entries.length; i++) { callback.call(thisArg, entries[i], name, this); } } } }; proto.keys = function () { var items = []; this.forEach(function (value, name) { items.push(name); }); return createIterator(items); }; proto.values = function () { var items = []; this.forEach(function (value) { items.push(value); }); return createIterator(items); }; proto.entries = function () { var items = []; this.forEach(function (value, name) { items.push([name, value]); }); return createIterator(items); }; if (iteratorSupported) { proto[Symbol.iterator] = proto.entries; } proto.toString = function () { var searchArray = []; this.forEach(function (value, name) { searchArray.push(serializeParam(name) + '=' + serializeParam(value)); }); return searchArray.join('&'); }; global.URLSearchParams = URLSearchParams; }; var checkIfURLSearchParamsSupported = function () { try { var URLSearchParams = global.URLSearchParams; return (new URLSearchParams('?a=1').toString() === 'a=1') && (typeof URLSearchParams.prototype.set === 'function'); } catch (e) { return false; } }; if (!checkIfURLSearchParamsSupported()) { polyfillURLSearchParams(); } var proto = global.URLSearchParams.prototype; if (typeof proto.sort !== 'function') { proto.sort = function () { var _this = this; var items = []; this.forEach(function (value, name) { items.push([name, value]); if (!_this._entries) { _this['delete'](name); } }); items.sort(function (a, b) { if (a[0] < b[0]) { return -1; } else if (a[0] > b[0]) { return +1; } return 0; }); // force reset because IE keeps keys index if (_this._entries) { _this._entries = {}; } for (var i = 0; i < items.length; i++) { this.append(items[i][0], items[i][1]); } }; } if (typeof proto._fromString !== 'function') { Object.defineProperty(proto, '_fromString', { enumerable: false, configurable: false, writable: false, value: function (searchString) { if (this._entries) { this._entries = {}; } else { var keys = []; this.forEach(function (value, name) { keys.push(name); }); for (var i = 0; i < keys.length; i++) { this['delete'](keys[i]); } } searchString = searchString.replace(/^\?/, ''); var attributes = searchString.split('&'); var attribute; for (var ii = 0; ii < attributes.length; ii++) { attribute = attributes[ii].split('='); this.append( deserializeParam(attribute[0]), (attribute.length > 1) ? deserializeParam(attribute[1]) : '' ); } } }); } // HTMLAnchorElement })( (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : ((typeof self !== 'undefined') ? self : this)) ); (function (global) { /** * Polyfill URL * * Inspired from : https://github.com/arv/DOM-URL-Polyfill/blob/master/src/url.js */ var checkIfURLIsSupported = function () { try { var u = new global.URL('b', 'http://a'); u.pathname = 'c%20d'; return (u.href === 'http://a/c%20d') && u.searchParams; } catch (e) { return false; } }; var polyfillURL = function () { var _URL = global.URL; var URL = function (url, base) { if (typeof url !== 'string') url = String(url); // Only create another document if the base is different from current location. var doc = document; var baseElement; if (base && (global.location === void 0 || base !== global.location.href)) { doc = document.implementation.createHTMLDocument(''); baseElement = doc.createElement('base'); baseElement.href = base; doc.head.appendChild(baseElement); try { if (baseElement.href.indexOf(base) !== 0) throw new Error(baseElement.href); } catch (err) { throw new Error('URL unable to set base ' + base + ' due to ' + err); } } var anchorElement = doc.createElement('a'); anchorElement.href = url; if (baseElement) { doc.body.appendChild(anchorElement); // force href to refresh anchorElement.href = anchorElement.href; } if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) { throw new TypeError('Invalid URL'); } Object.defineProperty(this, '_anchorElement', { value: anchorElement }); // create a linked searchParams which reflect its changes on URL var searchParams = new global.URLSearchParams(this.search); var enableSearchUpdate = true; var enableSearchParamsUpdate = true; var _this = this; ['append', 'delete', 'set'].forEach(function (methodName) { var method = searchParams[methodName]; searchParams[methodName] = function () { method.apply(searchParams, arguments); if (enableSearchUpdate) { enableSearchParamsUpdate = false; _this.search = searchParams.toString(); enableSearchParamsUpdate = true; } }; }); Object.defineProperty(this, 'searchParams', { value: searchParams, enumerable: true }); var search = void 0; Object.defineProperty(this, '_updateSearchParams', { enumerable: false, configurable: false, writable: false, value: function () { if (this.search !== search) { search = this.search; if (enableSearchParamsUpdate) { enableSearchUpdate = false; this.searchParams._fromString(this.search); enableSearchUpdate = true; } } } }); }; var proto = URL.prototype; var linkURLWithAnchorAttribute = function (attributeName) { Object.defineProperty(proto, attributeName, { get: function () { return this._anchorElement[attributeName]; }, set: function (value) { this._anchorElement[attributeName] = value; }, enumerable: true }); }; ['hash', 'host', 'hostname', 'port', 'protocol'] .forEach(function (attributeName) { linkURLWithAnchorAttribute(attributeName); }); Object.defineProperty(proto, 'search', { get: function () { return this._anchorElement['search']; }, set: function (value) { this._anchorElement['search'] = value; this._updateSearchParams(); }, enumerable: true }); Object.defineProperties(proto, { 'toString': { get: function () { var _this = this; return function () { return _this.href; }; } }, 'href': { get: function () { return this._anchorElement.href.replace(/\?$/, ''); }, set: function (value) { this._anchorElement.href = value; this._updateSearchParams(); }, enumerable: true }, 'pathname': { get: function () { return this._anchorElement.pathname.replace(/(^\/?)/, '/'); }, set: function (value) { this._anchorElement.pathname = value; }, enumerable: true }, 'origin': { get: function () { // get expected port from protocol var expectedPort = { 'http:': 80, 'https:': 443, 'ftp:': 21 }[this._anchorElement.protocol]; // add port to origin if, expected port is different than actual port // and it is not empty f.e http://foo:8080 // 8080 != 80 && 8080 != '' var addPortToOrigin = this._anchorElement.port != expectedPort && this._anchorElement.port !== ''; return this._anchorElement.protocol + '//' + this._anchorElement.hostname + (addPortToOrigin ? (':' + this._anchorElement.port) : ''); }, enumerable: true }, 'password': { // TODO get: function () { return ''; }, set: function (value) { }, enumerable: true }, 'username': { // TODO get: function () { return ''; }, set: function (value) { }, enumerable: true } }); URL.createObjectURL = function (blob) { return _URL.createObjectURL.apply(_URL, arguments); }; URL.revokeObjectURL = function (url) { return _URL.revokeObjectURL.apply(_URL, arguments); }; global.URL = URL; }; if (!checkIfURLIsSupported()) { polyfillURL(); } if ((global.location !== void 0) && !('origin' in global.location)) { var getOrigin = function () { return global.location.protocol + '//' + global.location.hostname + (global.location.port ? (':' + global.location.port) : ''); }; try { Object.defineProperty(global.location, 'origin', { get: getOrigin, enumerable: true }); } catch (e) { setInterval(function () { global.location.origin = getOrigin(); }, 100); } } })( (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : ((typeof self !== 'undefined') ? self : this)) ); /* * @preserve FormData polyfill for IE < 10. See https://developer.mozilla.org/en/docs/Web/API/FormData and http://caniuse.com/#search=formdata * * @author ShirtlessKirk copyright 2015 * @license WTFPL (http://www.wtfpl.net/txt/copying) */ /*global define: false, module: false */ /*jslint bitwise: true, continue: true, nomen: true */ (function formDataModule(global, definition) { // non-exporting module magic dance 'use strict'; var amd = 'amd', exports = 'exports'; // keeps the method names for CommonJS / AMD from being compiled to single character variable if (typeof define === 'function' && define[amd]) { define(function definer() { return definition(global); }); } else if (typeof module === 'function' && module[exports]) { module[exports] = definition(global); } else { definition(global); } }((typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : ((typeof self !== 'undefined') ? self : this)), function formDataPartialPolyfill(global) { // partial polyfill 'use strict'; var formDataPrototype, math = Math, method, methods, xhrSend, xmlHttpRequestPrototype; function has (key) { return this._data.hasOwnProperty(key); } function append (key, value) { var self = this; if (!has.call(self, key)) { self._data[key] = []; } self._data[key].push(value); } function deleteFn (key) { delete this._data[key]; } function getAll (key) { return this._data[key] || null; } function get (key) { var values = getAll.call(this, key); return values ? values[0] : null; } function set (key, value) { this._data[key] = [value]; } function createBoundary () { // for XHR var random = math.random; var salt = (random() * math.pow(10, ((random() * 12) | 0) + 1)); var hash = (random() * salt).toString(36); return '----------------FormData-' + hash; } function parseContents (children) { var child, counter, counter2, length, length2, name, option, self = this; for (counter = 0, length = children.length; counter < length; counter += 1) { child = children[counter]; name = child.name || child.id; if (!name || child.disabled) { continue; } switch (child.type) { case 'checkbox': if (child.checked) { self.append(name, child.value || 'on'); } break; // x/y coordinates or origin if missing case 'image': self.append(name + '.x', child.x || 0); self.append(name + '.y', child.y || 0); break; case 'radio': if (child.checked) { // using .set as only one can be valid (uses last one if more discovered) self.set(name, child.value); } break; case 'select-one': if (child.selectedIndex !== -1) { self.append(name, child.options[child.selectedIndex].value); } break; case 'select-multiple': for (counter2 = 0, length2 = child.options.length; counter2 < length2; counter2 += 1) { option = child.options[counter2]; if (option.selected) { self.append(name, option.value); } } break; case 'file': case 'reset': case 'submit': break; default: // hidden, text, textarea, password self.append(name, child.value); } } } function toString () { var self = this, body = [], data = self._data, key, prefix = '--'; for (key in data) { if (data.hasOwnProperty(key)) { body.push(prefix + self._boundary); // boundaries are prefixed with '--' // only form fields for now, files can wait / probably can't be done body.push('Content-Disposition: form-data; name="' + key + '"\r\n'); // two linebreaks between definition and content body.push(data[key]); } } if (body.length) { return body.join('\r\n') + '\r\n' + prefix + self._boundary + prefix; // form content ends with '--' } return ''; } /** * [FormData description] * @contructor * @param {?HTMLForm} form HTML <form> element to populate the object (optional) */ function FormData (form) { var self = this; if (!(self instanceof FormData)) { return new FormData(form); } if (form && (!form.tagName || form.tagName !== 'FORM')) { // not a form return; } self._boundary = createBoundary(); self._data = {}; if (!form) { // nothing to parse, we're done here return; } parseContents.call(self, form.children); } function send (data) { var self = this; if (data instanceof FormData) { self.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + data._boundary); return xhrSend.call(self, data.toString()); } return xhrSend.call(self, data || null); } methods = { append: append, get: get, getAll: getAll, has: has, set: set, toString: toString }; formDataPrototype = FormData.prototype; for (method in methods) { if (methods.hasOwnProperty(method)) { formDataPrototype[method] = methods[method]; } } formDataPrototype['delete'] = deleteFn; // IE9 if (!global.FormData) { xmlHttpRequestPrototype = global.XMLHttpRequest.prototype; xhrSend = xmlHttpRequestPrototype.send; xmlHttpRequestPrototype.send = send; global.FormData = FormData; } else if (!new global.FormData().getAll) { var fd = global.FormData; global.FormData = function (form) { if (form && form.tagName == 'FORM' && form.method.toLowerCase() == 'get') { global.FormData = FormData; return FormData(form); } // post请求还是使用原生FormData global.FormData = fd; return fd(form); }; } })); /** * closest polyfill */ if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; } if (!Element.prototype.closest) { Element.prototype.closest = function (s) { var el = this; do { if (el.matches(s)) return el; el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; }; } /** * NodeList forEach support */ if (window.NodeList && !NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype.forEach; } /** * hasAttribute polyfill */ (function (prototype) { prototype.hasAttribute = prototype.hasAttribute || function (name) { return !!(this.attributes[name] && this.attributes[name].specified); }; })(Element.prototype); /** * before() polyfill */ (function (arr) { arr.forEach(function (item) { if (item.hasOwnProperty('before')) { return; } Object.defineProperty(item, 'before', { configurable: true, enumerable: true, writable: true, value: function before () { var argArr = Array.prototype.slice.call(arguments); var docFrag = document.createDocumentFragment(); argArr.forEach(function (argItem) { var isNode = argItem instanceof Node; docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); }); this.parentNode.insertBefore(docFrag, this); } }); }); })([Element.prototype, CharacterData.prototype, DocumentType.prototype]); /** * after() polyfill */ (function (arr) { arr.forEach(function (item) { if (item.hasOwnProperty('after')) { return; } Object.defineProperty(item, 'after', { configurable: true, enumerable: true, writable: true, value: function after () { var argArr = Array.prototype.slice.call(arguments); var docFrag = document.createDocumentFragment(); argArr.forEach(function (argItem) { var isNode = argItem instanceof Node; docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); }); this.parentNode.insertBefore(docFrag, this.nextSibling); } }); }); })([Element.prototype, CharacterData.prototype, DocumentType.prototype]); /** * replaceWith() polyfill */ (function () { var ReplaceWith = function (Ele) { var parent = this.parentNode; var i = arguments.length; var firstIsNode = +(parent && typeof Ele === 'object'); if (!parent) return; while (i-- > firstIsNode) { if (parent && typeof arguments[i] !== 'object') { arguments[i] = document.createTextNode(arguments[i]); } if (!parent && arguments[i].parentNode) { arguments[i].parentNode.removeChild(arguments[i]); continue; } parent.insertBefore(this.previousSibling, arguments[i]); } if (firstIsNode) parent.replaceChild(this, Ele); }; if (!Element.prototype.replaceWith) { Element.prototype.replaceWith = ReplaceWith; } if (!CharacterData.prototype.replaceWith) { CharacterData.prototype.replaceWith = ReplaceWith; } if (!DocumentType.prototype.replaceWith) { CharacterData.prototype.replaceWith = ReplaceWith; } })(); /** * append() polyfill */ (function (arr) { arr.forEach(function (item) { if (item.hasOwnProperty('append')) { return; } Object.defineProperty(item, 'append', { configurable: true, enumerable: true, writable: true, value: function append() { var argArr = Array.prototype.slice.call(arguments); var docFrag = document.createDocumentFragment(); argArr.forEach(function (argItem) { var isNode = argItem instanceof Node; docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); }); this.appendChild(docFrag); } }); }); })([Element.prototype, Document.prototype, DocumentFragment.prototype]); /** * prepend() polyfill */ (function (arr) { arr.forEach(function (item) { if (item.hasOwnProperty('prepend')) { return; } Object.defineProperty(item, 'prepend', { configurable: true, enumerable: true, writable: true, value: function prepend() { var argArr = Array.prototype.slice.call(arguments); var docFrag = document.createDocumentFragment(); argArr.forEach(function (argItem) { var isNode = argItem instanceof Node; docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); }); this.insertBefore(docFrag, this.firstChild); } }); }); })([Element.prototype, Document.prototype, DocumentFragment.prototype]); /** * remove() polyfill */ (function (arr) { arr.forEach(function (item) { if (item.hasOwnProperty('remove')) { return; } Object.defineProperty(item, 'remove', { configurable: true, enumerable: true, writable: true, value: function remove() { if (this.parentNode === null) { return; } this.parentNode.removeChild(this); } }); }); })([Element.prototype, CharacterData.prototype, DocumentType.prototype]); /** * document.scrollingElement的polyfill * @type {[type]} */ /*! https://mths.be/scrollingelement v1.5.2 by @diegoperini & @mathias | MIT license */ if (!('scrollingElement' in document)) (function () { function computeStyle(element) { if (window.getComputedStyle) { // Support Firefox < 4 which throws on a single parameter. return getComputedStyle(element, null); } // Support Internet Explorer < 9. return element.currentStyle; } function isBodyElement(element) { // The `instanceof` check gives the correct result for e.g. `body` in a // non-HTML namespace. if (window.HTMLBodyElement) { return element instanceof HTMLBodyElement; } // Fall back to a `tagName` check for old browsers. return /body/i.test(element.tagName); } function getNextBodyElement(frameset) { // We use this function to be correct per spec in case `document.body` is // a `frameset` but there exists a later `body`. Since `document.body` is // a `frameset`, we know the root is an `html`, and there was no `body` // before the `frameset`, so we just need to look at siblings after the // `frameset`. var current = frameset; while (current = current.nextSibling) { if (current.nodeType == 1 && isBodyElement(current)) { return current; } } // No `body` found. return null; } // Note: standards mode / quirks mode can be toggled at runtime via // `document.write`. var isCompliantCached; var isCompliant = function () { var isStandardsMode = /^CSS1/.test(document.compatMode); if (!isStandardsMode) { // In quirks mode, the result is equivalent to the non-compliant // standards mode behavior. return false; } if (isCompliantCached === void 0) { // When called for the first time, check whether the browser is // standard-compliant, and cache the result. var iframe = document.createElement('iframe'); iframe.style.height = '1px'; (document.body || document.documentElement || document).appendChild(iframe); var doc = iframe.contentWindow.document; doc.write('<!DOCTYPE html><div style="height:9999em">x</div>'); doc.close(); isCompliantCached = doc.documentElement.scrollHeight > doc.body.scrollHeight; iframe.parentNode.removeChild(iframe); } return isCompliantCached; }; function isRendered(style) { return style.display != 'none' && !(style.visibility == 'collapse' && /^table-(.+-group|row|column)$/.test(style.display)); } function isScrollable(body) { // A `body` element is scrollable if `body` and `html` both have // non-`visible` overflow and are both being rendered. var bodyStyle = computeStyle(body); var htmlStyle = computeStyle(document.documentElement); return bodyStyle.overflow != 'visible' && htmlStyle.overflow != 'visible' && isRendered(bodyStyle) && isRendered(htmlStyle); } var scrollingElement = function () { if (isCompliant()) { return document.documentElement; } var body = document.body; // Note: `document.body` could be a `frameset` element, or `null`. // `tagName` is uppercase in HTML, but lowercase in XML. var isFrameset = body && !/body/i.test(body.tagName); body = isFrameset ? getNextBodyElement(body) : body; // If `body` is itself scrollable, it is not the `scrollingElement`. return body && isScrollable(body) ? null : body; }; if (Object.defineProperty) { // Support modern browsers that lack a native implementation. Object.defineProperty(document, 'scrollingElement', { 'get': scrollingElement }); } else if (document.__defineGetter__) { // Support Firefox ≤ 3.6.9, Safari ≤ 4.1.3. document.__defineGetter__('scrollingElement', scrollingElement); } else { // IE ≤ 4 lacks `attachEvent`, so it only gets this one assignment. IE ≤ 7 // gets it too, but the value is updated later (see `propertychange`). document.scrollingElement = scrollingElement(); document.attachEvent && document.attachEvent('onpropertychange', function () { // This is for IE ≤ 7 only. // A `propertychange` event fires when `<body>` is parsed because // `document.activeElement` then changes. if (window.event.propertyName == 'activeElement') { document.scrollingElement = scrollingElement(); } }); } }()); /** * Object.assign polyfill * @param {String} typeof Object.assign ! [description] * @return {[type]} [description] */ if (typeof Object.assign != 'function') { // Must be writable: true, enumerable: false, configurable: true Object.defineProperty(Object, 'assign', { value: function assign (target) { // .length of function is 2 'use strict'; if (target === null) { // TypeError if undefined or null throw new TypeError('Cannot convert undefined or null to object'); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource !== null) { // Skip over if undefined or null for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); } // Console-polyfill. MIT license. // https://github.com/paulmillr/console-polyfill // Make it safe to do console.log() always. (function (global) { 'use strict'; if (!global.console) { global.console = {}; } var con = global.console; var prop, method; var dummy = function () {}; var properties = ['memory']; var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn,timeLog,trace').split(','); while (prop = properties.pop()) if (!con[prop]) con[prop] = {}; while (method = methods.pop()) if (!con[method]) con[method] = dummy; // Using `this` for web workers & supports Browserify / Webpack. })((typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : ((typeof self !== 'undefined') ? self : this))); /** * CustomEvent constructor polyfill for IE * @return {[type]} [description] */ (function () { if (typeof window.CustomEvent === 'function') { //If not IE return false; } var CustomEvent = function (event, params) { params = params || { bubbles: false, cancelable: false, detail: undefined }; var evt = document.createEvent('CustomEvent'); evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); return evt; }; CustomEvent.prototype = window.Event.prototype; window.CustomEvent = CustomEvent; })(); /** * 字符串repeat for IE and some mobile * @param {[type]} !String.prototype.repeat [description] * @return {[type]} [description] */ if (!String.prototype.repeat) { String.prototype.repeat = function (count) { 'use strict'; if (this == null) { throw new TypeError('can\'t convert ' + this + ' to object'); } var str = '' + this; count = +count; if (count != count) { count = 0; } if (count < 0) { throw new RangeError('repeat count must be non-negative'); } if (count == Infinity) { throw new RangeError('repeat count must be less than infinity'); } count = Math.floor(count); if (str.length == 0 || count == 0) { return ''; } // 确保 count 是一个 31 位的整数。这样我们就可以使用如下优化的算法。 // 当前(2014年8月),绝大多数浏览器都不能支持 1 << 28 长的字符串,所以: if (str.length * count >= 1 << 28) { throw new RangeError('repeat count must not overflow maximum string size'); } var rpt = ''; for (;;) { if ((count & 1) == 1) { rpt += str; } count >>>= 1; if (count == 0) { break; } str += str; } return rpt; }; } // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel // MIT license (function () { var lastTime = 0; if (!window.requestAnimationFrame) { window.requestAnimationFrame = function (callback) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function () { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (id) { clearTimeout(id); }; } }()); /** * @description resize polyfill for IE/Edge * @author zhangxinxu(.com) */ if (typeof window.getComputedStyle(document.body).resize == 'undefined' && window.HTMLTextAreaElement) { HTMLTextAreaElement.prototype.setResize = function () { // 元素 var textarea = this; var target = textarea.data && textarea.data.resize; var resize = null; //