├── LICENSE
├── README.md
├── htmlfills.js
├── htmlfills.old.js
├── mod.js
├── monkeyPatches
├── addEventListenerSignal.js
├── addEventListenerSignal.test.html
├── elContainsText.js
├── focusOptions.js
├── forceToggle.js
└── test.html
├── polyfills
├── Array
│ ├── from.js
│ ├── of.js
│ └── prototype
│ │ ├── at.js
│ │ ├── copyWithin.js
│ │ ├── entries.js
│ │ ├── fill.js
│ │ ├── find.js
│ │ ├── findIndex.js
│ │ ├── findLast.js
│ │ ├── findLastIndex.js
│ │ ├── flat.js
│ │ ├── flatMap.js
│ │ ├── includes.js
│ │ ├── item.js
│ │ ├── keys.js
│ │ └── values.js
├── CSS
│ ├── escape.js
│ ├── registerProperty.js
│ └── supports.js
├── Element
│ ├── aom.combo.js
│ ├── aom.combo.test.html
│ ├── combo.js
│ └── prototype
│ │ ├── isVisible.js
│ │ ├── replaceChildren.js
│ │ ├── scrollIntoViewIfNeeded.js
│ │ ├── tests.html
│ │ └── toggleAttribute.js
├── HTMLElement
│ └── prototype
│ │ └── inert.js
├── HTMLFormElement
│ └── prototype
│ │ ├── reportValidity.js
│ │ └── requestSubmit.js
├── HTMLInputElement
│ └── prototype
│ │ ├── reportValidity.js
│ │ └── showPicker.js
├── HTMLSlotElement
│ └── prototype
│ │ └── assignedElements.js
├── Math
│ ├── sign.js
│ └── trunc.js
├── Node
│ └── prototype
│ │ ├── contains.js
│ │ ├── insertAfter.js
│ │ ├── isConnected.js
│ │ └── tests
│ │ └── contains.html
├── Number
│ └── isNumber.js
├── Object
│ ├── assign.js
│ ├── entries.js
│ ├── fromEntries.js
│ ├── hasOwn.js
│ ├── is.js
│ └── values.js
├── Promise
│ ├── allSettled.js
│ ├── any.js
│ └── withResolvers.js
├── RegExp
│ └── prototype
│ │ └── flags.js
├── SVGStyleElement
│ ├── combo.js
│ └── prototype
│ │ └── sheet.js
├── String
│ ├── fromCodePoint.js
│ └── prototype
│ │ ├── at.js
│ │ ├── codePointAt.js
│ │ ├── endsWith.js
│ │ ├── includes.js
│ │ ├── padEnd.js
│ │ ├── padStart.js
│ │ ├── repeat.js
│ │ ├── replaceAll.js
│ │ └── startsWith.js
├── SubmitEvent
│ └── prototype
│ │ ├── submitter.js
│ │ └── test.html
├── WeakRef.js
├── WeakSet.js
├── cancelIdleCallback.js
├── crypto
│ ├── randomUUID.js
│ └── randomUUID.original.js
├── document
│ ├── caretRangeFromPoint.js
│ └── currentScript.js
├── navigator
│ ├── share.js
│ └── share.test.html
├── requestIdleCallback.js
└── tests
│ ├── WeakRef.html
│ └── structuredClone.html
└── test.html
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Tobias Buschor
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 💊 lazyfill
2 |
3 | Polyfill Service - the lazy way
4 |
5 |
6 | Polyfills **are loaded on demand**, only when they are needed 😲
7 | Initial **3Kb** to polyfill a lot of Stuff!
8 |
9 | # Ussage
10 |
11 | Add this script on the top of your page:
12 | ```html
13 |
14 | ```
15 | **done!**
16 |
17 | # Polyfills
18 |
19 | (Anything missing? Any suggestions?)
20 |
21 |
22 |
23 |
24 | - Window
25 |
26 | - cookieStore
27 |
- fetch
28 |
- Promise
29 |
- IntersectionObserver
30 |
- ResizeObserver
31 |
- AbortController
32 |
- URLSearchParams
33 |
- Temporal
34 |
- temporal
35 |
- customElements
36 |
- structuredClone
37 |
- URLPattern
38 |
- ReadableStream
39 |
- Sanitizer
40 |
- requestIdleCallback
41 |
- cancelIdleCallback
42 |
- WeakSet
43 |
44 | - Element
45 |
46 | - setHTML
47 |
- matches
48 |
- closest
49 |
- prepend
50 |
- append
51 |
- before
52 |
- after
53 |
- replaceWidth
54 |
- remove
55 |
- blur
56 |
- focus
57 |
- classList
58 |
- getElementsByClassName
59 |
- children
60 |
- toggleAttribute
61 |
- isVisible
62 |
- scrollIntoViewIfNeeded
63 |
64 | - TypedArray
65 |
66 | - toReversed
67 |
- toSorted
68 |
- with
69 |
70 | - Array
71 |
72 | - toReversed
73 |
- toSorted
74 |
- with
75 |
- toSpliced
76 |
- from
77 |
- of
78 |
- at
79 |
- copyWithin
80 |
- entries
81 |
- fill
82 |
- find
83 |
- findIndex
84 |
- findLast
85 |
- findLastIndex
86 |
- flat
87 |
- flatMap
88 |
- includes
89 |
- keys
90 |
- values
91 |
92 | - Intl.DateTimeFormat
93 |
96 |
- Intl
97 |
98 | - DisplayNames
99 |
- ListFormat
100 |
- Locale
101 |
- PluralRules
102 |
- RelativeTimeFormat
103 |
- getCanonicalLocales
104 |
105 | - CSS
106 |
107 | - escape
108 |
- registerProperty
109 |
- supports
110 |
111 | - HTMLDocument
112 |
113 | - currentScript
114 |
- caretRangeFromPoint
115 |
116 | - Node
117 |
118 | - contains
119 |
- isConnected
120 |
121 | - HTMLElement
122 |
125 |
- HTMLFormElement
126 |
127 | - reportValidity
128 |
- requestSubmit
129 |
130 | - HTMLInputElement
131 |
132 | - reportValidity
133 |
134 | - HTMLSlotElement
135 |
136 | - assignedElements
137 |
138 | - Math
139 |
140 | - trunc
141 |
- sign
142 |
143 | - Navigator
144 |
147 |
- Number
148 |
151 |
- Object
152 |
153 | - assign
154 |
- entries
155 |
- fromEntries
156 |
- is
157 |
- values
158 |
- hasOwn
159 |
160 | - Promise
161 |
162 | - allSettled
163 |
- any
164 |
- withResolvers
165 |
166 | - RegExp
167 |
170 |
- String
171 |
172 | - fromCodePoint
173 |
- at
174 |
- codePointAt
175 |
- endsWith
176 |
- includes
177 |
- padEnd
178 |
- padStart
179 |
- repeat
180 |
- startsWith
181 |
- replaceAll
182 |
183 | - SubmitEvent
184 |
187 |
- SVGStyleElement
188 |
191 |
- Crypto
192 |
195 |
196 |
197 |
198 | - addEventListener signal options
199 |
- focus options
200 |
- classList force toggle
201 |
- Element.contains(TextNode) bug
202 |
203 |
204 |
205 | # How it works
206 |
207 | To every polyfillable property, the scripts adds a getter which **synchronously** loads the corresponding polyfill.
208 | Of course, we all know that blocking xhr-requests is not nice.
209 | Therefore, the url to the script that should be added to the page is given in the console.
210 | Ideal for prototyping.
211 |
212 | Let's assume that your browser does not support the function "String.prototype.at".
213 | ```js
214 | > ['a','b','c'].at(-1); // accessing [].at immediately loads the polyfill
215 | > 'c'
216 | ```
217 |
218 |
219 | # Help
220 | Any help is greatly appreciated.
221 |
222 | # Thanks / Resources
223 |
224 | https://github.com/es-shims
225 |
226 | https://github.com/behnammodi/polyfill
227 |
228 | https://polyfill.io/v3/
229 |
230 | https://ungap.github.io/
231 |
232 | https://github.com/Sylvain59650/all-polyfills
233 |
234 | https://vanillajstoolkit.com/polyfills/
235 |
--------------------------------------------------------------------------------
/htmlfills.js:
--------------------------------------------------------------------------------
1 | import {SelectorObserver} from 'https://cdn.jsdelivr.net/gh/u1ui/SelectorObserver.js@4.0.0/SelectorObserver.min.js'
2 |
3 | const scripts = {};
4 |
5 | const polyfills = {
6 | dialog: {
7 | supports: 'HTMLDialogElement' in window,
8 | js: 'https://cdn.jsdelivr.net/gh/nuxodin/dialog-polyfill@1.4.1/dialog.min.js',
9 | },
10 | "[focusgroup]": { // waiting for but to fix: https://github.com/MicrosoftEdge/MSEdgeExplainers/pull/581
11 | supports: 'focusgroup' in document.head,
12 | js: 'https://cdn.jsdelivr.net/gh/MicrosoftEdge/MSEdgeExplainers/Focusgroup/focusgroup_polyfill.js',
13 | },
14 | "[inert]": {
15 | supports: Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'inert')?.enumerable === true, // hacky test, mod.js adds inert property support
16 | js: 'https://cdn.jsdelivr.net/npm/wicg-inert@3.1.2/dist/inert.min.js',
17 | //js: 'https://unpkg.com/wicg-inert@3.1.2/dist/inert.min.js',
18 | },
19 | "search": {
20 | supports: window.HTMLSearchElement,
21 | js: (el)=> el.setAttribute('role', 'search'),
22 | },
23 | }
24 |
25 | Object.keys(polyfills).forEach(selector => {
26 | const data = polyfills[selector];
27 | if (data.supports) return;
28 | const obs = new SelectorObserver({
29 | on: (el) => {
30 | if (data.js instanceof Function) {
31 | data.js(el);
32 | }
33 | else {
34 | onScript(data.js, () => {
35 | console.log('💊 lazyfill: "'+selector+'" polyfilled, you need the polyfill: '+data.js);
36 | //data.onfound && data.onfound(el)
37 | });
38 | obs.disconnect();
39 | }
40 | },
41 | })
42 | obs.observe(selector);
43 | });
44 |
45 |
46 | function onScript(path, cb){
47 | if (!scripts[path]) {
48 | scripts[path] = {
49 | callbacks:[cb]
50 | };
51 | loadScript(path, function(){
52 | scripts[path].callbacks.forEach(cb);
53 | scripts[path].loaded = true;;
54 | });
55 | }
56 | if (scripts[path].loaded) cb();
57 | else scripts[path].callbacks.push(cb);
58 | }
59 | function loadScript(path, cb, eb) {
60 | const elem = document.createElement('script');
61 | elem.async = false;
62 | elem.src = path;
63 | elem.onload = cb;
64 | elem.onerror = eb;
65 | document.documentElement.firstChild.appendChild(elem);
66 | }
--------------------------------------------------------------------------------
/htmlfills.old.js:
--------------------------------------------------------------------------------
1 | !function (window, document) { 'use strict';
2 |
3 |
4 | /* onElement */
5 | var listeners = [],
6 | root = document,
7 | Observer;
8 |
9 | function qsa(el, selector) {
10 | try {
11 | return el.querySelectorAll(selector);
12 | } catch (e) {
13 | return [];
14 | }
15 | }
16 | function onElement(selector, callback) {
17 | const listener = {
18 | selector: selector,
19 | callback: callback,
20 | elements: new WeakMap(),
21 | };
22 | var els = qsa(root, listener.selector), i = 0, el;
23 | while (el = els[i++]) {
24 | listener.elements.set(el, true);
25 | listener.callback.call(el, el);
26 | }
27 | listeners.push(listener);
28 | if (!Observer) {
29 | Observer = new MutationObserver(checkMutations);
30 | Observer.observe(root, {
31 | childList: true,
32 | subtree: true
33 | });
34 | }
35 | checkListener(listener);
36 | }
37 | function checkListener(listener, target) {
38 | var i = 0, el, els = [];
39 | try {
40 | target && target.matches(listener.selector) && els.push(target);
41 | } catch (e) { }
42 | if (loaded) { // ok? check inside node on innerHTML - only when loaded
43 | Array.prototype.push.apply(els, qsa(target || root, listener.selector));
44 | }
45 | while (el = els[i++]) {
46 | if (listener.elements.has(el)) continue;
47 | listener.elements.set(el, true);
48 | listener.callback.call(el, el);
49 | }
50 | }
51 | function checkListeners(inside) {
52 | var i = 0, listener;
53 | while (listener = listeners[i++]) checkListener(listener, inside);
54 | }
55 | function checkMutations(mutations) {
56 | var j = 0, i, mutation, nodes, target;
57 | while (mutation = mutations[j++]) {
58 | nodes = mutation.addedNodes, i = 0;
59 | while (target = nodes[i++]) target.nodeType === 1 && checkListeners(target);
60 | }
61 | }
62 | let loaded = false;
63 | document.addEventListener('DOMContentLoaded', function () {
64 | loaded = true;
65 | });
66 | /* /onElement */
67 |
68 |
69 | const polyfills = {
70 | dialog: {
71 | supports: 'HTMLDialogElement' in window,
72 | js: 'https://cdn.jsdelivr.net/gh/nuxodin/dialog-polyfill@1.4.1/dist/dialog-polyfill.min.js',
73 | //js: 'https://cdn.jsdelivr.net/npm/dialog-polyfill@0.5.6/dist/dialog-polyfill.min.js',
74 | //css: 'https://cdn.jsdelivr.net/npm/dialog-polyfill@0.5.6/dialog-polyfill.css',
75 | //onfound: function(el){
76 | // dialogPolyfill.registerDialog(el);
77 | //}
78 | },
79 | "[focusgroup]": { // waiting for but to fix: https://github.com/MicrosoftEdge/MSEdgeExplainers/pull/581
80 | supports: 'focusgroup' in document.head,
81 | js: 'https://cdn.jsdelivr.net/gh/MicrosoftEdge/MSEdgeExplainers/Focusgroup/focusgroup_polyfill.js',
82 | },
83 | "[inert]": {
84 | supports: Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'inert')?.enumerable === true, // hacky test, mod.js adds inert property support
85 | js: 'https://cdn.jsdelivr.net/npm/wicg-inert@3.1.2/dist/inert.min.js',
86 | },
87 | }
88 |
89 | Object.keys(polyfills).forEach(function(selector){
90 | const data = polyfills[selector];
91 | if (data.supports) return;
92 | console.log(selector, data.supports)
93 | onElement(selector, function (el) {
94 | onScript(data.js, function(){
95 | data.onfound && data.onfound(el)
96 | });
97 | });
98 | });
99 |
100 |
101 | const scripts = {};
102 | function onScript(path, cb){
103 | if (!scripts[path]) {
104 | scripts[path] = {
105 | callbacks:[cb]
106 | };
107 | loadScript(path, function(){
108 | scripts[path].callbacks.forEach(cb);
109 | scripts[path].loaded = true;;
110 | })
111 | }
112 | if (scripts[path].loaded) cb();
113 | else scripts[path].callbacks.push(cb);
114 | }
115 | function loadScript(path, cb, eb) {
116 | const elem = document.createElement('script');
117 | elem.async = false;
118 | elem.src = path;
119 | elem.onload = cb;
120 | elem.onerror = eb;
121 | document.documentElement.firstChild.appendChild(elem);
122 | }
123 |
124 |
125 |
126 | }(window, document);
--------------------------------------------------------------------------------
/mod.js:
--------------------------------------------------------------------------------
1 | !function(window, document){ 'use strict';
2 | // other libaries should check properties like so: if (prop in obj) { ... }; so the getter will not fire
3 |
4 | var root = 'cdn.jsdelivr.net/gh/nuxodin/lazyfill@1.7.14/';
5 | var ending = '.min.js';
6 |
7 | //var root = 'localhost/github/lazyfill/'; var ending = '.js';
8 |
9 | /* very small polyfills, they are not worth adding to the service */
10 | if (!NodeList.prototype.forEach) NodeList.prototype.forEach = Array.prototype.forEach; // ie11
11 | if (!document.scrollingElement) document.scrollingElement = document.documentElement; // ie11
12 | if (!window.crypto) window.crypto = window.msCrypto; // ie11
13 | if (!window.SubmitEvent) window.SubmitEvent = Event; // safari v?
14 |
15 | var urls = {
16 | 'cdn.jsdelivr.net/npm/cookie-store@3.0.0/index.min.js': {
17 | 'cookieStore': [window],
18 | },
19 | 'cdn.jsdelivr.net/npm/whatwg-fetch@3.6.2/dist/fetch.umd.min.js':{
20 | 'fetch':[window],
21 | //'Headers':[window], 'Request':[window], 'Response':[window],
22 | },
23 | 'cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js':{
24 | 'Promise':[window]
25 | },
26 | 'polyfill.io/v3/polyfill.min.js?features=IntersectionObserver':{
27 | 'IntersectionObserver':[window]
28 | },
29 | 'cdn.jsdelivr.net/npm/@juggle/resize-observer@3.3.1/lib/exports/resize-observer.umd.js':{ // dit not work: 'polyfill.io/v3/polyfill.min.js?features=ResizeObserver'
30 | 'ResizeObserver':[window]
31 | },
32 | 'polyfill.io/v3/polyfill.min.js?features=AbortController':{
33 | 'AbortController':[window],
34 | //'AbortSignal': [window]
35 | },
36 | 'polyfill.io/v3/polyfill.min.js?features=URL':{
37 | //'URL':[window], // ie11: this will not work as it has "URL" but not as a constructor, what should we do?
38 | 'URLSearchParams':[window]
39 | },
40 | /* not ready yet, exposes window.temportal.Temporal */
41 | 'cdn.jsdelivr.net/npm/@js-temporal/polyfill@0.4.0/dist/index.umd.min.js':{
42 | Temporal:[window],
43 | temporal:[window],
44 | },
45 | 'unpkg.com/@ungap/custom-elements@0.1.15/es.js':{
46 | 'customElements':[window],
47 | },
48 | // 'cdn.jsdelivr.net/gh/nuxodin/structured-clone@2.4.0/index.min.js':{ // makes problems in safari
49 | // 'structuredClone':[window],
50 | // },
51 | 'cdn.jsdelivr.net/npm/urlpattern-polyfill@1.0.0-rc5/dist/index.umd.js':{
52 | 'URLPattern':[window],
53 | },
54 | 'unpkg.com/web-streams-polyfill@3.2.1/dist/polyfill.min.js':{
55 | 'ReadableStream':[window],
56 | },
57 | //'raw.githubusercontent.com/mozilla/sanitizer-polyfill/main/dist/sanitizer-polyfill.min.js':{
58 | 'mozilla.github.io/sanitizer-polyfill/dist/sanitizer-polyfill.min.js':{
59 | 'Sanitizer':[window],
60 | 'setHTML':[Element.prototype],
61 | },
62 | };
63 |
64 |
65 | var path = 'cdn.jsdelivr.net/gh/tc39/proposal-change-array-by-copy@main/polyfill.min.js';
66 | addCombo(path, {
67 | toReversed:1,
68 | toSorted:1,
69 | with:1,
70 | }, Object.getPrototypeOf(Int8Array.prototype));
71 | addCombo(path, {
72 | toReversed:1,
73 | toSorted:1,
74 | with:1,
75 | toSpliced:1,
76 | }, Array.prototype);
77 |
78 | addCombo('polyfill.io/v3/polyfill.min.js?features=Intl', {
79 | DateTimeFormat:{
80 | prototype:{
81 | formatToParts:1
82 | }
83 | },
84 | DisplayNames:1,
85 | ListFormat:1,
86 | Locale:1,
87 | PluralRules:1,
88 | RelativeTimeFormat:1,
89 | getCanonicalLocales:1,
90 | }, Intl);
91 |
92 | addCombo(root+'polyfills/Element/combo'+ending, {
93 | matches:1,
94 | closest:1,
95 | prepend:1,
96 | append:1,
97 | before:1,
98 | after:1,
99 | replaceWidth:1,
100 | remove:1,
101 | blur:1, // to use in SVGElement:
102 | focus:1,
103 | classList:1,
104 | getElementsByClassName:1,
105 | children:1,
106 | }, Element.prototype);
107 |
108 |
109 | /* set methods, stage 2
110 | addCombo('cdn.jsdelivr.net/npm/set-extensions@1.5.0/dist/index'+ending, {
111 | intersection:1,
112 | union:1,
113 | difference:1,
114 | symmetricDifference:1,
115 | isSubsetOf:1,
116 | isDisjointFrom:1,
117 | isSupersetOf:1,
118 | }, Set.prototype);
119 | */
120 |
121 | /* iterator helpers, stage 2
122 | var getPrototypeOf = Object.getPrototypeOf;
123 | var AsyncIteratorPrototype = getPrototypeOf(getPrototypeOf(getPrototypeOf((async function* () {})()[Symbol.asyncIterator]())));
124 | var IteratorPrototype = getPrototypeOf(getPrototypeOf([][Symbol.iterator]()));
125 | var props = {
126 | map:1,
127 | chain:1,
128 | count:1,
129 | cycle:1,
130 | drop:1,
131 | dropWhile:1,
132 | every:1,
133 | filter:1,
134 | find:1,
135 | findIndex:1,
136 | flatMap:1,
137 | forEach:1,
138 | fuse:1,
139 | join:1,
140 | map:1,
141 | max:1,
142 | min:1,
143 | partition:1,
144 | reduce:1,
145 | some:1,
146 | take:1,
147 | takeWhile:1,
148 | toArray:1,
149 | zip:1,
150 | }
151 | console.log(IteratorPrototype)
152 | path = 'cdn.jsdelivr.net/npm/iterator-polyfill@1.0.9/dist/index.min.js';
153 | addCombo(path, props, IteratorPrototype);
154 | addCombo(path, props, AsyncIteratorPrototype);
155 | */
156 |
157 |
158 | /* blank object "CSS" needed */
159 | if (!window.CSS) window.CSS = {};
160 | var lazyfills = {
161 | Array:{
162 | from:1,
163 | of:1,
164 | prototype:{
165 | at:1,
166 | copyWithin:1,
167 | entries:1,
168 | fill:1,
169 | find:1,
170 | findIndex:1,
171 | findLast:1,
172 | findLastIndex:1,
173 | flat:1,
174 | flatMap:1,
175 | includes:1,
176 | keys:1,
177 | values:1,
178 | }
179 | },
180 | CSS:{
181 | escape:1,
182 | registerProperty:1,
183 | supports:1,
184 | },
185 | document:{
186 | currentScript:1,
187 | caretRangeFromPoint:1,
188 | },
189 | Node:{
190 | prototype:{
191 | contains:1,
192 | isConnected:1,
193 | //inserAfter:1, draft
194 | },
195 | },
196 | Element:{
197 | prototype:{
198 | toggleAttribute:1,
199 | isVisible:1,
200 | scrollIntoViewIfNeeded:1,
201 | replaceChildren:1,
202 | }
203 | },
204 | HTMLElement:{
205 | prototype:{
206 | inert:1
207 | }
208 | },
209 | HTMLFormElement:{
210 | prototype:{
211 | reportValidity:1,
212 | requestSubmit:1,
213 | }
214 | },
215 | HTMLInputElement:{
216 | prototype:{
217 | reportValidity:1
218 | }
219 | },
220 | HTMLSlotElement:{
221 | prototype:{
222 | assignedElements:1
223 | }
224 | },
225 | Math:{
226 | trunc:1,
227 | sign:1,
228 | },
229 | navigator:{
230 | share:1
231 | },
232 | Number:{
233 | isInteger:1
234 | },
235 | Object:{
236 | assign:1,
237 | entries:1,
238 | fromEntries:1,
239 | is:1,
240 | values:1,
241 | hasOwn:1,
242 | },
243 | Promise:{
244 | allSettled:1,
245 | any:1,
246 | withResolvers:1,
247 | },
248 | RegExp:{
249 | prototype:{
250 | flags:1,
251 | }
252 | },
253 | String:{
254 | fromCodePoint:1,
255 | prototype:{
256 | at:1,
257 | codePointAt:1,
258 | endsWith:1,
259 | includes:1,
260 | padEnd:1,
261 | padStart:1,
262 | repeat:1,
263 | startsWith:1,
264 | replaceAll:1,
265 | }
266 | },
267 | SubmitEvent:{
268 | prototype:{
269 | submitter:1
270 | }
271 | },
272 | SVGStyleElement:{
273 | prototype:{
274 | sheet:1
275 | }
276 | },
277 | requestIdleCallback:1,
278 | cancelIdleCallback:1,
279 | WeakSet:1,
280 | crypto:{
281 | randomUUID:1,
282 | },
283 | };
284 | function addFsStruct(obj, realObj, rootUrl){
285 | var prop;
286 | for (prop in obj) {
287 | if (obj[prop] === 1) {
288 | var url = rootUrl + prop + ending
289 | if (!urls[url]) urls[url] = {};
290 | if (!urls[url][prop]) urls[url][prop] = [];
291 | urls[url][prop].push(realObj);
292 | } else {
293 | if (realObj[prop]===undefined) {
294 | console.warn('💊 lazyfill: Object '+prop+' not defined to polyfill its properties!');
295 | } else {
296 | addFsStruct(obj[prop], realObj[prop], rootUrl + prop + '/');
297 | }
298 |
299 | }
300 | }
301 | }
302 | addFsStruct(lazyfills, window, root+'polyfills/');
303 |
304 |
305 | for (let url in urls) addGetters(url, urls[url]);
306 |
307 | /* To list polyfills in the readme: *
308 | //IteratorPrototype.name = 'Iterator';
309 | //AsyncIteratorPrototype.name = 'AsyncIterator';
310 | CSS.name = 'CSS';
311 | let supports = {};
312 | Object.values(urls).forEach(function(props){
313 | Object.entries(props).forEach(([prop, objects])=>{
314 | objects.forEach(obj=>{
315 | let name = obj[Symbol.toStringTag] || obj.name || obj.constructor.name
316 | if (!supports[name]) supports[name] = [];
317 | supports[name].push(prop)
318 | })
319 | })
320 | });
321 | let output = '\n';
322 | Object.entries(supports).map(([obj, props])=>{
323 | output += '\n - '+obj
324 | output += '\n
'+props.map(prop => `\n - ${prop}`).join('')+'\n
';
325 | })
326 | output += '\n
'
327 | console.log(output)
328 | /* */
329 |
330 | console.log('💊 lazyfill: getters added, ready!');
331 |
332 | function addCombo(url, obj, target) {
333 | var prop;
334 | if (!urls[url]) urls[url] = {};
335 | for (prop in obj) {
336 | if (obj[prop] === 1) {
337 | if (!urls[url][prop]) urls[url][prop] = [];
338 | urls[url][prop].push(target);
339 | } else {
340 | addCombo(url, obj[prop], target[prop]);
341 | }
342 | }
343 | }
344 |
345 | function addGetters(url, props) {
346 | var prop, i, targets, target, propsNeeded = {};
347 | for (prop in props) {
348 | targets = props[prop];
349 | for (i=0; target=targets[i++] ;) {
350 | if (prop in target) continue; // not needed
351 | if (!propsNeeded[prop]) propsNeeded[prop] = [];
352 | propsNeeded[prop].push(target);
353 | //console.log('"'+prop+'" not supported, adding getter');
354 | addGetter(target, prop, url);
355 | }
356 | }
357 | function addGetter(obj, prop, url) {
358 | Object.defineProperty(obj, prop, {
359 | configurable: true,
360 | get: function() {
361 | // try { throw new Error(); } catch (e) { console.log(e.stack) } // track where it has been added
362 | deleteGetters(); // we have to delete all assigned getters for a url, otherwise the script is parsed anew with every polyfill!
363 | console.log('💊 lazyfill: "'+prop+'" polyfilled (sync!), you need the polyfill '+url);
364 |
365 | // umd
366 | window.exports = {};
367 | window.module = true; // todo: needed by umd but i dont know why?
368 | loadScriptSync('https://'+url);
369 | // if (!this[prop]) this[prop] = exports[prop]; // todo: loop exports?
370 | // new: polyfill the prototype, not the instance, ok?
371 | if (!obj[prop]) obj[prop] = exports[prop]; // todo: loop exports?
372 | return this[prop];
373 | },
374 | set: function(v) {
375 | //deleteGetters();
376 | delete obj[prop]; // needed? the getter has already deleted the property!??
377 | obj[prop] = v;
378 | }
379 | });
380 | }
381 | function deleteGetters() {
382 | var prop, targets, target;
383 | for (prop in propsNeeded) {
384 | targets = props[prop];
385 | for (i=0; target=targets[i++];) {
386 | delete target[prop];
387 | }
388 | }
389 | }
390 | };
391 |
392 |
393 | /* Monkey Patches */
394 | var monkeyPatches = {
395 | focusOptions:1,
396 | elContainsText:1,
397 | forceToggle:1,
398 | addEventListenerSignal:1,
399 | };
400 | var dummyEl = document.createElement('i');
401 | // focus options
402 | dummyEl.focus({
403 | get preventScroll() {
404 | delete monkeyPatches.focusOptions;
405 | },
406 | });
407 | // IE11 contains-bug, textNodes are not containing
408 | dummyEl.innerHTML = ' ';
409 | if (dummyEl.contains(dummyEl.firstChild)) delete monkeyPatches.elContainsText;
410 |
411 | // classList.toggle force options
412 | var cl = dummyEl.classList;
413 | cl.toggle('test',false);
414 | if (!cl.contains('test')) delete monkeyPatches.forceToggle
415 |
416 | // addEventListener signal option
417 | dummyEl.addEventListener('click',()=>{}, {
418 | get signal() {
419 | delete monkeyPatches.addEventListenerSignal;
420 | },
421 | });
422 |
423 | // load patches
424 | for (let patch in monkeyPatches) {
425 | console.log(patch)
426 | loadScriptAsync('https://'+root + 'monkeyPatches/' + patch + ending, true);
427 | }
428 |
429 |
430 |
431 | /* helpers */
432 | function loadScriptSync(path) {
433 | var xhr = new XMLHttpRequest();
434 | xhr.open('GET', path, false);
435 | xhr.send(null);
436 | if (xhr.status === 200) {
437 | var elem = document.createElement('script');
438 | elem.text = xhr.responseText;
439 | document.documentElement.firstChild.appendChild(elem);
440 | elem.setAttribute('data-src',path);
441 | } else {
442 | console.warn('💊 lazyfill: load failed '+path)
443 | }
444 | }
445 | function loadScriptAsync(path) {
446 | var elem = document.createElement('script');
447 | elem.async = false;
448 | elem.src = path;
449 | //elem.setAttribute('src',path);
450 | document.documentElement.firstChild.appendChild(elem);
451 | }
452 |
453 |
454 | /* more *
455 | // iterators, available on ch/ff, not useable for ie11
456 | if (window.Symbol && Symbol.iterator) {
457 | [HTMLCollection,NodeList,StyleSheetList,window.CSSRuleList].forEach(function(Interface){
458 | if (!Interface) return;
459 | var proto = Interface.prototype;
460 | if (proto[Symbol.iterator]) return;
461 | proto[Symbol.iterator] = Array.prototype[Symbol.iterator];
462 | });
463 | }
464 | /* */
465 |
466 |
467 | }(window, document);
468 |
--------------------------------------------------------------------------------
/monkeyPatches/addEventListenerSignal.js:
--------------------------------------------------------------------------------
1 | // idea from https://gist.github.com/samthor/2e11de5976fe673557b0ee14a3cb621a#file-eventlistener-signal-support-js
2 |
3 | !function(){
4 |
5 | let supported = false;
6 | document.createElement('i').addEventListener('click',()=>{}, {
7 | get signal() { supported = true; },
8 | });
9 | if (supported) return;
10 | if (!window.AbortController) throw new Error(`AbortController not supported`);
11 |
12 | const orig = EventTarget.prototype.addEventListener;
13 |
14 | EventTarget.prototype.addEventListener = function (eventName, fn, options) {
15 | if (options && options.signal) {
16 | if (options.signal.aborted) return; // do nothing, already aborted
17 | options.signal.addEventListener('abort', () => this.removeEventListener(eventName, fn, { ...options }) );
18 | }
19 | return orig.call(this, eventName, fn, options);
20 | };
21 |
22 | }();
23 |
--------------------------------------------------------------------------------
/monkeyPatches/addEventListenerSignal.test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
19 |
20 |
--------------------------------------------------------------------------------
/monkeyPatches/elContainsText.js:
--------------------------------------------------------------------------------
1 | /* IE11 contains-bug, textNodes are not containing */
2 | !function(d){
3 | var t = d.createTextNode(''), el = d.createElement('span');
4 | el.appendChild(t);
5 | if (!el.contains(t)) {
6 | HTMLElement.prototype.contains = function(contains) {
7 | return function(el) {
8 | return contains.call(this, !el || el.nodeType === 1 ? el : el.parentNode);
9 | };
10 | }(HTMLElement.prototype.contains);
11 | }
12 | }(document);
13 |
--------------------------------------------------------------------------------
/monkeyPatches/focusOptions.js:
--------------------------------------------------------------------------------
1 |
2 | !function(){
3 |
4 | let supported = false;
5 | document.createElement('i').focus({
6 | get preventScroll() {
7 | supported = true;
8 | },
9 | });
10 |
11 | if (!supported) {
12 | let original = HTMLElement.prototype.focus;
13 | Element.prototype.focus = HTMLElement.prototype.focus = function(options){
14 | if (options && options.preventScroll) {
15 | const map = new Map();
16 | let p = this;
17 | while (p = p.parentNode) map.set(p, [p.scrollLeft, p.scrollTop]);
18 | original.apply(this, arguments);
19 | map.forEach(function(pos, el){
20 | // todo: test: only if changed? does it trigger scroll?
21 | // IE flickers
22 | el.scrollLeft = pos[0]
23 | el.scrollTop = pos[1]
24 | });
25 | } else {
26 | original.apply(this, arguments);
27 | }
28 | }
29 | }
30 |
31 |
32 | }();
33 |
--------------------------------------------------------------------------------
/monkeyPatches/forceToggle.js:
--------------------------------------------------------------------------------
1 | // classList.toggle(x, force!) ie11
2 | !function(){
3 | var cl = document.createElement('div').classList;
4 | cl.toggle('test',false);
5 | if (!cl.contains('test')) return;
6 | var original = DOMTokenList.prototype.toggle;
7 | DOMTokenList.prototype.toggle = function(name, force){
8 | if (force!==undefined) {
9 | this[force?'add':'remove'](name);
10 | return force;
11 | }
12 | return original.call(this, name);
13 | }
14 | }();
15 |
--------------------------------------------------------------------------------
/monkeyPatches/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Level.css TEST
6 |
7 |
8 |
9 |
10 |
11 | Element contains text-nodes
12 |
22 |
23 |
24 | ClassList force toggle
25 |
36 |
37 |
38 | focus options preventScroll
39 | IE 11 and Safari 14+?
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | scrollable div
167 |
168 |
169 |
170 |
171 |
172 |
173 | scrollable div
174 |
175 |
176 |
--------------------------------------------------------------------------------
/polyfills/Array/from.js:
--------------------------------------------------------------------------------
1 | if (!Array.from) {
2 | Array.from = (function () {
3 | var toStr = Object.prototype.toString;
4 | var isCallable = function (fn) {
5 | return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
6 | };
7 | var toInteger = function (value) {
8 | var number = Number(value);
9 | if (isNaN(number)) {
10 | return 0;
11 | }
12 | if (number === 0 || !isFinite(number)) {
13 | return number;
14 | }
15 | return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
16 | };
17 | var maxSafeInteger = Math.pow(2, 53) - 1;
18 | var toLength = function (value) {
19 | var len = toInteger(value);
20 | return Math.min(Math.max(len, 0), maxSafeInteger);
21 | };
22 |
23 | // The length property of the from method is 1.
24 | return function from(arrayLike /*, mapFn, thisArg */) {
25 | // 1. Let C be the this value.
26 | var C = this;
27 |
28 | // 2. Let items be ToObject(arrayLike).
29 | var items = Object(arrayLike);
30 |
31 | // 3. ReturnIfAbrupt(items).
32 | if (arrayLike == null) {
33 | throw new TypeError(
34 | 'Array.from requires an array-like object - not null or undefined'
35 | );
36 | }
37 |
38 | // 4. If mapfn is undefined, then let mapping be false.
39 | var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
40 | var T;
41 | if (typeof mapFn !== 'undefined') {
42 | // 5. else
43 | // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
44 | if (!isCallable(mapFn)) {
45 | throw new TypeError(
46 | 'Array.from: when provided, the second argument must be a function'
47 | );
48 | }
49 |
50 | // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
51 | if (arguments.length > 2) {
52 | T = arguments[2];
53 | }
54 | }
55 |
56 | // 10. Let lenValue be Get(items, "length").
57 | // 11. Let len be ToLength(lenValue).
58 | var len = toLength(items.length);
59 |
60 | // 13. If IsConstructor(C) is true, then
61 | // 13. a. Let A be the result of calling the [[Construct]] internal method
62 | // of C with an argument list containing the single item len.
63 | // 14. a. Else, Let A be ArrayCreate(len).
64 | var A = isCallable(C) ? Object(new C(len)) : new Array(len);
65 |
66 | // 16. Let k be 0.
67 | var k = 0;
68 | // 17. Repeat, while k < len… (also steps a - h)
69 | var kValue;
70 | while (k < len) {
71 | kValue = items[k];
72 | if (mapFn) {
73 | A[k] =
74 | typeof T === 'undefined'
75 | ? mapFn(kValue, k)
76 | : mapFn.call(T, kValue, k);
77 | } else {
78 | A[k] = kValue;
79 | }
80 | k += 1;
81 | }
82 | // 18. Let putStatus be Put(A, "length", len, true).
83 | A.length = len;
84 | // 20. Return A.
85 | return A;
86 | };
87 | })();
88 | }
89 |
--------------------------------------------------------------------------------
/polyfills/Array/of.js:
--------------------------------------------------------------------------------
1 | if (!Array.of) {
2 | Array.of = function () {
3 | return Array.prototype.slice.call(arguments);
4 | };
5 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/at.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.at) {
2 | Array.prototype.at = function(n){
3 | //n = Math.trunc(n) || 0; not in ie11
4 | n = n < 0 ? Math.ceil(n) : Math.floor(n);
5 | if (n < 0) n += this.length;
6 | if (n < 0 || n >= this.length) return undefined;
7 | return this[n];
8 | }
9 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/copyWithin.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.copyWithin) {
2 | Object.defineProperty(Array.prototype, 'copyWithin', {
3 | configurable: true,
4 | writable: true,
5 | value: function (target, start /*, end*/) {
6 | // Steps 1-2.
7 | if (this == null) {
8 | throw new TypeError('this is null or not defined');
9 | }
10 |
11 | var O = Object(this);
12 |
13 | // Steps 3-5.
14 | var len = O.length >>> 0;
15 |
16 | // Steps 6-8.
17 | var relativeTarget = target >> 0;
18 |
19 | var to =
20 | relativeTarget < 0
21 | ? Math.max(len + relativeTarget, 0)
22 | : Math.min(relativeTarget, len);
23 |
24 | // Steps 9-11.
25 | var relativeStart = start >> 0;
26 |
27 | var from =
28 | relativeStart < 0
29 | ? Math.max(len + relativeStart, 0)
30 | : Math.min(relativeStart, len);
31 |
32 | // Steps 12-14.
33 | var end = arguments[2];
34 | var relativeEnd = end === undefined ? len : end >> 0;
35 |
36 | var final =
37 | relativeEnd < 0
38 | ? Math.max(len + relativeEnd, 0)
39 | : Math.min(relativeEnd, len);
40 |
41 | // Step 15.
42 | var count = Math.min(final - from, len - to);
43 |
44 | // Steps 16-17.
45 | var direction = 1;
46 |
47 | if (from < to && to < from + count) {
48 | direction = -1;
49 | from += count - 1;
50 | to += count - 1;
51 | }
52 |
53 | // Step 18.
54 | while (count > 0) {
55 | if (from in O) {
56 | O[to] = O[from];
57 | } else {
58 | delete O[to];
59 | }
60 |
61 | from += direction;
62 | to += direction;
63 | count--;
64 | }
65 |
66 | // Step 19.
67 | return O;
68 | },
69 | });
70 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/entries.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.entries) {
2 | Array.prototype.entries = function () {
3 | function Iterator() { }
4 |
5 | Iterator.prototype.next = function () {
6 | if (index > selfThis.length - 1) {
7 | done = true;
8 | }
9 | if (done) {
10 | return { value: undefined, done: true };
11 | }
12 | return { value: [index, selfThis[index++]], done: false };
13 | };
14 |
15 | var selfThis = this;
16 | var index = 0;
17 | var done;
18 |
19 | return new Iterator();
20 | };
21 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/fill.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.fill) {
2 | Object.defineProperty(Array.prototype, 'fill', {
3 | configurable: true,
4 | writable: true,
5 | value: function (value) {
6 | // Steps 1-2.
7 | if (this == null) {
8 | throw new TypeError('this is null or not defined');
9 | }
10 |
11 | var O = Object(this);
12 |
13 | // Steps 3-5.
14 | var len = O.length >>> 0;
15 |
16 | // Steps 6-7.
17 | var start = arguments[1];
18 | var relativeStart = start >> 0;
19 |
20 | // Step 8.
21 | var k =
22 | relativeStart < 0
23 | ? Math.max(len + relativeStart, 0)
24 | : Math.min(relativeStart, len);
25 |
26 | // Steps 9-10.
27 | var end = arguments[2];
28 | var relativeEnd = end === undefined ? len : end >> 0;
29 |
30 | // Step 11.
31 | var final =
32 | relativeEnd < 0
33 | ? Math.max(len + relativeEnd, 0)
34 | : Math.min(relativeEnd, len);
35 |
36 | // Step 12.
37 | while (k < final) {
38 | O[k] = value;
39 | k++;
40 | }
41 |
42 | // Step 13.
43 | return O;
44 | },
45 | });
46 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/find.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.find) {
2 | Object.defineProperty(Array.prototype, 'find', {
3 | configurable: true,
4 | writable: true,
5 | value: function (predicate) {
6 | // 1. Let O be ? ToObject(this value).
7 | if (this == null) {
8 | throw new TypeError('"this" is null or not defined');
9 | }
10 |
11 | var o = Object(this);
12 |
13 | // 2. Let len be ? ToLength(? Get(O, "length")).
14 | var len = o.length >>> 0;
15 |
16 | // 3. If IsCallable(predicate) is false, throw a TypeError exception.
17 | if (typeof predicate !== 'function') {
18 | throw new TypeError('predicate must be a function');
19 | }
20 |
21 | // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
22 | var thisArg = arguments[1];
23 |
24 | // 5. Let k be 0.
25 | var k = 0;
26 |
27 | // 6. Repeat, while k < len
28 | while (k < len) {
29 | // a. Let Pk be ! ToString(k).
30 | // b. Let kValue be ? Get(O, Pk).
31 | // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
32 | // d. If testResult is true, return kValue.
33 | var kValue = o[k];
34 | if (predicate.call(thisArg, kValue, k, o)) {
35 | return kValue;
36 | }
37 | // e. Increase k by 1.
38 | k++;
39 | }
40 |
41 | // 7. Return undefined.
42 | return undefined;
43 | },
44 | });
45 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/findIndex.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.findIndex) {
2 | Object.defineProperty(Array.prototype, 'findIndex', {
3 | configurable: true,
4 | writable: true,
5 | value: function (predicate) {
6 | // 1. Let O be ? ToObject(this value).
7 | if (this == null) {
8 | throw new TypeError('"this" is null or not defined');
9 | }
10 |
11 | var o = Object(this);
12 |
13 | // 2. Let len be ? ToLength(? Get(O, "length")).
14 | var len = o.length >>> 0;
15 |
16 | // 3. If IsCallable(predicate) is false, throw a TypeError exception.
17 | if (typeof predicate !== 'function') {
18 | throw new TypeError('predicate must be a function');
19 | }
20 |
21 | // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
22 | var thisArg = arguments[1];
23 |
24 | // 5. Let k be 0.
25 | var k = 0;
26 |
27 | // 6. Repeat, while k < len
28 | while (k < len) {
29 | // a. Let Pk be ! ToString(k).
30 | // b. Let kValue be ? Get(O, Pk).
31 | // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
32 | // d. If testResult is true, return k.
33 | var kValue = o[k];
34 | if (predicate.call(thisArg, kValue, k, o)) {
35 | return k;
36 | }
37 | // e. Increase k by 1.
38 | k++;
39 | }
40 |
41 | // 7. Return -1.
42 | return -1;
43 | },
44 | });
45 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/findLast.js:
--------------------------------------------------------------------------------
1 | // https://raw.githubusercontent.com/behnammodi/polyfill/master/array.polyfill.js
2 |
3 | if (!Array.prototype.findLast) {
4 | Object.defineProperty(Array.prototype, "findLast", {
5 | value: function (predicate, thisArg) {
6 | let idx = this.length - 1;
7 | while (idx >= 0) {
8 | const value = this[idx];
9 | if (predicate.call(thisArg, value, idx, this)) {
10 | return value;
11 | }
12 | idx--;
13 | }
14 | return undefined;
15 | }
16 | ,
17 | writable: true,
18 | enumerable: false,
19 | configurable: true
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/polyfills/Array/prototype/findLastIndex.js:
--------------------------------------------------------------------------------
1 | // https://raw.githubusercontent.com/behnammodi/polyfill/master/array.polyfill.js
2 |
3 | if (!Array.prototype.findLastIndex) {
4 | Object.defineProperty(Array.prototype, 'findLastIndex', {
5 | value: function (predicate, thisArg) {
6 | let idx = this.length - 1;
7 | while (idx >= 0) {
8 | const value = this[idx];
9 | if (predicate.call(thisArg, value, idx, this)) {
10 | return idx;
11 | }
12 | idx--;
13 | }
14 | return -1;
15 | }
16 | ,
17 | writable: true,
18 | enumerable: false,
19 | configurable: true
20 | });
21 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/flat.js:
--------------------------------------------------------------------------------
1 | // from https://github.com/behnammodi/polyfill/blob/master/array.polyfill.js
2 | if (!Array.prototype.flat) {
3 | Object.defineProperty(Array.prototype, 'flat', {
4 | configurable: true,
5 | writable: true,
6 | value: function () {
7 | var depth =
8 | typeof arguments[0] === 'undefined' ? 1 : Number(arguments[0]) || 0;
9 | var result = [];
10 | var forEach = result.forEach;
11 |
12 | var flatDeep = function (arr, depth) {
13 | forEach.call(arr, function (val) {
14 | if (depth > 0 && Array.isArray(val)) {
15 | flatDeep(val, depth - 1);
16 | } else {
17 | result.push(val);
18 | }
19 | });
20 | };
21 |
22 | flatDeep(this, depth);
23 | return result;
24 | },
25 | });
26 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/flatMap.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.flatMap) {
2 | Object.defineProperty(Array.prototype, 'flatMap', {
3 | configurable: true,
4 | writable: true,
5 | value: function () {
6 | return Array.prototype.map.apply(this, arguments).flat(1);
7 | },
8 | });
9 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/includes.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.includes) {
2 | Object.defineProperty(Array.prototype, 'includes', {
3 | configurable: true,
4 | writable: true,
5 | value: function (searchElement, fromIndex) {
6 | // 1. Let O be ? ToObject(this value).
7 | if (this == null) {
8 | throw new TypeError('"this" is null or not defined');
9 | }
10 |
11 | var o = Object(this);
12 |
13 | // 2. Let len be ? ToLength(? Get(O, "length")).
14 | var len = o.length >>> 0;
15 |
16 | // 3. If len is 0, return false.
17 | if (len === 0) {
18 | return false;
19 | }
20 |
21 | // 4. Let n be ? ToInteger(fromIndex).
22 | // (If fromIndex is undefined, this step produces the value 0.)
23 | var n = fromIndex | 0;
24 |
25 | // 5. If n ≥ 0, then
26 | // a. Let k be n.
27 | // 6. Else n < 0,
28 | // a. Let k be len + n.
29 | // b. If k < 0, let k be 0.
30 | var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
31 |
32 | function sameValueZero(x, y) {
33 | return (
34 | x === y ||
35 | (typeof x === 'number' &&
36 | typeof y === 'number' &&
37 | isNaN(x) &&
38 | isNaN(y))
39 | );
40 | }
41 |
42 | // 7. Repeat, while k < len
43 | while (k < len) {
44 | // a. Let elementK be the result of ? Get(O, ! ToString(k)).
45 | // b. If SameValueZero(searchElement, elementK) is true, return true.
46 | // c. Increase k by 1.
47 | if (sameValueZero(o[k], searchElement)) {
48 | return true;
49 | }
50 | k++;
51 | }
52 |
53 | // 8. Return false
54 | return false;
55 | },
56 | });
57 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/item.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxodin/lazyfill/c53e43fe2d88269cf84b924461218c23422cc49a/polyfills/Array/prototype/item.js
--------------------------------------------------------------------------------
/polyfills/Array/prototype/keys.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.keys) {
2 | Array.prototype.keys = function () {
3 | function Iterator() { }
4 |
5 | Iterator.prototype.next = function () {
6 | if (index > selfThis.length - 1) {
7 | done = true;
8 | }
9 | if (done) {
10 | return { value: undefined, done: true };
11 | }
12 | return { value: index++, done: false };
13 | };
14 |
15 | var selfThis = this;
16 | var index = 0;
17 | var done;
18 |
19 | return new Iterator();
20 | };
21 | }
--------------------------------------------------------------------------------
/polyfills/Array/prototype/values.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.values) {
2 | Array.prototype.values = function () {
3 | function Iterator() { }
4 |
5 | Iterator.prototype.next = function () {
6 | if (index > selfThis.length - 1) {
7 | done = true;
8 | }
9 | if (done) {
10 | return { value: undefined, done: true };
11 | }
12 | return { value: selfThis[index++], done: false };
13 | };
14 |
15 | var selfThis = this;
16 | var index = 0;
17 | var done;
18 |
19 | return new Iterator();
20 | };
21 | }
--------------------------------------------------------------------------------
/polyfills/CSS/escape.js:
--------------------------------------------------------------------------------
1 | /*! https://mths.be/cssescape v1.5.1 by @mathias | MIT license */
2 | ;(function(root, factory) {
3 | // https://github.com/umdjs/umd/blob/master/returnExports.js
4 | if (typeof exports == 'object') {
5 | // For Node.js.
6 | module.exports = factory(root);
7 | } else if (typeof define == 'function' && define.amd) {
8 | // For AMD. Register as an anonymous module.
9 | define([], factory.bind(root, root));
10 | } else {
11 | // For browser globals (not exposing the function separately).
12 | factory(root);
13 | }
14 | }(typeof global != 'undefined' ? global : this, function(root) {
15 |
16 | if (root.CSS && root.CSS.escape) {
17 | return root.CSS.escape;
18 | }
19 |
20 | // https://drafts.csswg.org/cssom/#serialize-an-identifier
21 | var cssEscape = function(value) {
22 | if (arguments.length == 0) throw new TypeError('`CSS.escape` requires an argument.');
23 | var string = String(value);
24 | var length = string.length;
25 | var index = -1;
26 | var codeUnit;
27 | var result = '';
28 | var firstCodeUnit = string.charCodeAt(0);
29 | while (++index < length) {
30 | codeUnit = string.charCodeAt(index);
31 | // Note: there’s no need to special-case astral symbols, surrogate
32 | // pairs, or lone surrogates.
33 |
34 | // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER
35 | // (U+FFFD).
36 | if (codeUnit == 0x0000) {
37 | result += '\uFFFD';
38 | continue;
39 | }
40 |
41 | if (
42 | // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
43 | // U+007F, […]
44 | (codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
45 | // If the character is the first character and is in the range [0-9]
46 | // (U+0030 to U+0039), […]
47 | (index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
48 | // If the character is the second character and is in the range [0-9]
49 | // (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
50 | (
51 | index == 1 &&
52 | codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
53 | firstCodeUnit == 0x002D
54 | )
55 | ) {
56 | // https://drafts.csswg.org/cssom/#escape-a-character-as-code-point
57 | result += '\\' + codeUnit.toString(16) + ' ';
58 | continue;
59 | }
60 |
61 | if (
62 | // If the character is the first character and is a `-` (U+002D), and
63 | // there is no second character, […]
64 | index == 0 &&
65 | length == 1 &&
66 | codeUnit == 0x002D
67 | ) {
68 | result += '\\' + string.charAt(index);
69 | continue;
70 | }
71 |
72 | // If the character is not handled by one of the above rules and is
73 | // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or
74 | // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to
75 | // U+005A), or [a-z] (U+0061 to U+007A), […]
76 | if (
77 | codeUnit >= 0x0080 ||
78 | codeUnit == 0x002D ||
79 | codeUnit == 0x005F ||
80 | codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
81 | codeUnit >= 0x0041 && codeUnit <= 0x005A ||
82 | codeUnit >= 0x0061 && codeUnit <= 0x007A
83 | ) {
84 | // the character itself
85 | result += string.charAt(index);
86 | continue;
87 | }
88 |
89 | // Otherwise, the escaped character.
90 | // https://drafts.csswg.org/cssom/#escape-a-character
91 | result += '\\' + string.charAt(index);
92 |
93 | }
94 | return result;
95 | };
96 |
97 | if (!root.CSS) root.CSS = {};
98 |
99 | root.CSS.escape = cssEscape;
100 | return cssEscape;
101 |
102 | }));
--------------------------------------------------------------------------------
/polyfills/CSS/registerProperty.js:
--------------------------------------------------------------------------------
1 |
2 | if (!CSS.registerProperty) {
3 | const pool = new Set();
4 | CSS.registerProperty = function(def){
5 | if (pool.has(def.name)) throw new Error(`property ${def.name} already registered`);
6 | pool.add(def.name);
7 |
8 | if (def.syntax!=null && def.syntax !== '*') console.log('CSS.registerProperty: syntax not supported in your browser');
9 |
10 | let hasWhere = CSS.supports('selector(:where(x))');
11 | let where = selector => hasWhere?`:where(${selector})`:selector;
12 |
13 | let style = '';
14 | if (def.initialValue != null) {
15 | style += where('html')+` { ${def.name}:${def.initialValue}; }`;
16 | }
17 | if (!def.inherits) { // if not inherited and no initial value, it inherits anyway, but the native chrome behavoir is the same!
18 | style += where('*,::before,::after') + ` { ${def.name}:${def.initialValue??''}; }`;
19 | }
20 | document.head.insertAdjacentHTML('afterbegin', ``);
21 | }
22 | }
23 |
24 | /*
25 | note:
26 | definition.syntax is not supported
27 | */
28 |
29 | /* test:
30 |
38 |
39 |
47 |
48 |
49 | This article has the style color:var(--my-color) and --my-color is defined as red.
50 | For H2, the style color:var(--my-color) is applyed, but as --my-color does not inherit, it gets the initialValue (blue)
51 |
52 | */
53 |
--------------------------------------------------------------------------------
/polyfills/CSS/supports.js:
--------------------------------------------------------------------------------
1 | /*! CSS.supports() Polyfill
2 | * https://gist.github.com/codler/03a0995195aa2859465f
3 | * Copyright (c) 2014 Han Lin Yap http://yap.nu; MIT license */
4 |
5 | /*
6 | * This polyfill has 2 issues:
7 | * On presto-based opera browsers (12.1, op_mini) it just uses window.supportsCSS with whatever limitations this has (i couldnt find out).
8 | * when there is an earlier version of window.CSS.supports present, it will get used and the parentheses-less one-argument version will not work.
9 | * It maybe not be performant when used excessively, once requested values will get cached though (will increase memory usage if used excessively).
10 | */
11 | (function () {
12 | //reassignment for presto-based opera-browsers
13 | if ("supportsCSS" in window) {
14 | window.CSS = {};
15 | window.CSS.supports = window.supportsCSS;
16 | return;
17 | }
18 | // if window.CSS doesnt exist, add it
19 | if (!("CSS" in window)) window.CSS = {};
20 | // if window.CSS.supports doesnt exist, use polyfill
21 | if (!("supports" in window.CSS)) {
22 | var _cache = {};
23 | window.CSS.supports = function (propertyName, value) {
24 | var key = [propertyName, value].toString();
25 | if (key in _cache) return _cache[key];
26 |
27 | //recursive calls if there are multiple CSS Property Values
28 | function cssSupports(propertyName, value) {
29 | var style = document.createElement("div").style;
30 | //case 1: boolean supports(CSSOMString conditionText);
31 | if (typeof propertyName === "string" && !value) {
32 | var arrOr = mergeOdd(propertyName, /([)])\s*or\s*([(])/gi);
33 | if (arrOr)
34 | return arrOr.some(function (supportsCondition) {
35 | return window.CSS.supports(supportsCondition);
36 | });
37 | var arrAnd = mergeOdd(propertyName, /([)])\s*and\s*([(])/gi);
38 | if (arrAnd)
39 | return arrAnd.every(function (supportsCondition) {
40 | return window.CSS.supports(supportsCondition);
41 | });
42 | //remove the first and last parentheses
43 | style.cssText = propertyName.replace("(", "").replace(/[)]$/, "");
44 | //is invalid when it doesnt get parsed
45 | return !!style.length;
46 | }
47 | //case 2: boolean supports(CSSOMString property, CSSOMString value);
48 | else if (
49 | typeof propertyName === "string" &&
50 | typeof value === "string"
51 | ) {
52 | style.cssText = propertyName + ":" + value;
53 | return !!style.length;
54 | }
55 | //doesnt match either function signature
56 | else return false;
57 | }
58 |
59 | return (_cache[key] = cssSupports(propertyName, value));
60 | };
61 | }
62 |
63 | //split string with regex -> pair strings -> filter out falsy values
64 | function mergeOdd(propertyName, reg) {
65 | var arr = propertyName.split(reg);
66 | if (arr.length > 1)
67 | return arr
68 | .map(function (value, index, arr) {
69 | return index % 2 == 0 ? value + arr[index + 1] : "";
70 | })
71 | .filter(Boolean);
72 | }
73 | })();
--------------------------------------------------------------------------------
/polyfills/Element/aom.combo.js:
--------------------------------------------------------------------------------
1 | // aom (beta)
2 |
3 | // https://www.digitala11y.com/wai-aria-1-1-cheat-sheet/
4 | // https://github.com/A11yance/aria-query
5 | // https://github.com/xi/aria-api
6 |
7 |
8 | // role reflection
9 | // https://wicg.github.io/aom/spec/aria-reflection.html#role-reflection
10 | if (!('role' in Element.prototype)) {
11 | Object.defineProperty(Element.prototype, 'role', {
12 | get: function() {
13 | return this.getAttribute('role');
14 | },
15 | set: function(value) {
16 | this.setAttribute('role', value);
17 | }
18 | });
19 | }
20 |
21 | // reflected attributes
22 | // https://wicg.github.io/aom/spec/aria-reflection.html#attribute-reflection
23 | const props = ['ActiveDescendant','Atomic','AutoComplete','Busy','Checked','ColCount','ColIndex','ColSpan','Controls','Current','DescribedBy','Details','Disabled','ErrorMessage','Expanded','FlowTo','HasPopup','Hidden','Invalid','KeyShortcuts','Label','LabelledBy','Level','Live','Modal','MultiLine','MultiSelectable','Orientation','Owns','Placeholder','PosInSet','Pressed','ReadOnly','Relevant','Required','RoleDescription','RowCount','RowIndex','RowSpan','Selected','SetSize','Sort','ValueMax','ValueMin','ValueNow','ValueText'];
24 | for (const prop of props) {
25 | const realProp = 'aria'+prop;
26 | const attr = 'aria-'+prop.toLowerCase();
27 | if (!(realProp in Element.prototype)) {
28 | Object.defineProperty(Element.prototype, realProp, {
29 | get: function() {
30 | return this.getAttribute(attr);
31 | },
32 | set: function(value) {
33 | this.setAttribute(attr, value);
34 | }
35 | });
36 | }
37 | }
38 |
39 | // computedRole
40 | if (!('computedRole' in Element.prototype)) {
41 | Object.defineProperty(Element.prototype, 'computedRole', {
42 | get: function() {
43 | let role = this.getAttribute('role');
44 | if (roles[role]) return role;
45 | const tag = this.tagName.toLowerCase();
46 | if (elementToRoles[tag]) {
47 | return elementToRoles[tag][0];
48 | } else {
49 | for (selector in elementToRoles) {
50 | if (this.matches(selector)) {
51 | return elementToRoles[selector][0];
52 | }
53 | }
54 | return null;
55 | }
56 | },
57 | set: function() {}
58 | });
59 |
60 | const roles = {alert:1,alertdialog:1,application:1,article:1,banner:1,button:1,cell:1,checkbox:1,columnheader:1,combobox:1,command:1,complementary:1,composite:1,contentinfo:1,definition:1,dialog:1,directory:1,document:1,feed:1,figure:1,form:1,grid:1,gridcell:1,group:1,heading:1,img:1,input:1,landmark:1,link:1,list:1,listbox:1,listitem:1,log:1,main:1,marquee:1,math:1,menu:1,menubar:1,menuitem:1,menuitemcheckbox:1,menuitemradio:1,navigation:1,note:1,option:1,presentation:1,progressbar:1,radio:1,radiogroup:1,range:1,region:1,roletype:1,row:1,rowgroup:1,rowheader:1,scrollbar:1,search:1,searchbox:1,section:1,sectionhead:1,select:1,separator:1,slider:1,spinbutton:1,status:1,structure:1,tab:1,Table:1,tablist:1,tabpanel:1,Term:1,textbox:1,timer:1,toolbar:1,tooltip:1,tree:1,treegrid:1,treeitem:1,widget:1,window:1,none:1};
61 |
62 | const elementToRoles = {
63 | 'article': [ 'article' ] ,
64 | 'button': [ 'button' ] ,
65 | 'td': ['cell', 'gridcell' ] ,
66 | 'input[type=checkbox]': [ 'checkbox' ] ,
67 | 'th': [ 'columnheader' ] ,
68 | 'select': [ 'combobox', 'listbox' ] ,
69 | 'menuitem': [ 'command', 'menuitem' ] ,
70 | 'dd': [ 'definition' ] ,
71 | 'figure': [ 'figure' ] ,
72 | 'form': [ 'form' ] ,
73 | 'table': [ 'table', 'grid' ] ,
74 | 'fieldset': [ 'group' ] ,
75 | 'h1': [ 'heading' ] ,
76 | 'h2': [ 'heading' ] ,
77 | 'h3': [ 'heading' ] ,
78 | 'h4': [ 'heading' ] ,
79 | 'h5': [ 'heading' ] ,
80 | 'h6': [ 'heading' ] ,
81 | 'img': [ 'img' ] ,
82 | 'a': [ 'link' ] ,
83 | 'link': [ 'link' ] ,
84 | 'ol': [ 'list' ] ,
85 | 'ul': [ 'list' ] ,
86 | 'li': [ 'listitem' ] ,
87 | 'nav': [ 'navigation' ] ,
88 | 'option': [ 'option' ] ,
89 | 'input[type=radio]' : [ 'radio' ] ,
90 | 'frame': [ 'region' ] ,
91 | 'rel': [ 'roletype' ] ,
92 | 'tr': [ 'row' ] ,
93 | 'tbody': [ 'rowgroup' ] ,
94 | 'tfoot': [ 'rowgroup' ] ,
95 | 'thead': [ 'rowgroup' ] ,
96 | 'th[scrope=row]': [ 'rowheader' ] ,
97 | 'input[type=search]': [ 'searchbox' ] ,
98 | 'hr': [ 'separator' ] ,
99 | 'dt': [ 'term' ] ,
100 | 'dfn': [ 'term' ] ,
101 | 'textarea': [ 'textbox' ] ,
102 | 'input[type=text]': [ 'textbox' ] ,
103 | 'input:not([type])': [ 'textbox' ] ,
104 | 'input[type=submit]': [ 'pushbutton' ] ,
105 | };
106 | }
107 |
108 |
109 |
110 |
111 |
112 |
113 | /*
114 | todo:
115 |
116 | ariaActiveDescendantElement
117 | ariaAtomic
118 | ariaAutoComplete
119 | ariaBusy
120 | ariaChecked
121 | ariaColCount
122 | ariaColIndex
123 | ariaColSpan
124 | ariaControlsElements
125 | ariaCurrent
126 | ariaDescribedByElements
127 | ariaDescription
128 | ariaDetailsElements
129 | ariaDisabled
130 | ariaErrorMessageElement
131 | ariaExpanded
132 | ariaFlowToElements
133 | ariaHasPopup
134 | ariaHidden
135 | ariaInvalid
136 | ariaKeyShortcuts
137 | ariaLabel
138 | ariaLabelledByElements
139 | ariaLevel
140 | ariaLive
141 | ariaModal
142 | ariaMultiLine
143 | ariaMultiSelectable
144 | ariaOrientation
145 | ariaOwnsElements
146 | ariaPlaceholder
147 | ariaPosInSet
148 | ariaPressed
149 | ariaReadOnly
150 | ariaRelevant
151 | ariaRequired
152 | ariaRoleDescription
153 | ariaRowCount
154 | ariaRowIndex
155 | ariaRowSpan
156 | ariaSelected
157 | ariaSetSize
158 | ariaSort
159 | ariaValueMax
160 | ariaValueMin
161 | ariaValueNow
162 | ariaValueText
163 | ariaVirtualContent
164 | */
--------------------------------------------------------------------------------
/polyfills/Element/aom.combo.test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Element.computedRole polyfill test
6 |
7 |
8 |
9 |
10 | Here the header
11 |
12 | Main
13 |
14 | h1 inside article
15 |
16 | div
17 |
18 |
19 |
20 |
21 | cell
22 | | cell
23 | |
24 |
25 |
26 |
27 | cell
28 | | cell
29 | |
30 |
31 | cell
32 | | cell
33 | |
34 |
35 |
36 |
42 |
43 |
44 |
45 |
46 |
47 |
87 |
--------------------------------------------------------------------------------
/polyfills/Element/combo.js:
--------------------------------------------------------------------------------
1 | !function(){ 'use strict';
2 |
3 | var ElProto = Element.prototype;
4 |
5 | var poly = {
6 | matches: ElProto.msMatchesSelector || ElProto.webkitMatchesSelector,
7 | closest: function(sel) {
8 | return this.matches(sel) ? this : (this.parentNode && this.parentNode.closest ? this.parentNode.closest(sel) : null);
9 | },
10 | prepend: function prepend() {
11 | this.insertBefore(mutationMacro(arguments) , this.firstChild);
12 | },
13 | append: function append() {
14 | this.appendChild(mutationMacro(arguments));
15 | },
16 | before: function before() {
17 | var parentNode = this.parentNode;
18 | parentNode && parentNode.insertBefore(mutationMacro(arguments), this);
19 | },
20 | after: function after() {
21 | var parentNode = this.parentNode;
22 | parentNode && parentNode.insertBefore(mutationMacro(arguments) , this.nextSibling);
23 | },
24 | replaceWidth: function replace() {
25 | var parentNode = this.parentNode;
26 | parentNode && parentNode.replaceChild(mutationMacro(arguments), this);
27 | },
28 | remove: function remove() {
29 | var parentNode = this.parentNode;
30 | parentNode && parentNode.removeChild(this);
31 | }
32 | };
33 | for (var prop in poly) {
34 | if (!(prop in ElProto)) ElProto[prop] = poly[prop];
35 | }
36 | function textNodeIfString(node) {
37 | return typeof node === 'string' ? d.createTextNode(node) : node;
38 | }
39 | function mutationMacro(nodes) {
40 | if (nodes.length === 1) return textNodeIfString(nodes[0]);
41 | for (var
42 | fragment = d.createDocumentFragment(),
43 | list = slice.call(nodes),
44 | i = 0;
45 | i < nodes.length;
46 | i++
47 | ) {
48 | fragment.appendChild(textNodeIfString(list[i]));
49 | }
50 | return fragment;
51 | }
52 |
53 |
54 | // copy from HTMLElement.proto to Element.proto (mainly for SVGElements ie11)
55 | var props = [
56 | 'blur', // ie11
57 | 'focus',
58 | 'classList',
59 | 'getElementsByClassName',
60 | // 'className',
61 | // 'insertAdjacentElement',
62 | // 'insertAdjacentHTML',
63 | // 'insertAdjacentText',
64 | 'children' // bug, webkit, chrome, ie has not children on the prototype
65 | ];
66 | function copyProperty(prop, from, to){
67 | var desc = Object.getOwnPropertyDescriptor(from, prop);
68 | Object.defineProperty(to, prop, desc);
69 | }
70 | for (var i=0, prop; prop = props[i++];) {
71 | !(prop in ElProto) && copyProperty(prop, HTMLElement.prototype, ElProto);
72 | }
73 |
74 |
75 |
76 | }();
77 |
--------------------------------------------------------------------------------
/polyfills/Element/prototype/isVisible.js:
--------------------------------------------------------------------------------
1 | // todo
2 | // wpt: https://github.com/web-platform-tests/wpt/blob/ff7c98f8fa23c8c36099d267ac258c0005f81180/css/cssom-view/isVisible.html
3 |
4 | if (!Element.prototype.isVisible) {
5 | Element.prototype.isVisible = function(options){
6 |
7 | // If this does not have an associated layout box, return false.
8 | if (!this.offsetParent) return false;
9 | //if (this.offsetWidth === 0 || this.offsetHeight === 0) return false;
10 |
11 | const style = getComputedStyle(this);
12 |
13 | // If a shadow-inclusive ancestor of this has content-visibility: hidden, return false.
14 | // can we skip "this"? It probably won't make offsetHeight.
15 | let oParent = this;
16 | while (oParent) {
17 | const style = getComputedStyle(oParent);
18 | if (style.getPropertyValue('content-visibility') === 'hidden') return false;
19 | oParent = oParent.offsetParent;
20 | }
21 |
22 | // If the checkAriaHidden dictionary member of options is true, and this is hidden (in the ARIA sense), return false. (removed from spec?)
23 |
24 | // If the checkInert dictionary member of options is true, and this is inert, return false.
25 | if (options && options.checkInert && this.closest('[inert]')) return false;
26 |
27 | // If the checkOpacity dictionary member of options is true, and this, or a shadow-inclusive ancestor of this, has a computed opacity value of 0, return false.
28 | if (options && options.checkOpacity && (style.getPropertyValue('opacity') === '0' || style.getPropertyValue('opacity') === '0.0')) return false;
29 |
30 | // If the checkVisibilityCSS dictionary member of options is true, and this is invisible, return false.
31 | if (options && options.checkVisibilityCSS && style.getPropertyValue('visibility') === 'hidden') return false;
32 |
33 | return true;
34 |
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/polyfills/Element/prototype/replaceChildren.js:
--------------------------------------------------------------------------------
1 | if (!('replaceChildren' in Element.prototype)) {
2 | Document.prototype.replaceChildren = Element.prototype.replaceChildren = function replaceChildren() {
3 | while (this.firstChild) this.removeChild(this.firstChild);
4 | this.append.apply(this, arguments);
5 | };
6 | }
--------------------------------------------------------------------------------
/polyfills/Element/prototype/scrollIntoViewIfNeeded.js:
--------------------------------------------------------------------------------
1 | // firefox
2 | if ( !Element.prototype.scrollIntoViewIfNeeded ) {
3 | Element.prototype.scrollIntoViewIfNeeded = function ( centerIfNeeded = true ) {
4 | const el = this;
5 | new IntersectionObserver( function( [entry] ) {
6 | const ratio = entry.intersectionRatio;
7 | if (ratio < 1) {
8 | let place = ratio <= 0 && centerIfNeeded ? 'center' : 'nearest';
9 | el.scrollIntoView( {
10 | block: place,
11 | inline: place,
12 | } );
13 | }
14 | this.disconnect();
15 | } ).observe(this);
16 | };
17 | }
--------------------------------------------------------------------------------
/polyfills/Element/prototype/tests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Element prototype tests
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | There is more 🔽
28 |
29 |
30 |
31 |
32 | bottom
33 |
34 |
35 |
--------------------------------------------------------------------------------
/polyfills/Element/prototype/toggleAttribute.js:
--------------------------------------------------------------------------------
1 | if (!Element.prototype.toggleAttribute) {
2 | Element.prototype.toggleAttribute = function (name, force) {
3 | if (force !== void 0) force = !!force
4 | if (this.hasAttribute(name)) {
5 | if (force) return true;
6 | this.removeAttribute(name);
7 | return false;
8 | }
9 | if (force === false) return false;
10 | this.setAttribute(name, "");
11 | return true;
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/polyfills/HTMLElement/prototype/inert.js:
--------------------------------------------------------------------------------
1 |
2 | if (!('inert' in HTMLElement.prototype)) {
3 |
4 | Object.defineProperty(HTMLElement.prototype, 'inert', {
5 | enumerable: true,
6 | get: function() {
7 | return this.hasAttribute('inert');
8 | },
9 | set: function(inert) {
10 | inert ? this.setAttribute('inert','') : this.removeAttribute('inert');
11 | },
12 | });
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/polyfills/HTMLFormElement/prototype/reportValidity.js:
--------------------------------------------------------------------------------
1 | if (!HTMLFormElement.prototype.reportValidity) {
2 | HTMLFormElement.prototype.reportValidity = function() {
3 | if (this.checkValidity()) return true;
4 | if (this.noValidate) {
5 | this.noValidate = false;
6 | this.requestSubmit();
7 | this.noValidate = true;
8 | } else {
9 | this.requestSubmit();
10 | }
11 | return false;
12 | };
13 | }
14 |
15 | /* old
16 | if (!HTMLFormElement.prototype.reportValidity) {
17 | HTMLFormElement.prototype.reportValidity = function() {
18 | if (this.checkValidity()) return true;
19 | var btn = d.createElement('button');
20 | this.appendChild(btn);
21 | btn.click();
22 | this.removeChild(btn);
23 | return false;
24 | };
25 | }
26 | */
--------------------------------------------------------------------------------
/polyfills/HTMLFormElement/prototype/requestSubmit.js:
--------------------------------------------------------------------------------
1 | if (!HTMLFormElement.prototype.requestSubmit) {
2 | HTMLFormElement.prototype.requestSubmit = function(submitter) {
3 | let submitBtn = submitter;
4 | if (!submitBtn) {
5 | submitBtn = document.createElement('input');
6 | submitBtn.type = 'submit';
7 | submitBtn.hidden = true;
8 | this.appendChild(submitBtn);
9 | }
10 | submitBtn.click();
11 | !submitter && this.removeChild(submitBtn);
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/polyfills/HTMLInputElement/prototype/reportValidity.js:
--------------------------------------------------------------------------------
1 | if (!HTMLInputElement.prototype.reportValidity) {
2 | HTMLInputElement.prototype.reportValidity = function(){
3 | if (this.checkValidity()) return true
4 | var tmpForm;
5 | if (!this.form) {
6 | var tmpForm = d.createElement('form');
7 | tmpForm.style.display = 'inline';
8 | this.before(tmpForm);
9 | tmpForm.append(this);
10 | }
11 | var siblings = Array.from(this.form.elements).filter(function(input){
12 | return input !== this && !!input.checkValidity && !input.disabled;
13 | },this);
14 | siblings.forEach(function(input){
15 | input.disabled = true;
16 | });
17 | this.form.reportValidity();
18 | siblings.forEach(function(input){
19 | input.disabled = false;
20 | });
21 | if (tmpForm) {
22 | tmpForm.before(this);
23 | tmpForm.remove();
24 | }
25 | this.focus();
26 | this.selectionStart = 0;
27 | return false;
28 | };
29 | }
--------------------------------------------------------------------------------
/polyfills/HTMLInputElement/prototype/showPicker.js:
--------------------------------------------------------------------------------
1 |
2 | if (!HTMLInputElement.prototype.showPicker) {
3 | let types = {'date':1, 'month':1, 'week':1, 'time':1, 'datetime-local':1, 'color':1, 'file':1};
4 | HTMLInputElement.prototype.showPicker = function() {
5 | if (this.type in types) {
6 | this.click();
7 | }
8 | };
9 | }
--------------------------------------------------------------------------------
/polyfills/HTMLSlotElement/prototype/assignedElements.js:
--------------------------------------------------------------------------------
1 | if (!HTMLSlotElement.prototype.assignedElements) {
2 | HTMLSlotElement.prototype.assignedElements = function () {
3 | return this.assignedNodes().filter(n => n instanceof Element)
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/polyfills/Math/sign.js:
--------------------------------------------------------------------------------
1 | if (!Math.sign) {
2 | Math.sign = function (x) {
3 | // If x is NaN, the result is NaN.
4 | // If x is -0, the result is -0.
5 | // If x is +0, the result is +0.
6 | // If x is negative and not -0, the result is -1.
7 | // If x is positive and not +0, the result is +1.
8 | return ((x > 0) - (x < 0)) || +x;
9 | // A more aesthetic pseudo-representation:
10 | //
11 | // ( (x > 0) ? 1 : 0 ) // if x is positive, then positive one
12 | // + // else (because you can't be both - and +)
13 | // ( (x < 0) ? -1 : 0 ) // if x is negative, then negative one
14 | // || // if x is 0, -0, or NaN, or not a number,
15 | // +x // then the result will be x, (or) if x is
16 | // // not a number, then x converts to number
17 | };
18 | }
--------------------------------------------------------------------------------
/polyfills/Math/trunc.js:
--------------------------------------------------------------------------------
1 | if (!Math.trunc) {
2 | Math.trunc = function (n) {
3 | return n < 0 ? Math.ceil(n) : Math.floor(n);
4 | };
5 | }
--------------------------------------------------------------------------------
/polyfills/Node/prototype/contains.js:
--------------------------------------------------------------------------------
1 | if (!('contains' in Node.prototype)) {
2 | Node.prototype.contains = function(el){
3 | if (el instanceof CharacterData) {
4 | if (!el.parentNode) return false;
5 | el = el.parentNode;
6 | }
7 | if (this === el) return true;
8 | if (this instanceof Document) {
9 | return this.documentElement.contains(el)
10 | }
11 | return HTMLElement.prototype.contains.call(this, el);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/polyfills/Node/prototype/insertAfter.js:
--------------------------------------------------------------------------------
1 | /*! (c) Andrea Giammarchi - ISC */
2 | /*
3 | https://github.com/ungap/insert-after/blob/main/index.js
4 | */
5 | if (!('insertAfter' in Node.prototype))
6 | Node.prototype.insertAfter = function insertAfter(node, ref) {
7 | return this.insertBefore(node, ref ? ref.nextSibling : this.firstChild);
8 | };
--------------------------------------------------------------------------------
/polyfills/Node/prototype/isConnected.js:
--------------------------------------------------------------------------------
1 | if (!('isConnected' in Node.prototype)) {
2 | Object.defineProperty(Node.prototype, 'isConnected',{
3 | get:function(){
4 | return this.ownerDocument.contains(this);
5 | }
6 | })
7 | }
8 |
--------------------------------------------------------------------------------
/polyfills/Node/prototype/tests/contains.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Level.css TEST
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
33 |
--------------------------------------------------------------------------------
/polyfills/Number/isNumber.js:
--------------------------------------------------------------------------------
1 | if (!Number.isInteger) {
2 | Number.isInteger = function (value) {
3 | return (
4 | typeof value === 'number' &&
5 | isFinite(value) &&
6 | Math.floor(value) === value
7 | );
8 | };
9 | }
--------------------------------------------------------------------------------
/polyfills/Object/assign.js:
--------------------------------------------------------------------------------
1 | if (typeof Object.assign != 'function') {
2 | Object.defineProperty(Object, "assign", {
3 | value: function assign(target, varArgs) {
4 | if (target == null) {
5 | throw new TypeError('Cannot convert undefined or null to object');
6 | }
7 | var to = Object(target);
8 | for (var index = 1; index < arguments.length; index++) {
9 | var nextSource = arguments[index];
10 | if (nextSource != null) {
11 | for (var nextKey in nextSource) {
12 | if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
13 | to[nextKey] = nextSource[nextKey];
14 | }
15 | }
16 | }
17 | }
18 | return to;
19 | },
20 | writable: true,
21 | configurable: true
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/polyfills/Object/entries.js:
--------------------------------------------------------------------------------
1 | if (!Object.entries) {
2 | Object.entries = function (obj) {
3 | var ownProps = Object.keys(obj),
4 | i = ownProps.length,
5 | resArray = new Array(i); // preallocate the Array
6 | while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]];
7 | return resArray;
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/polyfills/Object/fromEntries.js:
--------------------------------------------------------------------------------
1 | if (!Object.fromEntries) {
2 | Object.fromEntries = function (arr) {
3 | var obj = {}, item, i;
4 | for (i=0; item=arr[i++];) {
5 | obj[item[0]] = item[1];
6 | }
7 | return obj;
8 | };
9 | }
--------------------------------------------------------------------------------
/polyfills/Object/hasOwn.js:
--------------------------------------------------------------------------------
1 | !Object.hasOwn && (Object.hasOwn = Object.call.bind(Object.hasOwnProperty));
--------------------------------------------------------------------------------
/polyfills/Object/is.js:
--------------------------------------------------------------------------------
1 | if (!Object.is) {
2 | Object.defineProperty(Object, "is", {
3 | value: function (x, y) {
4 | // SameValue algorithm
5 | if (x === y) {
6 | // return true if x and y are not 0, OR
7 | // if x and y are both 0 of the same sign.
8 | // This checks for cases 1 and 2 above.
9 | return x !== 0 || 1 / x === 1 / y;
10 | } else {
11 | // return true if both x AND y evaluate to NaN.
12 | // The only possibility for a variable to not be strictly equal to itself
13 | // is when that variable evaluates to NaN (example: Number.NaN, 0/0, NaN).
14 | // This checks for case 3.
15 | return x !== x && y !== y;
16 | }
17 | }
18 | });
19 | }
--------------------------------------------------------------------------------
/polyfills/Object/values.js:
--------------------------------------------------------------------------------
1 | if (!Object.values) {
2 | Object.values = function values(O) {
3 | return Object.keys(O).map(function(key) {
4 | return O[key];
5 | });
6 | };
7 | }
8 | /*
9 | Object.key available in ie11!
10 | if (!Object.values) Object.values = function (o) {
11 | if (o !== Object(o)) throw new TypeError('Object.values called on a non-object');
12 | var values = [], key;
13 | for (key in o) if (Object.prototype.hasOwnProperty.call(o, key)) values.push(o[key]);
14 | return values;
15 | }
16 | */
--------------------------------------------------------------------------------
/polyfills/Promise/allSettled.js:
--------------------------------------------------------------------------------
1 | if (Promise && !Promise.allSettled) {
2 | Promise.allSettled = function (promises) {
3 | return Promise.all(promises.map(function (promise) {
4 | return promise.then(function (value) {
5 | return { state: 'fulfilled', value: value };
6 | }).catch(function (reason) {
7 | return { state: 'rejected', reason: reason };
8 | });
9 | }));
10 | };
11 | }
--------------------------------------------------------------------------------
/polyfills/Promise/any.js:
--------------------------------------------------------------------------------
1 | https://github.com/ungap/promise-any/blob/master/index.js
2 | var any = (Promise.any || function ($) {
3 | return new Promise(function (D, E, A, L) {
4 | A = [];
5 | L = $.map(function ($, i) {
6 | return Promise.resolve($).then(D, function (O) {
7 | return ((A[i] = O), --L) || E({ errors: A });
8 | });
9 | }).length;
10 | });
11 | }).bind(Promise);
--------------------------------------------------------------------------------
/polyfills/Promise/withResolvers.js:
--------------------------------------------------------------------------------
1 | Promise.withResolvers || (Promise.withResolvers = function withResolvers() {
2 | var a, b, c = new this(function (resolve, reject) {
3 | a = resolve;
4 | b = reject;
5 | });
6 | return {resolve: a, reject: b, promise: c};
7 | });
--------------------------------------------------------------------------------
/polyfills/RegExp/prototype/flags.js:
--------------------------------------------------------------------------------
1 | if (RegExp.prototype.flags === undefined) {
2 | Object.defineProperty(RegExp.prototype, 'flags', {
3 | configurable: true,
4 | get: function () {
5 | return this.toString().match(/[gimuy]*$/)[0];
6 | }
7 | });
8 | }
9 |
--------------------------------------------------------------------------------
/polyfills/SVGStyleElement/combo.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxodin/lazyfill/c53e43fe2d88269cf84b924461218c23422cc49a/polyfills/SVGStyleElement/combo.js
--------------------------------------------------------------------------------
/polyfills/SVGStyleElement/prototype/sheet.js:
--------------------------------------------------------------------------------
1 | // ie11
2 | if (!('sheet' in SVGStyleElement.prototype)) {
3 | Object.defineProperty(SVGStyleElement.prototype, 'sheet', {
4 | get:function(){
5 | var all = d.styleSheets;
6 | for (var i=0, sheet; sheet=all[i++];) {
7 | if (sheet.ownerNode === this) return sheet;
8 | }
9 | }
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/polyfills/String/fromCodePoint.js:
--------------------------------------------------------------------------------
1 | if (!String.fromCodePoint) {
2 | (function () {
3 | var defineProperty = (function () {
4 | try {
5 | var object = {};
6 | var $defineProperty = Object.defineProperty;
7 | var result = $defineProperty(object, object, object) && $defineProperty;
8 | } catch (error) { }
9 | return result;
10 | })();
11 | var stringFromCharCode = String.fromCharCode;
12 | var floor = Math.floor;
13 | var fromCodePoint = function () {
14 | var MAX_SIZE = 0x4000;
15 | var codeUnits = [];
16 | var highSurrogate;
17 | var lowSurrogate;
18 | var index = -1;
19 | var length = arguments.length;
20 | if (!length) {
21 | return '';
22 | }
23 | var result = '';
24 | while (++index < length) {
25 | var codePoint = Number(arguments[index]);
26 | if (
27 | !isFinite(codePoint) ||
28 | codePoint < 0 ||
29 | codePoint > 0x10ffff ||
30 | floor(codePoint) != codePoint
31 | ) {
32 | throw RangeError('Invalid code point: ' + codePoint);
33 | }
34 | if (codePoint <= 0xffff) {
35 | // BMP code point
36 | codeUnits.push(codePoint);
37 | } else {
38 | codePoint -= 0x10000;
39 | highSurrogate = (codePoint >> 10) + 0xd800;
40 | lowSurrogate = (codePoint % 0x400) + 0xdc00;
41 | codeUnits.push(highSurrogate, lowSurrogate);
42 | }
43 | if (index + 1 == length || codeUnits.length > MAX_SIZE) {
44 | result += stringFromCharCode.apply(null, codeUnits);
45 | codeUnits.length = 0;
46 | }
47 | }
48 | return result;
49 | };
50 | if (defineProperty) {
51 | defineProperty(String, 'fromCodePoint', {
52 | value: fromCodePoint,
53 | configurable: true,
54 | writable: true,
55 | });
56 | } else {
57 | String.fromCodePoint = fromCodePoint;
58 | }
59 | })();
60 | }
--------------------------------------------------------------------------------
/polyfills/String/prototype/at.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.at) {
2 | Object.defineProperty(String.prototype, "at",
3 | {
4 | value: function (n) {
5 | // ToInteger() abstract op
6 | n = Math.trunc(n) || 0;
7 | // Allow negative indexing from the end
8 | if (n < 0) n += this.length;
9 | // OOB access is guaranteed to return undefined
10 | if (n < 0 || n >= this.length) return undefined;
11 | // Otherwise, this is just normal property access
12 | return this[n];
13 | },
14 | writable: true,
15 | enumerable: false,
16 | configurable: true
17 | });
18 | }
--------------------------------------------------------------------------------
/polyfills/String/prototype/codePointAt.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.codePointAt) {
2 | Object.defineProperty(String.prototype, 'codePointAt', {
3 | configurable: true,
4 | writable: true,
5 | value: function codePointAt (position) {
6 | if (this == null) {
7 | throw TypeError();
8 | }
9 | var string = String(this);
10 | var size = string.length;
11 | var index = position ? Number(position) : 0;
12 | if (index != index) {
13 | index = 0;
14 | }
15 | if (index < 0 || index >= size) {
16 | return undefined;
17 | }
18 | var first = string.charCodeAt(index);
19 | var second;
20 | if (first >= 0xd800 && first <= 0xdbff && size > index + 1) {
21 | second = string.charCodeAt(index + 1);
22 | if (second >= 0xdc00 && second <= 0xdfff) {
23 | return (first - 0xd800) * 0x400 + second - 0xdc00 + 0x10000;
24 | }
25 | }
26 | return first;
27 | },
28 | });
29 | }
--------------------------------------------------------------------------------
/polyfills/String/prototype/endsWith.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.endsWith) {
2 | Object.defineProperty(String.prototype, 'endsWith', {
3 | configurable: true,
4 | writable: true,
5 | value: function (searchString, position) {
6 | var subjectString = this.toString();
7 | if (
8 | typeof position !== 'number' ||
9 | !isFinite(position) ||
10 | Math.floor(position) !== position ||
11 | position > subjectString.length
12 | ) {
13 | position = subjectString.length;
14 | }
15 | position -= searchString.length;
16 | var lastIndex = subjectString.lastIndexOf(searchString, position);
17 | return lastIndex !== -1 && lastIndex === position;
18 | },
19 | });
20 | }
--------------------------------------------------------------------------------
/polyfills/String/prototype/includes.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.includes) {
2 | String.prototype.includes = function(search, start){
3 | if (typeof start !== 'number') start = 0;
4 | if (start + search.length > this.length) return false;
5 | return this.indexOf(search, start) !== -1;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/polyfills/String/prototype/padEnd.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.padEnd) {
2 | Object.defineProperty(String.prototype, 'padEnd', {
3 | configurable: true,
4 | writable: true,
5 | value: function (targetLength, padString) {
6 | targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
7 | padString = String(typeof padString !== 'undefined' ? padString : ' ');
8 | if (this.length > targetLength) {
9 | return String(this);
10 | } else {
11 | targetLength = targetLength - this.length;
12 | if (targetLength > padString.length) {
13 | padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
14 | }
15 | return String(this) + padString.slice(0, targetLength);
16 | }
17 | },
18 | });
19 | }
--------------------------------------------------------------------------------
/polyfills/String/prototype/padStart.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.padStart) {
2 | Object.defineProperty(String.prototype, 'padStart', {
3 | configurable: true,
4 | writable: true,
5 | value: function (targetLength, padString) {
6 | targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
7 | padString = String(typeof padString !== 'undefined' ? padString : ' ');
8 | if (this.length > targetLength) {
9 | return String(this);
10 | } else {
11 | targetLength = targetLength - this.length;
12 | if (targetLength > padString.length) {
13 | padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
14 | }
15 | return padString.slice(0, targetLength) + String(this);
16 | }
17 | },
18 | });
19 | }
--------------------------------------------------------------------------------
/polyfills/String/prototype/repeat.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.repeat) {
2 | Object.defineProperty(String.prototype, 'repeat', {
3 | configurable: true,
4 | writable: true,
5 | value: function (count) {
6 | if (this == null) throw new TypeError("can't convert " + this + ' to object');
7 | var str = '' + this;
8 | count = +count;
9 | if (count != count) count = 0;
10 | if (count < 0) throw new RangeError('repeat count must be non-negative');
11 | if (count == Infinity) throw new RangeError('repeat count must be less than infinity');
12 | count = Math.floor(count);
13 | if (str.length == 0 || count == 0) return '';
14 | if (str.length * count >= 1 << 28) {
15 | throw new RangeError('repeat count must not overflow maximum string size');
16 | }
17 | var rpt = '';
18 | for (; ;) {
19 | if ((count & 1) == 1) rpt += str;
20 | count >>>= 1;
21 | if (count == 0) break;
22 | str += str;
23 | }
24 | return rpt;
25 | },
26 | });
27 | }
--------------------------------------------------------------------------------
/polyfills/String/prototype/replaceAll.js:
--------------------------------------------------------------------------------
1 | // https://github.com/zloirock/core-js/blob/d7409d106383f252ab25215a287d9b8160785918/packages/core-js/modules/es.string.replace-all.js#L23
2 | if (!''.replaceAll) {
3 | !function(){
4 |
5 | var stringIndexOf = function (string, searchValue, fromIndex) {
6 | if (fromIndex > string.length) return -1;
7 | if (searchValue === '') return fromIndex;
8 | return string.indexOf(searchValue, fromIndex);
9 | };
10 |
11 | var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g;
12 | var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g;
13 | function GetSubstitution(matched, str, position, captures, namedCaptures, replacement) {
14 | var tailPos = position + matched.length;
15 | var m = captures.length;
16 | var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
17 | if (namedCaptures !== undefined) {
18 | namedCaptures = toObject(namedCaptures);
19 | symbols = SUBSTITUTION_SYMBOLS;
20 | }
21 | return ''.replace.call(replacement, symbols, function (match, ch) {
22 | var capture;
23 | switch (ch.charAt(0)) {
24 | case '$': return '$';
25 | case '&': return matched;
26 | case '`': return str.slice(0, position);
27 | case "'": return str.slice(tailPos);
28 | case '<':
29 | capture = namedCaptures[ch.slice(1, -1)];
30 | break;
31 | default: // \d\d?
32 | var n = +ch;
33 | if (n === 0) return match;
34 | if (n > m) {
35 | var f = Math.floor(n / 10);
36 | if (f === 0) return match;
37 | if (f <= m) return captures[f - 1] === undefined ? ch.charAt(1) : captures[f - 1] + ch.charAt(1);
38 | return match;
39 | }
40 | capture = captures[n - 1];
41 | }
42 | return capture === undefined ? '' : capture;
43 | });
44 | };
45 |
46 | Object.defineProperty(String.prototype, 'replaceAll', {
47 | configurable: true,
48 | writable: true,
49 | value: function replaceAll(searchValue, replaceValue) {
50 | if (this == null) throw TypeError("Can't call method on " + this);
51 | var O = this;
52 | var IS_REG_EXP, flags, replacer, string, searchString, functionalReplace, searchLength, advanceBy, replacement;
53 | var position = 0;
54 | var endOfLastMatch = 0;
55 | var result = '';
56 | if (searchValue != null) {
57 | IS_REG_EXP = searchValue instanceof RegExp;
58 | if (IS_REG_EXP) {
59 | flags = String(searchValue.flags);
60 | if (!~flags.indexOf('g')) throw TypeError('`.replaceAll` does not allow non-global regexes');
61 | }
62 | replacer = window.Symbol && searchValue[Symbol.replace];
63 | var IS_PURE = true; // ??
64 | if (replacer !== undefined) {
65 | return replacer.call(searchValue, O, replaceValue);
66 | } else if (IS_PURE && IS_REG_EXP) {
67 | return String(O).replace(searchValue, replaceValue);
68 | }
69 | }
70 | string = String(O);
71 | searchString = String(searchValue);
72 | functionalReplace = typeof replaceValue === 'function';
73 | if (!functionalReplace) replaceValue = String(replaceValue);
74 | searchLength = searchString.length;
75 | advanceBy = Math.max(1, searchLength);
76 | position = stringIndexOf(string, searchString, 0);
77 | while (position !== -1) {
78 | if (functionalReplace) {
79 | replacement = String(replaceValue(searchString, position, string));
80 | } else {
81 | replacement = GetSubstitution(searchString, string, position, [], undefined, replaceValue);
82 | }
83 | result += string.slice(endOfLastMatch, position) + replacement;
84 | endOfLastMatch = position + searchLength;
85 | position = stringIndexOf(string, searchString, position + advanceBy);
86 | }
87 | if (endOfLastMatch < string.length) {
88 | result += string.slice(endOfLastMatch);
89 | }
90 | return result;
91 | }
92 | });
93 |
94 |
95 |
96 | }();
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/polyfills/String/prototype/startsWith.js:
--------------------------------------------------------------------------------
1 | if (!String.prototype.startsWith) {
2 | Object.defineProperty(String.prototype, 'startsWith', {
3 | configurable: true,
4 | writable: true,
5 | value: function (searchString, position) {
6 | position = position || 0;
7 | return this.substr(position, searchString.length) === searchString;
8 | },
9 | });
10 | }
--------------------------------------------------------------------------------
/polyfills/SubmitEvent/prototype/submitter.js:
--------------------------------------------------------------------------------
1 | !function(){ 'use strict';
2 | let lastBtn = null;
3 |
4 | addEventListener('click',function(e){
5 | if (!e.target.closest) return;
6 | lastBtn = e.target.closest('button, input[type=submit]');
7 | }, true);
8 |
9 | addEventListener('submit',function(e){
10 | if ('submitter' in e) return;
11 | var canditates = [document.activeElement, lastBtn];
12 | lastBtn = null;
13 | for (var i=0; i < canditates.length; i++) {
14 | var candidate = canditates[i];
15 | if (!candidate) continue;
16 | if (!candidate.form) continue;
17 | if (!candidate.matches('button, input[type=button], input[type=image]')) continue;
18 | e.submitter = candidate;
19 | return;
20 | }
21 | e.submitter = e.target.querySelector('button, input[type=button], input[type=image]')
22 | }, true);
23 | }();
24 |
--------------------------------------------------------------------------------
/polyfills/SubmitEvent/prototype/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SubmitEvent prototype test
6 |
7 |
8 |
9 |
10 |
15 |
--------------------------------------------------------------------------------
/polyfills/WeakRef.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 |
4 |
5 | Works in IE and Firefox
6 | not in Chrome and Safari :(
7 |
8 | Not very efficient, as it creates a HTMLCollection in the constructor and for deref()
9 | AND as it dont work for safari and chrome, it looses even more memory as the HTMLCollections are not garbage collected
10 |
11 | inspiration: https://github.com/whatwg/dom/issues/706
12 | "Creating new HTMLCollection instances everytime will increase management cost."
13 |
14 |
15 | Todo: any other solutions / hacks?
16 |
17 | */
18 |
19 | console.log('dont use this!');
20 |
21 | if (!window.WeakRef) {
22 | let el = document.createElement('div');
23 | window.WeakRef = function(value) {
24 | this.id = Math.random();
25 | let collection = el.getElementsByTagName("x"+this.id);
26 | collection.expando = value;
27 | collection = null;
28 | }
29 | WeakRef.prototype = {
30 | deref: function() {
31 | return el.getElementsByTagName("x"+this.id).expando;
32 | }
33 | }
34 | }
35 |
36 | /* todo: how to?
37 | function FinalizationGroup(fn) {
38 |
39 | }
40 | FinalizationGroup.prototype = {
41 | register(value, name) {
42 | },
43 | unregister(value, name) {
44 | },
45 | cleanupSome(fn) {
46 | }
47 | }
48 | */
--------------------------------------------------------------------------------
/polyfills/WeakSet.js:
--------------------------------------------------------------------------------
1 | if (!window.WeakSet) { 'use strict'
2 | WeakSet = function(iterable){
3 | this.Map = new WeakMap();
4 | iterable && iterable.forEach(this.add, this);
5 | }
6 | WeakSet.prototype = {
7 | add:function(value){
8 | this.Map.set(value, 1);
9 | return this;
10 | },
11 | delete:function(value){ return this.Map.delete(value); },
12 | has:function(value){ return this.Map.has(value); }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/polyfills/cancelIdleCallback.js:
--------------------------------------------------------------------------------
1 | if (!window.cancelIdleCallback) {
2 | window.cancelIdleCallback = function (id) {
3 | clearTimeout(id);
4 | };
5 | }
--------------------------------------------------------------------------------
/polyfills/crypto/randomUUID.js:
--------------------------------------------------------------------------------
1 | // Code based on Node.js' `lib/internal/crypto/random.js`, subject
2 | // to Node.js license found at:
3 | // https://raw.githubusercontent.com/nodejs/node/master/LICENSE
4 |
5 | !function () {
6 |
7 | const randomFillSync = window.crypto.getRandomValues.bind(window.crypto);
8 |
9 | // Implements an RFC 4122 version 4 random UUID.
10 | // To improve performance, random data is generated in batches
11 | // large enough to cover kBatchSize UUID's at a time. The uuidData
12 | // and uuid buffers are reused. Each call to randomUUID() consumes
13 | // 16 bytes from the buffer.
14 |
15 | const kHexDigits = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102];
16 | const kBatchSize = 128;
17 | let uuidData;
18 | let uuidNotBuffered;
19 | let uuid;
20 | let uuidBatch = 0;
21 | let slice = Uint8Array.prototype.slice || Array.prototype.slice;
22 |
23 | function getBufferedUUID() {
24 | if (uuidData === undefined) uuidData = new Uint8Array(16 * kBatchSize);
25 | if (uuidBatch === 0) randomFillSync(uuidData);
26 | uuidBatch = (uuidBatch + 1) % kBatchSize;
27 | return slice.call(uuidData, uuidBatch * 16, uuidBatch * 16 + 16);
28 | }
29 |
30 | function randomUUID(options) {
31 | const disableEntropyCache = options ? options.disableEntropyCache : false;
32 |
33 | if (uuid === undefined) {
34 | uuid = new Uint8Array(36);
35 | uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'.charCodeAt(0);
36 | uuid[14] = 52; // '4', identifies the UUID version
37 | }
38 |
39 | let uuidBuf;
40 | if (!disableEntropyCache) {
41 | uuidBuf = getBufferedUUID();
42 | } else {
43 | uuidBuf = uuidNotBuffered;
44 | if (uuidBuf === undefined) uuidBuf = uuidNotBuffered = new Uint8Array(16);
45 | randomFillSync(uuidBuf);
46 | }
47 |
48 | // Variant byte: 10xxxxxx (variant 1)
49 | uuidBuf[8] = (uuidBuf[8] & 0x3f) | 0x80;
50 |
51 | // This function is structured the way it is for performance.
52 | // The uuid buffer stores the serialization of the random
53 | // bytes from uuidData.
54 | // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
55 | let n = 0;
56 | uuid[0] = kHexDigits[uuidBuf[n] >> 4];
57 | uuid[1] = kHexDigits[uuidBuf[n++] & 0xf];
58 | uuid[2] = kHexDigits[uuidBuf[n] >> 4];
59 | uuid[3] = kHexDigits[uuidBuf[n++] & 0xf];
60 | uuid[4] = kHexDigits[uuidBuf[n] >> 4];
61 | uuid[5] = kHexDigits[uuidBuf[n++] & 0xf];
62 | uuid[6] = kHexDigits[uuidBuf[n] >> 4];
63 | uuid[7] = kHexDigits[uuidBuf[n++] & 0xf];
64 | // -
65 | uuid[9] = kHexDigits[uuidBuf[n] >> 4];
66 | uuid[10] = kHexDigits[uuidBuf[n++] & 0xf];
67 | uuid[11] = kHexDigits[uuidBuf[n] >> 4];
68 | uuid[12] = kHexDigits[uuidBuf[n++] & 0xf];
69 | // -
70 | // 4, uuid[14] is set already...
71 | uuid[15] = kHexDigits[uuidBuf[n++] & 0xf];
72 | uuid[16] = kHexDigits[uuidBuf[n] >> 4];
73 | uuid[17] = kHexDigits[uuidBuf[n++] & 0xf];
74 | // -
75 | uuid[19] = kHexDigits[uuidBuf[n] >> 4];
76 | uuid[20] = kHexDigits[uuidBuf[n++] & 0xf];
77 | uuid[21] = kHexDigits[uuidBuf[n] >> 4];
78 | uuid[22] = kHexDigits[uuidBuf[n++] & 0xf];
79 | // -
80 | uuid[24] = kHexDigits[uuidBuf[n] >> 4];
81 | uuid[25] = kHexDigits[uuidBuf[n++] & 0xf];
82 | uuid[26] = kHexDigits[uuidBuf[n] >> 4];
83 | uuid[27] = kHexDigits[uuidBuf[n++] & 0xf];
84 | uuid[28] = kHexDigits[uuidBuf[n] >> 4];
85 | uuid[29] = kHexDigits[uuidBuf[n++] & 0xf];
86 | uuid[30] = kHexDigits[uuidBuf[n] >> 4];
87 | uuid[31] = kHexDigits[uuidBuf[n++] & 0xf];
88 | uuid[32] = kHexDigits[uuidBuf[n] >> 4];
89 | uuid[33] = kHexDigits[uuidBuf[n++] & 0xf];
90 | uuid[34] = kHexDigits[uuidBuf[n] >> 4];
91 | uuid[35] = kHexDigits[uuidBuf[n] & 0xf];
92 |
93 | return String.fromCharCode.apply(null, uuid);
94 | }
95 |
96 | window.crypto.randomUUID = randomUUID;
97 |
98 |
99 | }();
100 |
--------------------------------------------------------------------------------
/polyfills/crypto/randomUUID.original.js:
--------------------------------------------------------------------------------
1 | // Code based on Node.js' `lib/internal/crypto/random.js`, subject
2 | // to Node.js license found at:
3 | // https://raw.githubusercontent.com/nodejs/node/master/LICENSE
4 |
5 | !function () {
6 |
7 | //
8 | // internal/errors
9 | //
10 | class ERR_INVALID_ARG_TYPE extends TypeError {
11 | constructor(name, type, value) {
12 | super(`${name} variable is not of type ${type} (value: '${value}')`);
13 | }
14 | code = 'ERR_INVALID_ARG_TYPE';
15 | }
16 |
17 | //
18 | // internal/validators
19 | //
20 | function validateBoolean(value, name) {
21 | if (typeof value !== 'boolean') throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value);
22 | }
23 |
24 | function validateObject(value, name) {
25 | if (value === null || Array.isArray(value) || typeof value !== 'object') {
26 | throw new ERR_INVALID_ARG_TYPE(name, 'Object', value);
27 | }
28 | }
29 |
30 | //
31 | // crypto
32 | //
33 | const randomFillSync =
34 | typeof window === 'undefined'
35 | ? require('crypto').randomFillSync
36 | : window.crypto.getRandomValues.bind(window.crypto);
37 |
38 | // Implements an RFC 4122 version 4 random UUID.
39 | // To improve performance, random data is generated in batches
40 | // large enough to cover kBatchSize UUID's at a time. The uuidData
41 | // and uuid buffers are reused. Each call to randomUUID() consumes
42 | // 16 bytes from the buffer.
43 |
44 | const kHexDigits = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102];
45 | const kBatchSize = 128;
46 | let uuidData;
47 | let uuidNotBuffered;
48 | let uuid;
49 | let uuidBatch = 0;
50 |
51 | function getBufferedUUID() {
52 | if (uuidData === undefined) {
53 | uuidData = new Uint8Array(16 * kBatchSize);
54 | }
55 | if (uuidBatch === 0) randomFillSync(uuidData);
56 | uuidBatch = (uuidBatch + 1) % kBatchSize;
57 | return uuidData.slice(uuidBatch * 16, uuidBatch * 16 + 16);
58 | }
59 |
60 | function randomUUID(options) {
61 | if (options !== undefined) validateObject(options, 'options');
62 | const { disableEntropyCache = false } = { ...options };
63 |
64 | validateBoolean(disableEntropyCache, 'options.disableEntropyCache');
65 |
66 | if (uuid === undefined) {
67 | uuid = new Uint8Array(36);
68 | uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'.charCodeAt(0);
69 | uuid[14] = 52; // '4', identifies the UUID version
70 | }
71 |
72 | let uuidBuf;
73 | if (!disableEntropyCache) {
74 | uuidBuf = getBufferedUUID();
75 | } else {
76 | uuidBuf = uuidNotBuffered;
77 | if (uuidBuf === undefined) uuidBuf = uuidNotBuffered = new Uint8Array(16);
78 | randomFillSync(uuidBuf);
79 | }
80 |
81 | // Variant byte: 10xxxxxx (variant 1)
82 | uuidBuf[8] = (uuidBuf[8] & 0x3f) | 0x80;
83 |
84 | // This function is structured the way it is for performance.
85 | // The uuid buffer stores the serialization of the random
86 | // bytes from uuidData.
87 | // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
88 | let n = 0;
89 | uuid[0] = kHexDigits[uuidBuf[n] >> 4];
90 | uuid[1] = kHexDigits[uuidBuf[n++] & 0xf];
91 | uuid[2] = kHexDigits[uuidBuf[n] >> 4];
92 | uuid[3] = kHexDigits[uuidBuf[n++] & 0xf];
93 | uuid[4] = kHexDigits[uuidBuf[n] >> 4];
94 | uuid[5] = kHexDigits[uuidBuf[n++] & 0xf];
95 | uuid[6] = kHexDigits[uuidBuf[n] >> 4];
96 | uuid[7] = kHexDigits[uuidBuf[n++] & 0xf];
97 | // -
98 | uuid[9] = kHexDigits[uuidBuf[n] >> 4];
99 | uuid[10] = kHexDigits[uuidBuf[n++] & 0xf];
100 | uuid[11] = kHexDigits[uuidBuf[n] >> 4];
101 | uuid[12] = kHexDigits[uuidBuf[n++] & 0xf];
102 | // -
103 | // 4, uuid[14] is set already...
104 | uuid[15] = kHexDigits[uuidBuf[n++] & 0xf];
105 | uuid[16] = kHexDigits[uuidBuf[n] >> 4];
106 | uuid[17] = kHexDigits[uuidBuf[n++] & 0xf];
107 | // -
108 | uuid[19] = kHexDigits[uuidBuf[n] >> 4];
109 | uuid[20] = kHexDigits[uuidBuf[n++] & 0xf];
110 | uuid[21] = kHexDigits[uuidBuf[n] >> 4];
111 | uuid[22] = kHexDigits[uuidBuf[n++] & 0xf];
112 | // -
113 | uuid[24] = kHexDigits[uuidBuf[n] >> 4];
114 | uuid[25] = kHexDigits[uuidBuf[n++] & 0xf];
115 | uuid[26] = kHexDigits[uuidBuf[n] >> 4];
116 | uuid[27] = kHexDigits[uuidBuf[n++] & 0xf];
117 | uuid[28] = kHexDigits[uuidBuf[n] >> 4];
118 | uuid[29] = kHexDigits[uuidBuf[n++] & 0xf];
119 | uuid[30] = kHexDigits[uuidBuf[n] >> 4];
120 | uuid[31] = kHexDigits[uuidBuf[n++] & 0xf];
121 | uuid[32] = kHexDigits[uuidBuf[n] >> 4];
122 | uuid[33] = kHexDigits[uuidBuf[n++] & 0xf];
123 | uuid[34] = kHexDigits[uuidBuf[n] >> 4];
124 | uuid[35] = kHexDigits[uuidBuf[n] & 0xf];
125 |
126 | return String.fromCharCode.apply(null, uuid);
127 | }
128 |
129 | window.crypto.randomUUID = randomUUID;
130 |
131 |
132 | }();
133 |
--------------------------------------------------------------------------------
/polyfills/document/caretRangeFromPoint.js:
--------------------------------------------------------------------------------
1 | if (!document.caretRangeFromPoint) { // polyfill for ff
2 | document.caretRangeFromPoint = function(x,y){
3 | let caretP = document.caretPositionFromPoint(x,y);
4 | let range = document.createRange();
5 | range.setStart(caretP.offsetNode, caretP.offset);
6 | return range;
7 | };
8 | }
9 |
--------------------------------------------------------------------------------
/polyfills/document/currentScript.js:
--------------------------------------------------------------------------------
1 | if (!('currentScript' in document)) {
2 |
3 | Object.defineProperty(document, 'currentScript', {
4 | get: function () {
5 | // todo: find script without src
6 | try { throw new Error(); }
7 | catch (e) {
8 | if (!e.stack) throw new Error('error.stack not available');
9 | var i = 0;
10 | var res = ((/.*at [^(]*\((.*):.+:.+\)$/ig).exec(e.stack) || [false])[1];
11 | var scripts = document.scripts;
12 | for (i = 0; i < scripts.length; i++) {
13 | if (scripts[i].src == res || scripts[i].readyState == "interactive") {
14 | return scripts[i];
15 | }
16 | }
17 | }
18 | console.warn('currentScript not found')
19 | }
20 | });
21 |
22 | }
--------------------------------------------------------------------------------
/polyfills/navigator/share.js:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2016 Tobias Buschor https://goo.gl/gl0mbf | MIT License https://goo.gl/HgajeK */
2 | !function(){ 'use strict';
3 |
4 | const share = async function(data){
5 |
6 | if (!window.HTMLDialogElement) {
7 | await import('https://cdn.jsdelivr.net/gh/nuxodin/dialog-polyfill@1.4.1/dialog.min.js');
8 | }
9 |
10 | const dialog = document.createElement('dialog');
11 | dialog.className = 'c1Share';
12 | dialog.innerHTML = ''+style;
13 | const body = dialog.querySelector('.-body');
14 |
15 | //let shared = false;
16 | function close(){ // to be animated
17 | dialog.classList.remove('-Open');
18 | setTimeout(()=>{
19 | dialog.close();
20 | },200);
21 | }
22 |
23 | const buildText = (...parts) => parts.filter(Boolean).join('\n\n');
24 | const payload = {
25 | title: enc(data.title),
26 | text: enc(data.text),
27 | url: enc(data.url),
28 | titleText: enc(buildText(data.title, data.text)+'\n'),
29 | titleTextUrl: enc(buildText(data.title, data.text, data.url)+'\n'),
30 | textUrl: enc(buildText(data.text, data.url)+'\n'),
31 | }
32 |
33 | document.body.append(dialog);
34 | dialog.showModal();
35 | dialog.classList.add('-Open');
36 | dialog.addEventListener('close', () => {
37 | //shared ? resolve() : reject(); // safaris implementation of the promise
38 | dialog.remove();
39 | });
40 |
41 | share.items.forEach((item,name)=>{
42 | name = txt[name] || name;
43 | const a = document.createElement('a');
44 | a.innerHTML = item.svg+name;
45 | // not mentoned in screenreader
46 | a.firstElementChild.setAttribute('aria-hidden',true);
47 | a.href = item.url ? item.url(payload) : '';
48 | a.target = 'share_poly';
49 | a.tabindex = 0;
50 | a.addEventListener('click',e=>{
51 | if (item.click) item.click(data);
52 | else window.open(a.href, 'share_poly', 'width=700,height=500');
53 | close();
54 | //shared = true;
55 | e.preventDefault();
56 | });
57 | body.append(a);
58 | });
59 | dialog.addEventListener('click', e => e.target === dialog && close() );
60 |
61 | // like the Chrome implementation, it resolves when the dialogue is opened. (not like safari)
62 | // now that we made the share function async, we dont need the promse anymore.
63 | // return new Promise((resolve)=>resolve());
64 | };
65 | share.items = new Map();
66 |
67 | share.items.set('E-Mail',{
68 | url: ({title, textUrl}) => 'mailto:?subject='+title+'&body='+textUrl,
69 | svg:'',
70 | });
71 | share.items.set('SMS',{
72 | url: ({titleTextUrl}) => 'sms:?body='+titleTextUrl,
73 | svg:'',
74 | });
75 | share.items.set('Copy',{
76 | click: data => navigator.clipboard.writeText(`${data.title}\n${data.text || ''}\n${data.url}`),
77 | svg:'',
78 | });
79 | share.items.set('Twitter',{
80 | url: ({titleText, url}) => 'https://twitter.com/intent/tweet?original_referer='+enc(location.href)+'&ref_src=twsrc%5Etfw&text='+titleText+'&tw_p=tweetbutton&url='+url,
81 | svg:'',
82 | });
83 | share.items.set('Facebook',{
84 | url: ({url, title}) => 'https://www.facebook.com/sharer/sharer.php?u='+url+'&t='+title,
85 | svg:'',
86 | });
87 | share.items.set('Telegram',{
88 | url: ({titleTextUrl}) => 'https://telegram.me/share/msg?url='+enc(location.host)+'&text=' + titleTextUrl,
89 | svg: ''
90 | });
91 | share.items.set('Pinterest',{
92 | url: ({url,titleText}) => 'https://pinterest.com/pin/create/button/?url='+url+'&xmedia='+'&description='+titleText,
93 | svg:'',
94 | });
95 | share.items.set('WhatsApp',{
96 | url: ({titleTextUrl}) => 'https://api.whatsapp.com/send?text='+titleTextUrl, //nativ: url: ({titleTextUrl}) => 'whatsapp://send?text='+titleTextUrl,
97 | svg:'',
98 | });
99 | share.items.set('LinkedIn',{
100 | url: ({title,text,url}) => 'https://www.linkedin.com/shareArticle?mini=true&url='+url+'&title='+title+'&summary='+text,
101 | svg:'',
102 | });
103 |
104 | if (!navigator.share) navigator.share = share;
105 | window.u1Share = share;
106 |
107 |
108 | const enc = encodeURIComponent;
109 |
110 | const style =
111 | '';
161 |
162 |
163 |
164 | // thanks: https://github.com/on2-dev/share-api-polyfill/blob/main/src/share.js
165 | const languages = {
166 | cs: {
167 | shareTitle: 'Sdílet',
168 | //cancel: 'Zrušit',
169 | Copy: 'Kopírovat',
170 | //print: 'Tisk',
171 | //selectSms: 'Vyberte kontakt'
172 | },
173 | sk: {
174 | shareTitle: 'Zdieľať',
175 | //cancel: 'Zrušiť',
176 | Copy: 'Kopírovat',
177 | //print: 'Tlač',
178 | //selectSms: 'Vyberte kontakt'
179 | },
180 | ja: {
181 | shareTitle: '共有する',
182 | //cancel: 'キャンセル',
183 | Copy: 'コピーする',
184 | //print: '印刷する',
185 | //selectSms: '連絡先を選択してください'
186 | },
187 | zh: {
188 | shareTitle: '分享',
189 | //cancel: '取消',
190 | Copy: '複製連結',
191 | //print: '列印',
192 | //selectSms: '選擇聯絡人'
193 | },
194 | pt: {
195 | shareTitle: 'Compartilhar',
196 | //cancel: 'Cancelar',
197 | Copy: 'Copiar',
198 | //print: 'Imprimir',
199 | //selectSms: 'Selecione um contato'
200 | },
201 | en: {
202 | shareTitle: 'Share',
203 | //cancel: 'Cancel',
204 | Copy: 'Copy',
205 | //print: 'Print',
206 | //selectSms: 'Pick a contact'
207 | },
208 | es: {
209 | shareTitle: 'Compartir',
210 | //cancel: 'Cancelar',
211 | Copy: 'Copiar',
212 | //print: 'Imprimir',
213 | 'E-Mail': 'Correo',
214 | //selectSms: 'Seleccionar un contacto'
215 | },
216 | fr: {
217 | shareTitle: 'Partager',
218 | //cancel: 'Annuler',
219 | Copy: 'Copier',
220 | //print: 'Imprimer',
221 | //selectSms: 'Veuillez choisir un contact'
222 | },
223 | de: {
224 | shareTitle: 'Teilen',
225 | //cancel: 'Abbrechen',
226 | Copy: 'Kopieren',
227 | //print: 'Drucken',
228 | //selectSms: 'Wählen Sie einen Kontakt aus'
229 | },
230 | it: {
231 | shareTitle: 'Condividi',
232 | //cancel: 'Annulla',
233 | Copy: 'Copia',
234 | //print: 'Stampa',
235 | 'E-Mail': 'Email',
236 | //selectSms: 'Seleziona un contatto'
237 | },
238 | nl: {
239 | shareTitle: 'Delen',
240 | //cancel: 'Annuleren',
241 | Copy: 'Kopiëren',
242 | //print: 'Printen',
243 | //selectSms: 'Selecteer een contact'
244 | },
245 | sv: {
246 | shareTitle: 'Dela',
247 | //cancel: 'Avbryt',
248 | Copy: 'Kopiera',
249 | //print: 'Skriv ut',
250 | //selectSms: 'Välj en kontakt'
251 | },
252 | da: {
253 | shareTitle: 'Del',
254 | //cancel: 'Luk',
255 | Copy: 'Kopiér',
256 | //print: 'Udskriv',
257 | //selectSms: 'Vælg en kontaktperson'
258 | },
259 | ru: {
260 | shareTitle: 'Поделиться',
261 | //cancel: 'Отмена',
262 | Copy: 'Скопировать',
263 | //print: 'Печать',
264 | 'E-Mail': 'Э-майл',
265 | //selectSms: 'Выбери контакт'
266 | },
267 | tr: {
268 | shareTitle: 'Paylaş',
269 | //cancel: 'Vazgeç',
270 | Copy: 'Kopyala',
271 | //print: 'Yazdır',
272 | 'E-Mail': 'E-posta',
273 | //selectSms: 'Bir kişi seç'
274 | },
275 | ko: {
276 | shareTitle: '공유',
277 | //cancel: '취소',
278 | Copy: '링크 복사',
279 | //print: '인쇄',
280 | //selectSms: '연락처를 선택하세요'
281 | },
282 | ta: {
283 | shareTitle: 'பகிர்',
284 | //cancel: 'இரத்து',
285 | Copy: 'நகலெடு',
286 | //print: 'அச்சிடு',
287 | 'E-Mail': 'மின்னஞ்சல்',
288 | //selectSms: 'ஒரு தொடர்பைத் தேர்வுசெய்க'
289 | },
290 | pl: {
291 | shareTitle: 'Dzielić',
292 | //cancel: 'Anuluj',
293 | Copy: 'Kopiuj',
294 | //print: 'Wydrukować',
295 | //selectSms: 'Wybierz kontakt'
296 | },
297 | is: {
298 | shareTitle: 'Deila',
299 | //cancel: 'Hætta við',
300 | Copy: 'Afrita',
301 | //print: 'Prenta',
302 | 'E-Mail': 'Póstur',
303 | //selectSms: 'Veldu tengilið'
304 | },
305 | hu: {
306 | shareTitle: 'Megosztás',
307 | //cancel: 'Bezárás',
308 | Copy: 'Másolás',
309 | //print: 'Nyomtatás',
310 | //selectSms: 'Válasszon egy kontaktot'
311 | },
312 | };
313 |
314 | const lang = navigator.language.substr(0, 2).toLowerCase();
315 | const txt = languages[lang] || languages['en'];
316 |
317 | }();
318 |
--------------------------------------------------------------------------------
/polyfills/navigator/share.test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | navigator.share
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
24 |
25 |
26 |
27 |
28 |
38 |
--------------------------------------------------------------------------------
/polyfills/requestIdleCallback.js:
--------------------------------------------------------------------------------
1 | if (!window.requestIdleCallback) {
2 | window.requestIdleCallback = function (callback, options) {
3 | var options = options || {};
4 | var relaxation = 1;
5 | var timeout = options.timeout || relaxation;
6 | var start = performance.now();
7 | return setTimeout(function () {
8 | callback({
9 | get didTimeout() {
10 | return options.timeout ? false : (performance.now() - start) - relaxation > timeout;
11 | },
12 | timeRemaining: function () {
13 | return Math.max(0, relaxation + (performance.now() - start));
14 | },
15 | });
16 | }, relaxation);
17 | };
18 | }
--------------------------------------------------------------------------------
/polyfills/tests/WeakRef.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | WeakRef test
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/polyfills/tests/structuredClone.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | WeakRef test
7 |
8 |
9 |
10 |
11 |
12 |
27 |
--------------------------------------------------------------------------------
/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | lazyfill TEST
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
79 |
80 |
81 |
82 |
83 |
86 |
87 |
88 |
89 |
92 |
93 |
94 |
95 |
inert
96 |
100 |
101 |
102 |
103 |
focusgroup
104 |
109 |
110 |
111 |
112 | inside search element.
113 | It sould be block and have a role=search
114 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------