source: trip-planner-front/node_modules/css-has-pseudo/index.mjs@ 1ad8e64

Last change on this file since 1ad8e64 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 4.5 KB
Line 
1function cssHasPseudo(document) {
2 const observedItems = []; // document.createAttribute() doesn't support `:` in the name. innerHTML does
3
4 const attributeElement = document.createElement('x'); // walk all stylesheets to collect observed css rules
5
6 [].forEach.call(document.styleSheets, walkStyleSheet);
7 transformObservedItems(); // observe DOM modifications that affect selectors
8
9 const mutationObserver = new MutationObserver(mutationsList => {
10 mutationsList.forEach(mutation => {
11 [].forEach.call(mutation.addedNodes || [], node => {
12 // walk stylesheets to collect observed css rules
13 if (node.nodeType === 1 && node.sheet) {
14 walkStyleSheet(node.sheet);
15 }
16 }); // transform observed css rules
17
18 cleanupObservedCssRules();
19 transformObservedItems();
20 });
21 });
22 mutationObserver.observe(document, {
23 childList: true,
24 subtree: true
25 }); // observe DOM events that affect pseudo-selectors
26
27 document.addEventListener('focus', transformObservedItems, true);
28 document.addEventListener('blur', transformObservedItems, true);
29 document.addEventListener('input', transformObservedItems); // transform observed css rules
30
31 function transformObservedItems() {
32 requestAnimationFrame(() => {
33 observedItems.forEach(item => {
34 const nodes = [];
35 [].forEach.call(document.querySelectorAll(item.scopeSelector), element => {
36 const nthChild = [].indexOf.call(element.parentNode.children, element) + 1;
37 const relativeSelectors = item.relativeSelectors.map(relativeSelector => item.scopeSelector + ':nth-child(' + nthChild + ') ' + relativeSelector).join(); // find any relative :has element from the :scope element
38
39 const relativeElement = element.parentNode.querySelector(relativeSelectors);
40 const shouldElementMatch = item.isNot ? !relativeElement : relativeElement;
41
42 if (shouldElementMatch) {
43 // memorize the node
44 nodes.push(element); // set an attribute with an irregular attribute name
45 // document.createAttribute() doesn't support special characters
46
47 attributeElement.innerHTML = '<x ' + item.attributeName + '>';
48 element.setAttributeNode(attributeElement.children[0].attributes[0].cloneNode()); // trigger a style refresh in IE and Edge
49
50 document.documentElement.style.zoom = 1;
51 document.documentElement.style.zoom = null;
52 }
53 }); // remove the encoded attribute from all nodes that no longer match them
54
55 item.nodes.forEach(node => {
56 if (nodes.indexOf(node) === -1) {
57 node.removeAttribute(item.attributeName); // trigger a style refresh in IE and Edge
58
59 document.documentElement.style.zoom = 1;
60 document.documentElement.style.zoom = null;
61 }
62 }); // update the
63
64 item.nodes = nodes;
65 });
66 });
67 } // remove any observed cssrules that no longer apply
68
69
70 function cleanupObservedCssRules() {
71 [].push.apply(observedItems, observedItems.splice(0).filter(item => item.rule.parentStyleSheet && item.rule.parentStyleSheet.ownerNode && document.documentElement.contains(item.rule.parentStyleSheet.ownerNode)));
72 } // walk a stylesheet to collect observed css rules
73
74
75 function walkStyleSheet(styleSheet) {
76 try {
77 // walk a css rule to collect observed css rules
78 [].forEach.call(styleSheet.cssRules || [], rule => {
79 if (rule.selectorText) {
80 // decode the selector text in all browsers to:
81 // [1] = :scope, [2] = :not(:has), [3] = :has relative, [4] = :scope relative
82 const selectors = decodeURIComponent(rule.selectorText.replace(/\\(.)/g, '$1')).match(/^(.*?)\[:(not-)?has\((.+?)\)\](.*?)$/);
83
84 if (selectors) {
85 const attributeName = ':' + (selectors[2] ? 'not-' : '') + 'has(' + // encode a :has() pseudo selector as an attribute name
86 encodeURIComponent(selectors[3]).replace(/%3A/g, ':').replace(/%5B/g, '[').replace(/%5D/g, ']').replace(/%2C/g, ',') + ')';
87 observedItems.push({
88 rule,
89 scopeSelector: selectors[1],
90 isNot: selectors[2],
91 relativeSelectors: selectors[3].split(/\s*,\s*/),
92 attributeName,
93 nodes: []
94 });
95 }
96 } else {
97 walkStyleSheet(rule);
98 }
99 });
100 } catch (error) {
101 /* do nothing and continue */
102 }
103 }
104}
105
106export default cssHasPseudo;
107//# sourceMappingURL=index.mjs.map
Note: See TracBrowser for help on using the repository browser.