mirror of
https://github.com/iconify/iconify.git
synced 2024-11-09 23:00:56 +00:00
Rebuild observer in SVG framework. Now it supports multiple root nodes
This commit is contained in:
parent
0266760091
commit
7645047431
14
packages/browser-tests/package-lock.json
generated
14
packages/browser-tests/package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@iconify/iconify-browser-tests",
|
"name": "@iconify/iconify-browser-tests",
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -11,9 +11,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@iconify/core": {
|
"@iconify/core": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.3",
|
||||||
"resolved": "https://registry.npmjs.org/@iconify/core/-/core-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/@iconify/core/-/core-1.0.0-beta.3.tgz",
|
||||||
"integrity": "sha512-PIPWM7Z0R8CClnl9kx8c3G8qe4gF+WGvro6IOcYRLw5YsVt0JyagGh5MgTHH8yfhMWlpAgiiROm65tJpKHctQw==",
|
"integrity": "sha512-VqdW1vu7uWBI4QhOijVbT4vxDUKLjGNOye7SbJxvB2XQpJIQe9ZKnNqIyX1fO1olSV+Zf4Y1CQhWjw/sOxW+sQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@cyberalien/redundancy": "^1.0.0",
|
"@cyberalien/redundancy": "^1.0.0",
|
||||||
@ -22,9 +22,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@iconify/iconify": {
|
"@iconify/iconify": {
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.4",
|
||||||
"resolved": "https://registry.npmjs.org/@iconify/iconify/-/iconify-2.0.0-beta.3.tgz",
|
"resolved": "https://registry.npmjs.org/@iconify/iconify/-/iconify-2.0.0-beta.4.tgz",
|
||||||
"integrity": "sha512-s+R3tKl+5+21Foj/JtODPtoAZmxCBt+NLTS0oTwDaibl8VFkomoPDuMPdT+twSVD7iJG81+MqERr0zTk8HyFfg==",
|
"integrity": "sha512-/uUDM3D2rYWa5JmfC9DIfoznGbodBwwsMcpMOyG5xx5vgMZzfJYrgBWA1kCT+ec5NJ3bcH2etZBzkLOVS3sJAA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@iconify/types": {
|
"@iconify/types": {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"description": "Browser tests for @iconify/iconify package",
|
"description": "Browser tests for @iconify/iconify package",
|
||||||
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.4",
|
||||||
"license": "(Apache-2.0 OR GPL-2.0)",
|
"license": "(Apache-2.0 OR GPL-2.0)",
|
||||||
"bugs": "https://github.com/iconify/iconify/issues",
|
"bugs": "https://github.com/iconify/iconify/issues",
|
||||||
"homepage": "https://iconify.design/",
|
"homepage": "https://iconify.design/",
|
||||||
@ -19,8 +19,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cyberalien/redundancy": "^1.0.0",
|
"@cyberalien/redundancy": "^1.0.0",
|
||||||
"@iconify/core": "^1.0.0-beta.2",
|
"@iconify/core": "^1.0.0-beta.3",
|
||||||
"@iconify/iconify": "^2.0.0-beta.3",
|
"@iconify/iconify": "^2.0.0-beta.4",
|
||||||
"@iconify/types": "^1.0.3",
|
"@iconify/types": "^1.0.3",
|
||||||
"@rollup/plugin-buble": "^0.21.1",
|
"@rollup/plugin-buble": "^0.21.1",
|
||||||
"@rollup/plugin-commonjs": "^11.0.2",
|
"@rollup/plugin-commonjs": "^11.0.2",
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import mocha from 'mocha';
|
import mocha from 'mocha';
|
||||||
import chai from 'chai';
|
import chai from 'chai';
|
||||||
|
|
||||||
import { getNode } from './node';
|
import { getNode, setRoot } from './node';
|
||||||
import { setRoot } from '@iconify/iconify/lib/modules/root';
|
import { listRootNodes } from '@iconify/iconify/lib/modules/root';
|
||||||
import {
|
import {
|
||||||
initObserver,
|
initObserver,
|
||||||
isObserverPaused,
|
|
||||||
pauseObserver,
|
pauseObserver,
|
||||||
} from '@iconify/iconify/lib/modules/observer';
|
} from '@iconify/iconify/lib/modules/observer';
|
||||||
|
|
||||||
@ -16,28 +15,40 @@ describe('Testing observer creation', () => {
|
|||||||
const node = getNode('observer-creation');
|
const node = getNode('observer-creation');
|
||||||
setRoot(node);
|
setRoot(node);
|
||||||
|
|
||||||
|
// Get node
|
||||||
|
const list = listRootNodes();
|
||||||
|
expect(list.length).to.be.equal(1);
|
||||||
|
|
||||||
|
const item = list[0];
|
||||||
|
expect(item.node).to.be.equal(node);
|
||||||
|
expect(item.observer).to.be.equal(void 0);
|
||||||
|
|
||||||
|
// Do test
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
|
|
||||||
node.innerHTML = '<div></div><ul><li>test</li><li>test2</li></ul>';
|
node.innerHTML = '<div></div><ul><li>test</li><li>test2</li></ul>';
|
||||||
initObserver((root) => {
|
initObserver((root) => {
|
||||||
expect(root).to.be.equal(node);
|
expect(root.node).to.be.equal(node);
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
|
|
||||||
// Should be called only once
|
// Should be called only once
|
||||||
expect(counter).to.be.equal(1);
|
expect(counter).to.be.equal(1);
|
||||||
|
|
||||||
expect(isObserverPaused()).to.be.equal(false);
|
// Check if observer is paused
|
||||||
|
expect(item.observer).to.not.be.equal(void 0);
|
||||||
|
expect(item.observer.paused).to.be.equal(0);
|
||||||
|
|
||||||
// Pause observer
|
// Pause observer
|
||||||
pauseObserver();
|
pauseObserver();
|
||||||
expect(isObserverPaused()).to.be.equal(true);
|
expect(item.observer.paused).to.be.equal(1);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add few nodes to trigger observer
|
// Add few nodes to trigger observer
|
||||||
expect(isObserverPaused()).to.be.equal(false);
|
expect(item.observer).to.not.be.equal(void 0);
|
||||||
|
expect(item.observer.paused).to.be.equal(0);
|
||||||
node.querySelector('div').innerHTML =
|
node.querySelector('div').innerHTML =
|
||||||
'<span class="test">Some text</span><i>!</i>';
|
'<span class="test">Some text</span><i>!</i>';
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import mocha from 'mocha';
|
import mocha from 'mocha';
|
||||||
import chai from 'chai';
|
import chai from 'chai';
|
||||||
|
|
||||||
import { getNode } from './node';
|
import { getNode, setRoot } from './node';
|
||||||
import { elementFinderProperty } from '@iconify/iconify/lib/modules/element';
|
import { elementFinderProperty } from '@iconify/iconify/lib/modules/element';
|
||||||
import { setRoot } from '@iconify/iconify/lib/modules/root';
|
|
||||||
import {
|
import {
|
||||||
initObserver,
|
initObserver,
|
||||||
pauseObserver,
|
pauseObserver,
|
||||||
resumeObserver,
|
resumeObserver,
|
||||||
isObserverPaused,
|
|
||||||
} from '@iconify/iconify/lib/modules/observer';
|
} from '@iconify/iconify/lib/modules/observer';
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
@ -24,7 +22,7 @@ describe('Testing observer with DOM manipulation', () => {
|
|||||||
node.innerHTML =
|
node.innerHTML =
|
||||||
'<div></div><ul><li>test</li><li>test2</li></ul><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg); vertical-align: -0.125em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24" data-icon="mdi-home" data-inline="false" class="iconify"><path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"></path></svg>';
|
'<div></div><ul><li>test</li><li>test2</li></ul><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg); vertical-align: -0.125em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24" data-icon="mdi-home" data-inline="false" class="iconify"><path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"></path></svg>';
|
||||||
initObserver((root) => {
|
initObserver((root) => {
|
||||||
expect(root).to.be.equal(node);
|
expect(root.node).to.be.equal(node);
|
||||||
expect(waitingCallback).to.be.equal(true);
|
expect(waitingCallback).to.be.equal(true);
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
@ -108,7 +106,6 @@ describe('Testing observer with DOM manipulation', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add few nodes to trigger observer
|
// Add few nodes to trigger observer
|
||||||
expect(isObserverPaused()).to.be.equal(false);
|
|
||||||
node.querySelector('div').innerHTML =
|
node.querySelector('div').innerHTML =
|
||||||
'<span class="test">Some text</span><i>!</i>';
|
'<span class="test">Some text</span><i>!</i>';
|
||||||
});
|
});
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import mocha from 'mocha';
|
import mocha from 'mocha';
|
||||||
import chai from 'chai';
|
import chai from 'chai';
|
||||||
|
|
||||||
import { getNode } from './node';
|
import { getNode, setRoot } from './node';
|
||||||
import { addFinder } from '@iconify/iconify/lib/modules/finder';
|
import { addFinder } from '@iconify/iconify/lib/modules/finder';
|
||||||
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
||||||
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
|
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
|
||||||
import { getStorage, addIconSet } from '@iconify/core/lib/storage';
|
import { getStorage, addIconSet } from '@iconify/core/lib/storage';
|
||||||
import { setRoot, getRootNodes } from '@iconify/iconify/lib/modules/root';
|
import { listRootNodes } from '@iconify/iconify/lib/modules/root';
|
||||||
import { scanDOM } from '@iconify/iconify/lib/modules/scanner';
|
import { scanDOM, scanElement } from '@iconify/iconify/lib/modules/scanner';
|
||||||
|
import { removeObservedNode } from '@iconify/iconify/lib/modules/observer';
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
@ -43,10 +44,12 @@ describe('Scanning DOM', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Sanity check before running tests
|
// Sanity check before running tests
|
||||||
expect(getRootNodes()).to.be.eql([]);
|
expect(listRootNodes()).to.be.eql([]);
|
||||||
|
|
||||||
it('Scan DOM with preloaded icons', () => {
|
it('Scan DOM with preloaded icons', () => {
|
||||||
const node = getNode('scan-dom');
|
const node = getNode('scan-dom');
|
||||||
|
setRoot(node);
|
||||||
|
|
||||||
node.innerHTML =
|
node.innerHTML =
|
||||||
'<div><p>Testing scanning DOM</p><ul>' +
|
'<div><p>Testing scanning DOM</p><ul>' +
|
||||||
'<li>Valid icons:' +
|
'<li>Valid icons:' +
|
||||||
@ -60,49 +63,66 @@ describe('Scanning DOM', () => {
|
|||||||
'</ul></div>';
|
'</ul></div>';
|
||||||
|
|
||||||
// Scan node
|
// Scan node
|
||||||
setRoot(node);
|
|
||||||
scanDOM();
|
scanDOM();
|
||||||
|
|
||||||
// Find elements
|
// Find elements
|
||||||
const elements = node.querySelectorAll('svg.iconify');
|
const elements = node.querySelectorAll('svg.iconify');
|
||||||
expect(elements.length).to.be.equal(4);
|
expect(elements.length).to.be.equal(4);
|
||||||
|
|
||||||
// Make sure tempoary node was not added as root, but new root node was
|
// Check root nodes list
|
||||||
expect(getRootNodes()).to.be.eql([
|
const nodes = listRootNodes();
|
||||||
{
|
expect(nodes.length).to.be.equal(1);
|
||||||
node: node,
|
expect(nodes[0].node).to.be.equal(node);
|
||||||
temporary: false,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Scan DOM with unattached root', () => {
|
it('Scan DOM with unattached root', () => {
|
||||||
|
const fakeNode = getNode('scan-dom');
|
||||||
|
setRoot(fakeNode);
|
||||||
|
|
||||||
const node = document.createElement('div');
|
const node = document.createElement('div');
|
||||||
|
|
||||||
node.innerHTML = '<span class="iconify" data-icon="mdi:home"></span>';
|
node.innerHTML = '<span class="iconify" data-icon="mdi:home"></span>';
|
||||||
|
|
||||||
// Get old root nodes. It should not be empty because of previous test(s)
|
// Check root nodes list
|
||||||
const oldRoot = getRootNodes();
|
let nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(1);
|
||||||
|
expect(nodes[0].node).to.be.equal(fakeNode);
|
||||||
|
|
||||||
// Scan node
|
// Scan node
|
||||||
scanDOM(node);
|
scanElement(node);
|
||||||
|
|
||||||
// Find elements
|
// Find elements
|
||||||
const elements = node.querySelectorAll('svg.iconify');
|
const elements = node.querySelectorAll('svg.iconify');
|
||||||
expect(elements.length).to.be.equal(1);
|
expect(elements.length).to.be.equal(1);
|
||||||
|
|
||||||
// Make sure tempoary node was not added as root
|
// Make sure tempoary node was not added as root
|
||||||
expect(getRootNodes()).to.be.eql(oldRoot);
|
nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(1);
|
||||||
|
expect(nodes[0].node).to.be.equal(fakeNode);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Scan DOM with icon as root', () => {
|
it('Scan DOM with icon as root', () => {
|
||||||
|
const fakeNode = getNode('scan-dom');
|
||||||
|
setRoot(fakeNode);
|
||||||
|
|
||||||
const node = document.createElement('span');
|
const node = document.createElement('span');
|
||||||
node.setAttribute('data-icon', 'mdi:home');
|
node.setAttribute('data-icon', 'mdi:home');
|
||||||
|
|
||||||
|
// Check root nodes list
|
||||||
|
let nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(1);
|
||||||
|
expect(nodes[0].node).to.be.equal(fakeNode);
|
||||||
|
|
||||||
// Scan node
|
// Scan node
|
||||||
scanDOM(node);
|
scanElement(node);
|
||||||
|
|
||||||
// Check node
|
// Check node
|
||||||
expect(node.tagName).to.be.equal('SPAN');
|
expect(node.tagName).to.be.equal('SPAN');
|
||||||
expect(node.innerHTML).to.be.equal('');
|
expect(node.innerHTML).to.be.equal('');
|
||||||
|
|
||||||
|
// Make sure tempoary node was not added as root
|
||||||
|
nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(1);
|
||||||
|
expect(nodes[0].node).to.be.equal(fakeNode);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import mocha from 'mocha';
|
import mocha from 'mocha';
|
||||||
import chai from 'chai';
|
import chai from 'chai';
|
||||||
|
|
||||||
import { getNode } from './node';
|
import { getNode, setRoot } from './node';
|
||||||
import { addFinder } from '@iconify/iconify/lib/modules/finder';
|
import { addFinder } from '@iconify/iconify/lib/modules/finder';
|
||||||
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
||||||
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
|
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
|
||||||
import { getStorage, addIconSet } from '@iconify/core/lib/storage';
|
import { getStorage, addIconSet } from '@iconify/core/lib/storage';
|
||||||
import { setRoot, getRootNodes } from '@iconify/iconify/lib/modules/root';
|
import { listRootNodes } from '@iconify/iconify/lib/modules/root';
|
||||||
import { scanDOM } from '@iconify/iconify/lib/modules/scanner';
|
import { scanDOM } from '@iconify/iconify/lib/modules/scanner';
|
||||||
import { initObserver } from '@iconify/iconify/lib/modules/observer';
|
import {
|
||||||
|
initObserver,
|
||||||
|
observeNode,
|
||||||
|
removeObservedNode,
|
||||||
|
} from '@iconify/iconify/lib/modules/observer';
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
@ -45,30 +49,38 @@ describe('Observe DOM', () => {
|
|||||||
|
|
||||||
it('Basic test', (done) => {
|
it('Basic test', (done) => {
|
||||||
const node = getNode('observe-dom');
|
const node = getNode('observe-dom');
|
||||||
|
const ignoredNode = getNode('observe-dom');
|
||||||
|
|
||||||
// Set root and init observer
|
// Set root and init observer
|
||||||
setRoot(node);
|
setRoot(node);
|
||||||
initObserver(scanDOM);
|
initObserver(scanDOM);
|
||||||
|
|
||||||
// Test getRootNodes
|
// Test listRootNodes
|
||||||
expect(getRootNodes()).to.be.eql([
|
const nodes = listRootNodes();
|
||||||
{
|
expect(nodes.length).to.be.equal(1);
|
||||||
node: node,
|
expect(nodes[0].node).to.be.equal(node);
|
||||||
temporary: false,
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Set HTML
|
// Set HTML
|
||||||
node.innerHTML =
|
node.innerHTML =
|
||||||
'<p>Testing observing DOM</p>' +
|
'<p>Testing observing DOM</p>' +
|
||||||
'<span class="iconify" data-icon="mdi:home"></span>';
|
'<span class="iconify" data-icon="mdi:home"></span>';
|
||||||
|
ignoredNode.innerHTML =
|
||||||
|
'<p>This node should be ignored</p>' +
|
||||||
|
'<span class="iconify" data-icon="mdi:home"></span>';
|
||||||
|
|
||||||
// Test nodes
|
// Test nodes
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Find elements
|
// Find elements
|
||||||
const elements = node.querySelectorAll('svg.iconify');
|
let elements = node.querySelectorAll('svg.iconify');
|
||||||
expect(elements.length).to.be.equal(1);
|
expect(elements.length).to.be.equal(1);
|
||||||
|
|
||||||
|
elements = ignoredNode.querySelectorAll('svg.iconify');
|
||||||
|
expect(elements.length).to.be.equal(
|
||||||
|
0,
|
||||||
|
'Looks like document.body is observed!'
|
||||||
|
);
|
||||||
|
|
||||||
// Test for "home" icon contents
|
// Test for "home" icon contents
|
||||||
expect(node.innerHTML.indexOf('20v-6h4v6h5v')).to.not.be.equal(-1);
|
expect(node.innerHTML.indexOf('20v-6h4v6h5v')).to.not.be.equal(-1);
|
||||||
|
|
||||||
@ -114,4 +126,112 @@ describe('Observe DOM', () => {
|
|||||||
}, 100);
|
}, 100);
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Adding node to observe', (done) => {
|
||||||
|
const baseNode = getNode('observe-dom');
|
||||||
|
const node = getNode('observe-dom');
|
||||||
|
|
||||||
|
// Set root and init observer
|
||||||
|
setRoot(baseNode);
|
||||||
|
initObserver(scanDOM);
|
||||||
|
|
||||||
|
// Test listRootNodes
|
||||||
|
let nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(1);
|
||||||
|
expect(nodes[0].node).to.be.equal(baseNode);
|
||||||
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
|
|
||||||
|
// Observe another node
|
||||||
|
observeNode(node);
|
||||||
|
|
||||||
|
nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(2);
|
||||||
|
expect(nodes[0].node).to.be.equal(baseNode);
|
||||||
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
|
expect(nodes[1].node).to.be.equal(node);
|
||||||
|
expect(nodes[1].temporary).to.be.equal(false);
|
||||||
|
|
||||||
|
// Set HTML
|
||||||
|
baseNode.innerHTML =
|
||||||
|
'<p>Testing observing 2 nodes (1)</p>' +
|
||||||
|
'<span class="iconify" data-icon="mdi:home"></span>';
|
||||||
|
node.innerHTML =
|
||||||
|
'<p>Testing observing 2 nodes (2)</p>' +
|
||||||
|
'<span class="iconify" data-icon="mdi:home"></span>';
|
||||||
|
|
||||||
|
// Test nodes
|
||||||
|
setTimeout(() => {
|
||||||
|
// Find elements
|
||||||
|
let elements = node.querySelectorAll('svg.iconify');
|
||||||
|
expect(elements.length).to.be.equal(1);
|
||||||
|
|
||||||
|
elements = baseNode.querySelectorAll('svg.iconify');
|
||||||
|
expect(elements.length).to.be.equal(1);
|
||||||
|
|
||||||
|
// Test for "home" icon contents
|
||||||
|
expect(node.innerHTML.indexOf('20v-6h4v6h5v')).to.not.be.equal(-1);
|
||||||
|
expect(baseNode.innerHTML.indexOf('20v-6h4v6h5v')).to.not.be.equal(
|
||||||
|
-1
|
||||||
|
);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Stop observing node', (done) => {
|
||||||
|
const baseNode = getNode('observe-dom');
|
||||||
|
const node = getNode('observe-dom');
|
||||||
|
|
||||||
|
// Set root and init observer
|
||||||
|
setRoot(baseNode);
|
||||||
|
initObserver(scanDOM);
|
||||||
|
|
||||||
|
// Test listRootNodes
|
||||||
|
let nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(1);
|
||||||
|
expect(nodes[0].node).to.be.equal(baseNode);
|
||||||
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
|
|
||||||
|
// Observe another node
|
||||||
|
observeNode(node);
|
||||||
|
|
||||||
|
nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(2);
|
||||||
|
expect(nodes[0].node).to.be.equal(baseNode);
|
||||||
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
|
expect(nodes[1].node).to.be.equal(node);
|
||||||
|
expect(nodes[1].temporary).to.be.equal(false);
|
||||||
|
|
||||||
|
// Stop observing baseNode
|
||||||
|
removeObservedNode(baseNode);
|
||||||
|
|
||||||
|
nodes = listRootNodes();
|
||||||
|
expect(nodes.length).to.be.equal(1);
|
||||||
|
expect(nodes[0].node).to.be.equal(node);
|
||||||
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
|
|
||||||
|
// Set HTML
|
||||||
|
baseNode.innerHTML =
|
||||||
|
'<p>Testing observing 2 nodes (1)</p>' +
|
||||||
|
'<span class="iconify" data-icon="mdi:home"></span>';
|
||||||
|
node.innerHTML =
|
||||||
|
'<p>Testing observing 2 nodes (2)</p>' +
|
||||||
|
'<span class="iconify" data-icon="mdi:home"></span>';
|
||||||
|
|
||||||
|
// Test nodes
|
||||||
|
setTimeout(() => {
|
||||||
|
// Find elements
|
||||||
|
let elements = node.querySelectorAll('svg.iconify');
|
||||||
|
expect(elements.length).to.be.equal(1);
|
||||||
|
|
||||||
|
elements = baseNode.querySelectorAll('svg.iconify');
|
||||||
|
expect(elements.length).to.be.equal(0);
|
||||||
|
|
||||||
|
// Test for "home" icon contents
|
||||||
|
expect(node.innerHTML.indexOf('20v-6h4v6h5v')).to.not.be.equal(-1);
|
||||||
|
expect(baseNode.innerHTML.indexOf('20v-6h4v6h5v')).to.be.equal(-1);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import mocha from 'mocha';
|
import mocha from 'mocha';
|
||||||
import chai from 'chai';
|
import chai from 'chai';
|
||||||
|
|
||||||
import { getNode } from './node';
|
import { getNode, setRoot } from './node';
|
||||||
import { addFinder } from '@iconify/iconify/lib/modules/finder';
|
import { addFinder } from '@iconify/iconify/lib/modules/finder';
|
||||||
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
|
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
|
||||||
import { API } from '@iconify/core/lib/api/';
|
import { API } from '@iconify/core/lib/api/';
|
||||||
@ -10,8 +10,8 @@ import { setAPIConfig } from '@iconify/core/lib/api/config';
|
|||||||
import { coreModules } from '@iconify/core/lib/modules';
|
import { coreModules } from '@iconify/core/lib/modules';
|
||||||
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
||||||
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
|
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
|
||||||
import { setRoot, getRootNodes } from '@iconify/iconify/lib/modules/root';
|
import { listRootNodes } from '@iconify/iconify/lib/modules/root';
|
||||||
import { scanDOM } from '@iconify/iconify/lib/modules/scanner';
|
import { scanDOM, scanElement } from '@iconify/iconify/lib/modules/scanner';
|
||||||
|
|
||||||
const expect = chai.expect;
|
const expect = chai.expect;
|
||||||
|
|
||||||
@ -86,6 +86,7 @@ describe('Scanning DOM with API', () => {
|
|||||||
setFakeData(provider, prefix2, data2);
|
setFakeData(provider, prefix2, data2);
|
||||||
|
|
||||||
const node = getNode('scan-dom');
|
const node = getNode('scan-dom');
|
||||||
|
|
||||||
node.innerHTML =
|
node.innerHTML =
|
||||||
'<div><p>Testing scanning DOM with API</p><ul>' +
|
'<div><p>Testing scanning DOM with API</p><ul>' +
|
||||||
'<li>Inline icons:' +
|
'<li>Inline icons:' +
|
||||||
@ -118,13 +119,11 @@ describe('Scanning DOM with API', () => {
|
|||||||
setRoot(node);
|
setRoot(node);
|
||||||
scanDOM();
|
scanDOM();
|
||||||
|
|
||||||
// Test getRootNodes
|
// Test listRootNodes
|
||||||
expect(getRootNodes()).to.be.eql([
|
const nodes = listRootNodes();
|
||||||
{
|
expect(nodes.length).to.be.equal(1);
|
||||||
node: node,
|
expect(nodes[0].node).to.be.equal(node);
|
||||||
temporary: false,
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// First API response should have loaded
|
// First API response should have loaded
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -253,13 +252,11 @@ describe('Scanning DOM with API', () => {
|
|||||||
setRoot(node);
|
setRoot(node);
|
||||||
scanDOM();
|
scanDOM();
|
||||||
|
|
||||||
// Test getRootNodes
|
// Test listRootNodes
|
||||||
expect(getRootNodes()).to.be.eql([
|
const nodes = listRootNodes();
|
||||||
{
|
expect(nodes.length).to.be.equal(1);
|
||||||
node: node,
|
expect(nodes[0].node).to.be.equal(node);
|
||||||
temporary: false,
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Make sure no icons were rendered yet
|
// Make sure no icons were rendered yet
|
||||||
const elements = node.querySelectorAll('svg.iconify');
|
const elements = node.querySelectorAll('svg.iconify');
|
||||||
@ -447,27 +444,22 @@ describe('Scanning DOM with API', () => {
|
|||||||
|
|
||||||
// Set root node, test nodes list
|
// Set root node, test nodes list
|
||||||
setRoot(fakeRoot);
|
setRoot(fakeRoot);
|
||||||
expect(getRootNodes()).to.be.eql([
|
|
||||||
{
|
// Test listRootNodes
|
||||||
node: fakeRoot,
|
let nodes = listRootNodes();
|
||||||
temporary: false,
|
expect(nodes.length).to.be.equal(1);
|
||||||
},
|
expect(nodes[0].node).to.be.equal(fakeRoot);
|
||||||
]);
|
expect(nodes[0].temporary).to.be.equal(false);
|
||||||
|
|
||||||
// Scan different node
|
// Scan different node
|
||||||
scanDOM(node);
|
scanElement(node);
|
||||||
|
|
||||||
// Test nodes list
|
// Test listRootNodes
|
||||||
expect(getRootNodes()).to.be.eql([
|
nodes = listRootNodes();
|
||||||
{
|
expect(nodes.length).to.be.equal(2);
|
||||||
node: fakeRoot,
|
expect(nodes[0].node).to.be.equal(fakeRoot);
|
||||||
temporary: false,
|
expect(nodes[1].node).to.be.equal(node);
|
||||||
},
|
expect(nodes[1].temporary).to.be.equal(true);
|
||||||
{
|
|
||||||
node: node,
|
|
||||||
temporary: true,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// API response should have loaded
|
// API response should have loaded
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -478,12 +470,9 @@ describe('Scanning DOM with API', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Test nodes list: temporary node should have been removed
|
// Test nodes list: temporary node should have been removed
|
||||||
expect(getRootNodes()).to.be.eql([
|
nodes = listRootNodes();
|
||||||
{
|
expect(nodes.length).to.be.equal(1);
|
||||||
node: fakeRoot,
|
expect(nodes[0].node).to.be.equal(fakeRoot);
|
||||||
temporary: false,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
done();
|
done();
|
||||||
|
@ -9,10 +9,16 @@ const expect = chai.expect;
|
|||||||
const selector =
|
const selector =
|
||||||
'span.iconify, i.iconify, span.iconify-inline, i.iconify-inline';
|
'span.iconify, i.iconify, span.iconify-inline, i.iconify-inline';
|
||||||
|
|
||||||
const node = getNode('iconify-api');
|
// Do not observe document.body!
|
||||||
Iconify.setRoot(node);
|
Iconify.stopObserving(document.body);
|
||||||
|
|
||||||
node.innerHTML =
|
// Create node to observe
|
||||||
|
const observedNode = getNode('iconify-api');
|
||||||
|
const ignoredNode = getNode('iconify-api');
|
||||||
|
|
||||||
|
Iconify.observe(observedNode);
|
||||||
|
|
||||||
|
observedNode.innerHTML =
|
||||||
'<div><p>Testing Iconify with API</p><ul>' +
|
'<div><p>Testing Iconify with API</p><ul>' +
|
||||||
'<li>Inline icons:' +
|
'<li>Inline icons:' +
|
||||||
' <span class="iconify-inline" data-icon="mdi:home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
' <span class="iconify-inline" data-icon="mdi:home" style="color: red; box-shadow: 0 0 2px black;"></span>' +
|
||||||
@ -24,13 +30,23 @@ node.innerHTML =
|
|||||||
'</li>' +
|
'</li>' +
|
||||||
'</ul></div>';
|
'</ul></div>';
|
||||||
|
|
||||||
describe('Testing Iconify object', () => {
|
ignoredNode.innerHTML =
|
||||||
|
'<div>This node should not have icons! <span class="iconify-inline" data-icon="mdi:home" style="color: red; box-shadow: 0 0 2px black;"></span>';
|
||||||
|
|
||||||
|
describe('Testing Iconify object with API', () => {
|
||||||
it('Rendering icons with API', () => {
|
it('Rendering icons with API', () => {
|
||||||
// Icons should have been replaced by now
|
// Icons should have been replaced by now
|
||||||
let list = node.querySelectorAll(selector);
|
let list = observedNode.querySelectorAll(selector);
|
||||||
expect(list.length).to.be.equal(0);
|
expect(list.length).to.be.equal(0);
|
||||||
|
|
||||||
list = node.querySelectorAll('svg.iconify');
|
list = observedNode.querySelectorAll('svg.iconify');
|
||||||
expect(list.length).to.be.equal(4);
|
expect(list.length).to.be.equal(4);
|
||||||
|
|
||||||
|
// Icons in ignored node should not have been replaced
|
||||||
|
list = ignoredNode.querySelectorAll(selector);
|
||||||
|
expect(list.length).to.be.equal(1);
|
||||||
|
|
||||||
|
list = ignoredNode.querySelectorAll('svg.iconify');
|
||||||
|
expect(list.length).to.be.equal(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -12,8 +12,11 @@ const selector =
|
|||||||
const node1 = getNode('iconify-basic');
|
const node1 = getNode('iconify-basic');
|
||||||
const node2 = getNode('iconify-basic');
|
const node2 = getNode('iconify-basic');
|
||||||
|
|
||||||
|
// Do not observe document.body!
|
||||||
|
Iconify.stopObserving(document.body);
|
||||||
|
|
||||||
// Set root node
|
// Set root node
|
||||||
Iconify.setRoot(node1);
|
Iconify.observe(node1);
|
||||||
|
|
||||||
describe('Testing Iconify object', () => {
|
describe('Testing Iconify object', () => {
|
||||||
const prefix = 'invalid-' + Date.now();
|
const prefix = 'invalid-' + Date.now();
|
||||||
|
@ -12,8 +12,11 @@ const selector =
|
|||||||
const node1 = getNode('iconify-basic');
|
const node1 = getNode('iconify-basic');
|
||||||
const node2 = getNode('iconify-basic');
|
const node2 = getNode('iconify-basic');
|
||||||
|
|
||||||
|
// Do not observe document.body!
|
||||||
|
Iconify.stopObserving(document.body);
|
||||||
|
|
||||||
// Set root node
|
// Set root node
|
||||||
Iconify.setRoot(node1);
|
Iconify.observe(node1);
|
||||||
|
|
||||||
describe('Testing Iconify object (without API)', () => {
|
describe('Testing Iconify object (without API)', () => {
|
||||||
const prefix = 'invalid-' + Date.now();
|
const prefix = 'invalid-' + Date.now();
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import { addRootNode, listRootNodes } from '@iconify/iconify/lib/modules/root';
|
||||||
|
import { removeObservedNode } from '@iconify/iconify/lib/modules/observer';
|
||||||
|
import { ObservedNode } from '@iconify/iconify/lib/modules/observed-node';
|
||||||
|
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,3 +16,15 @@ export function getNode(prefix = 'test') {
|
|||||||
document.getElementById('debug').appendChild(node);
|
document.getElementById('debug').appendChild(node);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set root node, remove old nodes
|
||||||
|
*/
|
||||||
|
export function setRoot(node: HTMLElement): ObservedNode {
|
||||||
|
listRootNodes().forEach((node) => {
|
||||||
|
if (typeof node.node !== 'function') {
|
||||||
|
removeObservedNode(node.node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return addRootNode(node);
|
||||||
|
}
|
||||||
|
2
packages/core/package-lock.json
generated
2
packages/core/package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@iconify/core",
|
"name": "@iconify/core",
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "@iconify/core",
|
"name": "@iconify/core",
|
||||||
"description": "Reusable files used by multiple Iconify packages",
|
"description": "Reusable files used by multiple Iconify packages",
|
||||||
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.3",
|
||||||
"license": "(Apache-2.0 OR GPL-2.0)",
|
"license": "(Apache-2.0 OR GPL-2.0)",
|
||||||
"bugs": "https://github.com/iconify/iconify/issues",
|
"bugs": "https://github.com/iconify/iconify/issues",
|
||||||
"homepage": "https://iconify.design/",
|
"homepage": "https://iconify.design/",
|
||||||
|
@ -21,13 +21,13 @@ Iconify SVG framework is designed to be as easy to use as possible.
|
|||||||
Add this line to your page to load Iconify SVG framework (you can add it to `<head>` section of the page or before `</body>`):
|
Add this line to your page to load Iconify SVG framework (you can add it to `<head>` section of the page or before `</body>`):
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://code.iconify.design/2/2.0.0-beta.3/iconify.min.js"></script>
|
<script src="https://code.iconify.design/2/2.0.0-beta.4/iconify.min.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@2.0.0-beta.3/dist/iconify.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@iconify/iconify@2.0.0-beta.4/dist/iconify.min.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
or, if you are building a project with something like WebPack or Rollup, you can include the script by installing `@iconify/iconify` as a dependency and importing it in your project:
|
or, if you are building a project with something like WebPack or Rollup, you can include the script by installing `@iconify/iconify` as a dependency and importing it in your project:
|
||||||
|
8
packages/iconify/package-lock.json
generated
8
packages/iconify/package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@iconify/iconify",
|
"name": "@iconify/iconify",
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -31,9 +31,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@iconify/core": {
|
"@iconify/core": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.3",
|
||||||
"resolved": "https://registry.npmjs.org/@iconify/core/-/core-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/@iconify/core/-/core-1.0.0-beta.3.tgz",
|
||||||
"integrity": "sha512-PIPWM7Z0R8CClnl9kx8c3G8qe4gF+WGvro6IOcYRLw5YsVt0JyagGh5MgTHH8yfhMWlpAgiiROm65tJpKHctQw==",
|
"integrity": "sha512-VqdW1vu7uWBI4QhOijVbT4vxDUKLjGNOye7SbJxvB2XQpJIQe9ZKnNqIyX1fO1olSV+Zf4Y1CQhWjw/sOxW+sQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@cyberalien/redundancy": "^1.0.0",
|
"@cyberalien/redundancy": "^1.0.0",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "@iconify/iconify",
|
"name": "@iconify/iconify",
|
||||||
"description": "Unified SVG framework with over 50,000 icons to choose from",
|
"description": "Unified SVG framework with over 50,000 icons to choose from",
|
||||||
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
||||||
"version": "2.0.0-beta.3",
|
"version": "2.0.0-beta.4",
|
||||||
"license": "(Apache-2.0 OR GPL-2.0)",
|
"license": "(Apache-2.0 OR GPL-2.0)",
|
||||||
"main": "./dist/iconify.min.js",
|
"main": "./dist/iconify.min.js",
|
||||||
"types": "./dist/iconify.d.ts",
|
"types": "./dist/iconify.d.ts",
|
||||||
@ -24,7 +24,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cyberalien/redundancy": "^1.0.0",
|
"@cyberalien/redundancy": "^1.0.0",
|
||||||
"@iconify/core": "^1.0.0-beta.2",
|
"@iconify/core": "^1.0.0-beta.3",
|
||||||
"@iconify/types": "^1.0.3",
|
"@iconify/types": "^1.0.3",
|
||||||
"@microsoft/api-extractor": "^7.9.2",
|
"@microsoft/api-extractor": "^7.9.2",
|
||||||
"@rollup/plugin-buble": "^0.21.3",
|
"@rollup/plugin-buble": "^0.21.3",
|
||||||
|
@ -25,13 +25,16 @@ import {
|
|||||||
initObserver,
|
initObserver,
|
||||||
pauseObserver,
|
pauseObserver,
|
||||||
resumeObserver,
|
resumeObserver,
|
||||||
|
observeNode,
|
||||||
|
removeObservedNode,
|
||||||
} from './modules/observer';
|
} from './modules/observer';
|
||||||
import { scanDOM } from './modules/scanner';
|
import { scanDOM, scanElement } from './modules/scanner';
|
||||||
|
|
||||||
// Finders
|
// Finders
|
||||||
import { addFinder } from './modules/finder';
|
import { addFinder } from './modules/finder';
|
||||||
import { finder as iconifyFinder } from './finders/iconify';
|
import { finder as iconifyFinder } from './finders/iconify';
|
||||||
import { setRoot } from './modules/root';
|
import { findRootNode, addRootNode, addBodyNode } from './modules/root';
|
||||||
|
import { onReady } from './modules/ready';
|
||||||
// import { finder as iconifyIconFinder } from './finders/iconify-icon';
|
// import { finder as iconifyIconFinder } from './finders/iconify-icon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,23 +197,28 @@ export interface IconifyGlobal {
|
|||||||
/**
|
/**
|
||||||
* Scan DOM
|
* Scan DOM
|
||||||
*/
|
*/
|
||||||
scanDOM: typeof scanDOM;
|
scan: (root?: HTMLElement) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set root node
|
* Add root node
|
||||||
*/
|
*/
|
||||||
setRoot: (root: HTMLElement) => void;
|
observe: (root: HTMLElement) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove root node
|
||||||
|
*/
|
||||||
|
stopObserving: (root: HTMLElement) => void;
|
||||||
|
|
||||||
/* Observer */
|
/* Observer */
|
||||||
/**
|
/**
|
||||||
* Pause observer
|
* Pause observer
|
||||||
*/
|
*/
|
||||||
pauseObserver: typeof pauseObserver;
|
pauseObserver: (root?: HTMLElement) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume observer
|
* Resume observer
|
||||||
*/
|
*/
|
||||||
resumeObserver: typeof resumeObserver;
|
resumeObserver: (root?: HTMLElement) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -296,30 +304,56 @@ export const IconifyCommon: IconifyGlobal = {
|
|||||||
replaceIDs,
|
replaceIDs,
|
||||||
|
|
||||||
// Scan DOM
|
// Scan DOM
|
||||||
scanDOM,
|
scan: (root?: HTMLElement) => {
|
||||||
|
if (root) {
|
||||||
|
scanElement(root);
|
||||||
|
} else {
|
||||||
|
scanDOM();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Set root node
|
// Add root node
|
||||||
setRoot: (root: HTMLElement) => {
|
observe: (root: HTMLElement) => {
|
||||||
setRoot(root);
|
observeNode(root);
|
||||||
|
},
|
||||||
|
|
||||||
// Restart observer
|
// Remove root node
|
||||||
initObserver(scanDOM);
|
stopObserving: (root: HTMLElement) => {
|
||||||
|
removeObservedNode(root);
|
||||||
// Scan DOM on next tick
|
|
||||||
setTimeout(scanDOM);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Pause observer
|
// Pause observer
|
||||||
pauseObserver,
|
pauseObserver: (root?: HTMLElement) => {
|
||||||
|
if (root) {
|
||||||
|
const node = findRootNode(root);
|
||||||
|
if (node) {
|
||||||
|
pauseObserver(node);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pauseObserver();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Resume observer
|
// Resume observer
|
||||||
resumeObserver,
|
resumeObserver: (root?: HTMLElement) => {
|
||||||
|
if (root) {
|
||||||
|
const node = findRootNode(root);
|
||||||
|
if (node) {
|
||||||
|
resumeObserver(node);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resumeObserver();
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise stuff
|
* Initialise stuff
|
||||||
*/
|
*/
|
||||||
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
||||||
|
// Add document.body node
|
||||||
|
addBodyNode();
|
||||||
|
|
||||||
// Add finder modules
|
// Add finder modules
|
||||||
// addFinder(iconifyIconFinder);
|
// addFinder(iconifyIconFinder);
|
||||||
addFinder(iconifyFinder);
|
addFinder(iconifyFinder);
|
||||||
@ -362,7 +396,7 @@ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
|||||||
|
|
||||||
// Load observer and scan DOM on next tick
|
// Load observer and scan DOM on next tick
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
scanDOM();
|
|
||||||
initObserver(scanDOM);
|
initObserver(scanDOM);
|
||||||
|
scanDOM();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
27
packages/iconify/src/modules/observed-node.ts
Normal file
27
packages/iconify/src/modules/observed-node.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Callback
|
||||||
|
*/
|
||||||
|
export type GetHTMLElement = () => HTMLElement | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observed node type
|
||||||
|
*/
|
||||||
|
export interface ObservedNode {
|
||||||
|
// Node
|
||||||
|
node: HTMLElement | GetHTMLElement;
|
||||||
|
|
||||||
|
// True if node should be removed when all placeholders have been replaced
|
||||||
|
temporary?: boolean;
|
||||||
|
|
||||||
|
// Observer data
|
||||||
|
observer?: {
|
||||||
|
// MutationObserver instance
|
||||||
|
instance?: MutationObserver;
|
||||||
|
|
||||||
|
// Number instead of boolean to allow multiple pause/resume calls. Observer is resumed only when pause reaches 0
|
||||||
|
paused: number;
|
||||||
|
|
||||||
|
// Timer for pending scan
|
||||||
|
pendingScan?: number;
|
||||||
|
};
|
||||||
|
}
|
@ -1,15 +1,17 @@
|
|||||||
import { elementFinderProperty, IconifyElement } from './element';
|
import { elementFinderProperty, IconifyElement } from './element';
|
||||||
import { getRoot } from './root';
|
import { ObservedNode } from './observed-node';
|
||||||
|
import {
|
||||||
/**
|
listRootNodes,
|
||||||
* MutationObserver instance, null until DOM is ready
|
addRootNode,
|
||||||
*/
|
findRootNode,
|
||||||
let instance: MutationObserver | null = null;
|
removeRootNode,
|
||||||
|
} from './root';
|
||||||
|
import { onReady } from './ready';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observer callback function
|
* Observer callback function
|
||||||
*/
|
*/
|
||||||
export type ObserverCallback = (root: HTMLElement) => void;
|
export type ObserverCallback = (item: ObservedNode) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback
|
* Callback
|
||||||
@ -25,32 +27,20 @@ const observerParams: MutationObserverInit = {
|
|||||||
attributes: true,
|
attributes: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Pause. Number instead of boolean to allow multiple pause/resume calls. Observer is resumed only when pause reaches 0
|
|
||||||
*/
|
|
||||||
let paused = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scan is pending when observer is resumed
|
|
||||||
*/
|
|
||||||
let scanPending = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scan is already queued
|
|
||||||
*/
|
|
||||||
let scanQueued = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue DOM scan
|
* Queue DOM scan
|
||||||
*/
|
*/
|
||||||
function queueScan(): void {
|
function queueScan(node: ObservedNode): void {
|
||||||
if (!scanQueued) {
|
if (!node.observer) {
|
||||||
scanQueued = true;
|
return;
|
||||||
setTimeout(() => {
|
}
|
||||||
scanQueued = false;
|
|
||||||
scanPending = false;
|
const observer = node.observer;
|
||||||
|
if (!observer.pendingScan) {
|
||||||
|
observer.pendingScan = setTimeout(() => {
|
||||||
|
delete observer.pendingScan;
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(getRoot());
|
callback(node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -59,8 +49,13 @@ function queueScan(): void {
|
|||||||
/**
|
/**
|
||||||
* Check mutations for added nodes
|
* Check mutations for added nodes
|
||||||
*/
|
*/
|
||||||
function checkMutations(mutations: MutationRecord[]): void {
|
function checkMutations(node: ObservedNode, mutations: MutationRecord[]): void {
|
||||||
if (!scanPending) {
|
if (!node.observer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = node.observer;
|
||||||
|
if (!observer.pendingScan) {
|
||||||
for (let i = 0; i < mutations.length; i++) {
|
for (let i = 0; i < mutations.length; i++) {
|
||||||
const item = mutations[i];
|
const item = mutations[i];
|
||||||
if (
|
if (
|
||||||
@ -71,9 +66,8 @@ function checkMutations(mutations: MutationRecord[]): void {
|
|||||||
(item.target as IconifyElement)[elementFinderProperty] !==
|
(item.target as IconifyElement)[elementFinderProperty] !==
|
||||||
void 0)
|
void 0)
|
||||||
) {
|
) {
|
||||||
scanPending = true;
|
if (!observer.paused) {
|
||||||
if (!paused) {
|
queueScan(node);
|
||||||
queueScan();
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -84,108 +78,173 @@ function checkMutations(mutations: MutationRecord[]): void {
|
|||||||
/**
|
/**
|
||||||
* Start/resume observer
|
* Start/resume observer
|
||||||
*/
|
*/
|
||||||
function observe(): void {
|
function observe(node: ObservedNode, root: HTMLElement): void {
|
||||||
if (instance) {
|
node.observer.instance.observe(root, observerParams);
|
||||||
instance.observe(getRoot(), observerParams);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start mutation observer
|
* Start mutation observer
|
||||||
*/
|
*/
|
||||||
function startObserver(): void {
|
function startObserver(node: ObservedNode): void {
|
||||||
if (instance !== null) {
|
let observer = node.observer;
|
||||||
|
if (observer && observer.instance) {
|
||||||
|
// Already started
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scanPending = true;
|
const root = typeof node.node === 'function' ? node.node() : node.node;
|
||||||
instance = new MutationObserver(checkMutations);
|
if (!root) {
|
||||||
observe();
|
// document.body is not available yet
|
||||||
if (!paused) {
|
return;
|
||||||
queueScan();
|
}
|
||||||
|
|
||||||
|
if (!observer) {
|
||||||
|
observer = {
|
||||||
|
paused: 0,
|
||||||
|
};
|
||||||
|
node.observer = observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new instance, observe
|
||||||
|
observer.instance = new MutationObserver(checkMutations.bind(null, node));
|
||||||
|
observe(node, root);
|
||||||
|
|
||||||
|
// Scan immediately
|
||||||
|
if (!observer.paused) {
|
||||||
|
queueScan(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fake interface to test old IE properties
|
/**
|
||||||
interface OldIEElement extends HTMLElement {
|
* Start all observers
|
||||||
doScroll?: boolean;
|
*/
|
||||||
|
function startObservers(): void {
|
||||||
|
listRootNodes().forEach(startObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export module
|
* Stop observer
|
||||||
*/
|
*/
|
||||||
|
function stopObserver(node: ObservedNode): void {
|
||||||
|
if (!node.observer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = node.observer;
|
||||||
|
|
||||||
|
// Stop scan
|
||||||
|
if (observer.pendingScan) {
|
||||||
|
clearTimeout(observer.pendingScan);
|
||||||
|
delete observer.pendingScan;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect observer
|
||||||
|
if (observer.instance) {
|
||||||
|
observer.instance.disconnect();
|
||||||
|
delete observer.instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start observer when DOM is ready
|
* Start observer when DOM is ready
|
||||||
*/
|
*/
|
||||||
export function initObserver(cb: ObserverCallback): void {
|
export function initObserver(cb: ObserverCallback): void {
|
||||||
callback = cb;
|
let isRestart = callback !== void 0;
|
||||||
|
|
||||||
if (instance && !paused) {
|
if (callback !== cb) {
|
||||||
// Restart observer
|
// Change callback and stop all pending observers
|
||||||
instance.disconnect();
|
callback = cb;
|
||||||
observe();
|
if (isRestart) {
|
||||||
|
listRootNodes().forEach(stopObserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRestart) {
|
||||||
|
// Restart instances
|
||||||
|
startObservers();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
// Start observers when document is ready
|
||||||
const doc = document;
|
onReady(startObservers);
|
||||||
if (
|
|
||||||
doc.readyState === 'complete' ||
|
|
||||||
(doc.readyState !== 'loading' &&
|
|
||||||
!(doc.documentElement as OldIEElement).doScroll)
|
|
||||||
) {
|
|
||||||
startObserver();
|
|
||||||
} else {
|
|
||||||
doc.addEventListener('DOMContentLoaded', startObserver);
|
|
||||||
window.addEventListener('load', startObserver);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause observer
|
* Pause observer
|
||||||
*/
|
*/
|
||||||
export function pauseObserver(root?: HTMLElement): void {
|
export function pauseObserver(node?: ObservedNode): void {
|
||||||
if (root && getRoot() !== root) {
|
(node ? [node] : listRootNodes()).forEach((node) => {
|
||||||
// Invalid root node
|
if (!node.observer) {
|
||||||
return;
|
node.observer = {
|
||||||
}
|
paused: 1,
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
paused++;
|
const observer = node.observer;
|
||||||
if (paused > 1 || instance === null) {
|
observer.paused++;
|
||||||
return;
|
if (observer.paused > 1 || !observer.instance) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check pending records, stop observer
|
// Disconnect observer
|
||||||
checkMutations(instance.takeRecords());
|
const instance = observer.instance;
|
||||||
instance.disconnect();
|
// checkMutations(node, instance.takeRecords());
|
||||||
|
instance.disconnect();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume observer
|
* Resume observer
|
||||||
*/
|
*/
|
||||||
export function resumeObserver(root?: HTMLElement): void {
|
export function resumeObserver(observer?: ObservedNode): void {
|
||||||
if (root && getRoot() !== root) {
|
(observer ? [observer] : listRootNodes()).forEach((node) => {
|
||||||
// Invalid root node
|
if (!node.observer) {
|
||||||
return;
|
// Start observer
|
||||||
}
|
startObserver(node);
|
||||||
|
return;
|
||||||
if (!paused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
paused--;
|
|
||||||
|
|
||||||
if (!paused && instance) {
|
|
||||||
observe();
|
|
||||||
if (scanPending) {
|
|
||||||
queueScan();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
const observer = node.observer;
|
||||||
|
if (observer.paused) {
|
||||||
|
observer.paused--;
|
||||||
|
|
||||||
|
if (!observer.paused) {
|
||||||
|
// Start / resume
|
||||||
|
const root =
|
||||||
|
typeof node.node === 'function' ? node.node() : node.node;
|
||||||
|
|
||||||
|
if (!root) {
|
||||||
|
return;
|
||||||
|
} else if (observer.instance) {
|
||||||
|
observe(node, root);
|
||||||
|
} else {
|
||||||
|
startObserver(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if observer is paused
|
* Observe node
|
||||||
*/
|
*/
|
||||||
export function isObserverPaused(): boolean {
|
export function observeNode(
|
||||||
return paused > 0;
|
root: HTMLElement,
|
||||||
|
autoRemove = false
|
||||||
|
): ObservedNode {
|
||||||
|
const node = addRootNode(root, autoRemove);
|
||||||
|
startObserver(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove observed node
|
||||||
|
*/
|
||||||
|
export function removeObservedNode(root: HTMLElement): void {
|
||||||
|
const node = findRootNode(root);
|
||||||
|
if (node) {
|
||||||
|
stopObserver(node);
|
||||||
|
removeRootNode(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
21
packages/iconify/src/modules/ready.ts
Normal file
21
packages/iconify/src/modules/ready.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Fake interface to test old IE properties
|
||||||
|
interface OldIEElement extends HTMLElement {
|
||||||
|
doScroll?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute function when DOM is ready
|
||||||
|
*/
|
||||||
|
export function onReady(callback): void {
|
||||||
|
const doc = document;
|
||||||
|
if (
|
||||||
|
doc.readyState === 'complete' ||
|
||||||
|
(doc.readyState !== 'loading' &&
|
||||||
|
!(doc.documentElement as OldIEElement).doScroll)
|
||||||
|
) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
doc.addEventListener('DOMContentLoaded', callback);
|
||||||
|
window.addEventListener('load', callback);
|
||||||
|
}
|
||||||
|
}
|
@ -1,80 +1,77 @@
|
|||||||
// Default root element
|
import { ObservedNode } from './observed-node';
|
||||||
let root: HTMLElement;
|
|
||||||
|
|
||||||
// Interface for extra root nodes
|
|
||||||
export interface ExtraRootNode {
|
|
||||||
node: HTMLElement;
|
|
||||||
temporary: boolean; // True if node should be removed when all placeholders have been replaced
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additional root elements
|
|
||||||
let customRoot: ExtraRootNode[] = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get root element
|
* List of root nodes
|
||||||
*/
|
*/
|
||||||
export function getRoot(): HTMLElement {
|
let nodes: ObservedNode[] = [];
|
||||||
return root ? root : (document.querySelector('body') as HTMLElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set root element
|
* Find node
|
||||||
*/
|
*/
|
||||||
export function setRoot(node: HTMLElement): void {
|
export function findRootNode(node: HTMLElement): ObservedNode | undefined {
|
||||||
root = node;
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
const item = nodes[i];
|
||||||
|
let root = typeof item.node === 'function' ? item.node() : item.node;
|
||||||
|
if (root === node) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add extra root node
|
* Add extra root node
|
||||||
*/
|
*/
|
||||||
export function addRoot(node: HTMLElement, autoRemove = false): ExtraRootNode {
|
export function addRootNode(
|
||||||
if (root === node) {
|
root: HTMLElement,
|
||||||
return {
|
autoRemove = false
|
||||||
node: root,
|
): ObservedNode {
|
||||||
temporary: false,
|
let node = findRootNode(root);
|
||||||
};
|
if (node) {
|
||||||
}
|
// Node already exist: switch type if needed
|
||||||
|
if (node.temporary) {
|
||||||
for (let i = 0; i < customRoot.length; i++) {
|
node.temporary = autoRemove;
|
||||||
const item = customRoot[i];
|
|
||||||
if (item.node === node) {
|
|
||||||
// Found matching node
|
|
||||||
if (!autoRemove && item.temporary) {
|
|
||||||
// Change to permanent
|
|
||||||
item.temporary = false;
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add item
|
// Create item, add it to list, start observer
|
||||||
const item = {
|
node = {
|
||||||
node,
|
node: root,
|
||||||
temporary: autoRemove,
|
temporary: autoRemove,
|
||||||
};
|
};
|
||||||
customRoot.push(item);
|
nodes.push(node);
|
||||||
|
|
||||||
return item;
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add document.body node
|
||||||
|
*/
|
||||||
|
export function addBodyNode(): ObservedNode {
|
||||||
|
if (document.body) {
|
||||||
|
return addRootNode(document.body);
|
||||||
|
}
|
||||||
|
nodes.push({
|
||||||
|
node: () => {
|
||||||
|
return document.body;
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove root node
|
* Remove root node
|
||||||
*/
|
*/
|
||||||
export function removeRoot(node: HTMLElement): void {
|
export function removeRootNode(root: HTMLElement): void {
|
||||||
customRoot = customRoot.filter((item) => item.node !== node);
|
nodes = nodes.filter((node) => {
|
||||||
|
const element =
|
||||||
|
typeof node.node === 'function' ? node.node() : node.node;
|
||||||
|
return root !== element;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all root nodes
|
* Get list of root nodes
|
||||||
*/
|
*/
|
||||||
export function getRootNodes(): ExtraRootNode[] {
|
export function listRootNodes(): ObservedNode[] {
|
||||||
return (root
|
return nodes;
|
||||||
? [
|
|
||||||
{
|
|
||||||
node: root,
|
|
||||||
temporary: false,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []
|
|
||||||
).concat(customRoot);
|
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,14 @@ import { FullIconifyIcon } from '@iconify/core/lib/icon';
|
|||||||
import { findPlaceholders } from './finder';
|
import { findPlaceholders } from './finder';
|
||||||
import { IconifyElementData, elementDataProperty } from './element';
|
import { IconifyElementData, elementDataProperty } from './element';
|
||||||
import { renderIcon } from './render';
|
import { renderIcon } from './render';
|
||||||
import { pauseObserver, resumeObserver } from './observer';
|
import { ObservedNode } from './observed-node';
|
||||||
import {
|
import {
|
||||||
getRoot,
|
pauseObserver,
|
||||||
getRootNodes,
|
resumeObserver,
|
||||||
addRoot,
|
removeObservedNode,
|
||||||
removeRoot,
|
observeNode,
|
||||||
ExtraRootNode,
|
} from './observer';
|
||||||
} from './root';
|
import { findRootNode, addRootNode, listRootNodes } from './root';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to avoid scanning DOM too often
|
* Flag to avoid scanning DOM too often
|
||||||
@ -51,10 +51,29 @@ const compareIcons = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan node for placeholders
|
||||||
|
*/
|
||||||
|
export function scanElement(root: HTMLElement): void {
|
||||||
|
// Add temporary node
|
||||||
|
let node = findRootNode(root);
|
||||||
|
if (!node) {
|
||||||
|
scanDOM(
|
||||||
|
{
|
||||||
|
node: root,
|
||||||
|
temporary: true,
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
scanDOM(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan DOM for placeholders
|
* Scan DOM for placeholders
|
||||||
*/
|
*/
|
||||||
export function scanDOM(customRoot?: HTMLElement): void {
|
export function scanDOM(node?: ObservedNode, addTempNode = false): void {
|
||||||
scanQueued = false;
|
scanQueued = false;
|
||||||
|
|
||||||
// List of icons to load: [provider][prefix][name] = boolean
|
// List of icons to load: [provider][prefix][name] = boolean
|
||||||
@ -63,18 +82,9 @@ export function scanDOM(customRoot?: HTMLElement): void {
|
|||||||
Record<string, Record<string, boolean>>
|
Record<string, Record<string, boolean>>
|
||||||
> = Object.create(null);
|
> = Object.create(null);
|
||||||
|
|
||||||
// Add temporary root node
|
// Get placeholders
|
||||||
let customRootItem: ExtraRootNode;
|
(node ? [node] : listRootNodes()).forEach((node) => {
|
||||||
if (customRoot) {
|
const root = typeof node.node === 'function' ? node.node() : node.node;
|
||||||
customRootItem = addRoot(customRoot, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get root node and placeholders
|
|
||||||
const rootNodes: ExtraRootNode[] = customRoot
|
|
||||||
? [customRootItem]
|
|
||||||
: getRootNodes();
|
|
||||||
rootNodes.forEach((rootItem) => {
|
|
||||||
const root = rootItem.node;
|
|
||||||
|
|
||||||
if (!root || !root.querySelectorAll) {
|
if (!root || !root.querySelectorAll) {
|
||||||
return;
|
return;
|
||||||
@ -121,9 +131,9 @@ export function scanDOM(customRoot?: HTMLElement): void {
|
|||||||
// Check icon
|
// Check icon
|
||||||
const storage = getStorage(provider, prefix);
|
const storage = getStorage(provider, prefix);
|
||||||
if (storage.icons[name] !== void 0) {
|
if (storage.icons[name] !== void 0) {
|
||||||
// Icon exists - replace placeholder
|
// Icon exists - pause observer before replacing placeholder
|
||||||
if (!paused && !rootItem.temporary) {
|
if (!paused && node.observer) {
|
||||||
pauseObserver(root);
|
pauseObserver(node);
|
||||||
paused = true;
|
paused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,13 +188,16 @@ export function scanDOM(customRoot?: HTMLElement): void {
|
|||||||
hasPlaceholders = true;
|
hasPlaceholders = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove temporay node
|
// Node stuff
|
||||||
if (rootItem.temporary && !hasPlaceholders) {
|
if (node.temporary && !hasPlaceholders) {
|
||||||
removeRoot(root);
|
// Remove temporary node
|
||||||
}
|
removeObservedNode(root);
|
||||||
|
} else if (addTempNode && hasPlaceholders) {
|
||||||
if (paused && !rootItem.temporary) {
|
// Add new temporary node
|
||||||
resumeObserver(root);
|
observeNode(root, true);
|
||||||
|
} else if (paused && node.observer) {
|
||||||
|
// Resume observer
|
||||||
|
resumeObserver(node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user