Reputation: 1069
I'm trying to integrate a Javascript library in my Polymer 1.7 element which uses document.getElementById(divId);
. My Polymer element looks something like this:
<template>
<div id="libDiv"></div>
<button on-tap="go">Go!</button>
</template>
<script src="https://some-provider.com/greatlib.js"></script>
<script>
Polymer({
is: 'lib-test',
go: function () {
GreatLib.render('libDiv');
}
});
</script>
The library greatlib.js
could look something like this:
var GreatLib = (function() {
var render = function(divId) {
document.getElementById(divId).innerHTML = 'GreatLib is great!';
};
return {render: render};
}());
Of cause document.getElementById(divId)
can't find my div because it is in a Shadow DOM and not on the main document.
Is there a way to work around this and let document.getElementById(divId)
find elements in my Polymer element, without modifying "GreatLib"?
Run the following example in Chrome:
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<!--Use shadow DOM if available -->
<script>
window.Polymer = {
dom: 'shadow'
};
</script>
<link href="polymer/polymer.html" rel="import">
<dom-module id="x-example">
<style></style>
<template>
<div id="libDiv"></div>
<button on-tap="go">Go!</button>
</template>
<script>
var GreatLib = (function() {
var writeTextToDiv = function(divId) {
console.log('divId', divId);
console.log('document.getElementById(divId)', document.getElementById(divId));
document.getElementById(divId).innerHTML = 'GreatLib is great!';
};
return {
writeTextToDiv: writeTextToDiv
};
}());
Polymer({
is: 'x-example',
go: function () {
GreatLib.writeTextToDiv('libDiv');
}
});
</script>
</dom-module>
<x-example></x-example>
Upvotes: 1
Views: 955
Reputation: 136756
I don't know Polymer nor shadowDOM, and I took the opportunity of this question as an excuse to learn a bit on it.
So first of, it doesn't seem like a great idea to use ids for getting your shadowDOM. Also, as a reminder, shadowDOM is a way to hide the structure of your page.
But here is one Q/A that helped me to come to the conclusion that nope, document.getElementyId
is not the right tool out-of-the box.
However, you can access it thanks to document.querySelector
and the ::shadow
selector so here is an horrible hack that should probably not be used by anyone but which seems to work :
(function(){
// first check selector support
try{
document.querySelector('::shadow');
}
catch(e){
return; // not supported don't change anything
}
var gbi = document.getElementById.bind(document);
document.getElementById = function(_id){
var el = gbi(_id); // first try the original one
if(el){
return el;
}
else // nothing, try in the shadow
return document.querySelector('*::shadow #' + _id);
}
})()
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<!--Use shadow DOM if available -->
<script>
window.Polymer = {
dom: 'shadow'
};
</script>
<link href="polymer/polymer.html" rel="import">
<dom-module id="x-example">
<style></style>
<template>
<div id="libDiv"></div>
<button on-tap="go">Go!</button>
</template>
<script>
var GreatLib = (function() {
var writeTextToDiv = function(divId) {
console.log('divId', divId);
console.log('document.getElementById(divId)', document.getElementById(divId));
document.getElementById(divId).innerHTML = 'GreatLib is great!';
};
return {
writeTextToDiv: writeTextToDiv
};
}());
Polymer({
is: 'x-example',
go: function () {
GreatLib.writeTextToDiv('libDiv');
}
});
</script>
</dom-module>
<x-example></x-example>
Upvotes: 1