Reputation:
I have a drop-down element in Polymer. Because of z-indexing issues, I need to pull the drop-down part out and make it a direct child of <body>
. Unfortunately, I can't figure out how to do that and still be able to actually style the element. The only solution I can come up with is to make the drop-down portion its own polymer tag, but that seems really... backwards.
In short, I have an element:
<my-element>
<template>
<style>...</style>
<input>
<div id="dropdown">...</div>
</template>
</my-element>
And then JS in the element that does document.body.appendChild( this.$.dropdown )
I'm trying to figure out how to stylize the drop-down once its been moved, but Polymer/Web Components' CSS isolation is preventing me from doing that.
Upvotes: 2
Views: 834
Reputation:
[edit] Note that polymer can't properly handle on-*
event handlers attached via the DOM with this method due to the fact that it can't walk the DOM tree back up to the polymer-element. So events need to be manually attached to anything using this.
I created a custom element that can be inserted into any element and it will pull out all rules that start with body
and promote them to a new stylesheet inserted into head
. There is a bit of work to be done, specifically around browsers that need to be polyfilled as the ::shadow
selector won't work. But I'll get to that shortly.
<link rel="import" href="../polymer/polymer.html" />
<polymer-element name="promote-body-css">
<script>
'use strict';
~function(){
var promoted = {};
function promote( node ){
var nodeName = node.nodeName;
if( promoted[ nodeName ] ){ return; }
var promoteRules = [];
[].forEach.call( node.querySelectorAll( '::shadow style' ), function( stylesheet ){
[].forEach.call( stylesheet.sheet.cssRules, function( rule ){
if( rule.cssText.indexOf( 'body ' ) === 0 ){
promoteRules.push( rule.cssText );
}
} );
} );
if( promoteRules.length ){
var stylesheet = document.createElement( 'style' );
stylesheet.innerHTML = promoteRules.join( '' ) + '/* Inserted from polymer element ' + nodeName + ' */';
document.getElementsByTagName( 'head' )[0].appendChild( stylesheet );
}
}
promoted[ nodeName ] = 1;
Polymer( 'promote-body-css', {
attached : function( parent ){
promote( ( parent = this.parentNode ).host || parent );
}
} );
}();
</script>
</polymer-element>
Upvotes: 1