Issue
I am attempting to find a selector that is relative to the script that I have injected into the shadow dom.
I can find the element I need if I explicitly find it using the document, then selecting the shadowRoot and using querySelector again.
i.e. var selector = "document.querySelector('#shadow').shadowRoot.querySelector('img')";
Is it possible to get the shadowRoot without having to explicitly get the element that it is on from within the shadowRoot?
I have tried document.currentScript
but it comes back as null when executed in the shadow dom
document.querySelector('#shadow').attachShadow({mode: 'open'});
var shadow = document.querySelector('#shadow');
shadow.shadowRoot.innerHTML = '<img id="img"><div></div>';
var scriptElement = document.createElement('script');
// Can this be relative to the script tag?
var selector = "document.querySelector('#shadow').shadowRoot.querySelector('img')";
scriptElement.textContent = `
JsBarcode(${selector}, "401246",
{
format: "CODE128",
displayValue: true,
height: 25,
width: 1,
fontSize: 16,
lineColor: "#000000"
}
);
`;
var shadowDiv = document.querySelector('#shadow').shadowRoot.querySelector('div');
shadowDiv.appendChild(scriptElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsbarcode/3.11.5/JsBarcode.all.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="src/style.css">
</head>
<body>
<h1 id="header"></h1>
<div id="shadow">
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsbarcode/3.11.5/JsBarcode.all.min.js"></script>
<script src="src/script.js"></script>
</body>
</html>
Solution
<script>
run in Global scope, not in shadowRoot scope.
To prevent the 3rd party script loading multiple times.
load the
<script>
(in the<head>
or anywhere)use the script
onload
Event- (the Global JsBarCode Function is now defined)
- then create a new Web Component
<jsbar-code>
- that encodes any existing or future
<jsbar-code>
tags
every
<jsbar-code>
calls the (Global!)JsBarCode function
to transform its own<svg>
in its shadowDOM
<jsbar-code value="210169"></jsbar-code>
<jsbar-code value="12312023" fontSize="21"></jsbar-code>
<jsbar-code format="upc" value="123456789012" textmargin="0" fontoptions="bold"></jsbar-code>
<jsbar-code format="pharmacode" lineColor="#0aa" width="4" height="40" value="21" displayValue="0"></jsbar-code>
<script>
document.head.append(
Object.assign(document.createElement("script"), {
src: "//cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js",
onload: () => {
customElements.define(
"jsbar-code",
class extends HTMLElement {
connectedCallback() {
this.attachShadow({mode:"open"}).innerHTML = `<svg></svg>`;
let attr = (x) => this.getAttribute(x) || "";
let options = { // default options
format: "CODE128",
displayValue: attr("displayValue") != "0",
height: 25,
width: 1,
fontSize: 16,
lineColor: attr("lineColor") || "black"
};
Array.from(this.attributes).forEach(({
nodeName, // override defaults with attribute settings
nodeValue
}) => options[nodeName] = nodeValue);
// execute Global function
JsBarcode(this.shadowRoot.querySelector("svg"), options.value, options);
}
}
);
}
}))
</script>
Also available in JSFiddle Playground: https://jsfiddle.net/WebComponents/baeqszjm/
Answered By - Danny '365CSI' Engelman
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.