How to set custom CSS property for distributed content - dart

I am trying to set the custom CSS property of the PaperMenu node passed as content.
--paper-menu-background-color:green; works in the main document or when the PaperMenu is part of my custom component and are not in distributedNodes().
I have the following main.html
<html>
<head>
<meta charset="utf-8">
<link rel="import" href="packages/polymer_elements/paper_menu_button.html">
<link rel="import" href="packages/polymer_elements/paper_menu.html">
<link rel="import" href="packages/polymer_elements/paper_submenu.html">
<link rel="import" href="packages/polymer_elements/paper_item.html">
<link rel="import" href="packages/polymer_elements/paper_icon_button.html">
<link rel="import" href="packages/polymer_elements/paper_badge.html">
<link rel="import" href="packages/my_p/my_menu_bar.html">
</head>
<body unresolved>
<my-menu-bar>
<paper-menu>
<paper-submenu>
<paper-item class="menu-trigger">Topics</paper-item>
<paper-menu raised class="menu-content">
<paper-item>Topic 1</paper-item>
<paper-item>Topic 2</paper-item>
<paper-item>Topic 3</paper-item>
</paper-menu>
</paper-submenu>
</paper-menu>
</my-menu-bar>
<script type="application/dart" src="index.dart"></script>
<script src="packages/browser/dart.js"></script>
</body>
</html>
I don't want the below in the main.html though it works:
<style is="custom-style">
:root{--paper-menu-background-color:green;}
</style>
my_menu_bar.html
<dom-module id="my-menu-bar">
<style>
:host ::content paper-menu{
display:inline-block;
top:0;
vertical-align: text-top;
--paper-menu-background-color:green;
<!--Does not work, setting colors via script-->
}
</style>
<template>
<div id='my_menu_bar_div'>
<content></content>
</div>
</template>
</dom-module>
css below take effect but not '--paper-menu-background-color:green;'
display:inline-block; top:0; vertical-align: text-top;
Setting background color via dart script and reflection works:
#HtmlImport('my_menu_bar.html')
library m_p.lib.my_menu_bar;
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'package:polymer_elements/paper_input.dart';
import 'package:polymer_elements/paper_menu.dart';
import 'package:polymer_elements/paper_submenu.dart';
import 'package:polymer_elements/paper_item.dart';
import 'dart:async';
import 'package:web_components/web_components.dart';
import 'dart:mirrors';
#PolymerRegister('my-menu-bar')
class MyMenuBar extends PolymerElement {
MyMenuBar.created() : super.created() { }
void _recursive_set_style(var e, String attrName, String value){
// print(reflect(e).type.superclass.toString());
if(!(reflect(e).type.isSubtypeOf(reflectClass(HtmlElement))))
return;
// print('ya, it\'s subtype of HtmlElement');
InstanceMirror helperMirror = reflect(e.style);
var methodsAr = helperMirror.type.instanceMembers;
var sym = new Symbol(attrName);
print(methodsAr[sym]);
if(null !=methodsAr[sym]){
helperMirror.setField(sym,value);
}
for(var ie in e.children){
_recursive_set_style(ie,attrName,value);
}
}
attached() {
super.attached();
new Future(() {
ContentElement ce = Polymer.dom(this.root)
.querySelector('content');
PolymerDom dom = Polymer.dom(ce);
List<Node> nodes = dom.getDistributedNodes();
nodes.removeWhere((n)=>!(n is PaperMenu));
//Setting colors
updateStyles();
for(var e in nodes){
_recursive_set_style(e,'backgroundColor','rgb(156, 58, 53)');
}
});
}
}
Personally I like scripting over css, but love to know the standard way to do this and why this is happening.
Edit
Thanks to Günter Zöchbauer's comment, the function is now reduced to:
void _recursive_set_style(var e, String attrName, String value){
e.attributes[attrName]=value;
for(var ie in e.children){
_recursive_set_style(ie,attrName,value);
}
}
As to wrapping the content tag, it did not work or I'm doing something silly still.
Edit2
Hi, Günter Zöchbauer.
If you can help me confirm this, that would be great.
It's so hard to be sure about anything.
my-menu-bar:
<dom-module id="my-menu-bar">
<style>
:host ::content paper-menu{
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host ::content .special{
<!--setting class name did nothing-->
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host div#my_menu_bar ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div > ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
#my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
::content paper-menu{
--paper-menu-background-color:green;
}
paper-menu{
--paper-menu-background-color:green;
}
:root ::content paper-menu{
--paper-menu-background-color:green;
}
:root #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
:host ::content .paper-menu{
--paper-menu-background-color:green;
}
:host ::content #paper-menu{
--paper-menu-background-color:green;
}
</style>
<template>
<style>
:host ::content paper-menu{
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host ::content .special{
<!--setting class name did nothing-->
display:inline-block;
top:0;
backgroundColor:black;
--paper-menu-background-color:green;
vertical-align: text-top;
}
:host div#my_menu_bar ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div > ::content paper-menu{
--paper-menu-background-color:green;
}
:host #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
#my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
::content paper-menu{
--paper-menu-background-color:green;
}
paper-menu{
--paper-menu-background-color:green;
}
:root ::content paper-menu{
--paper-menu-background-color:green;
}
:root #my_menu_bar_div ::content paper-menu{
--paper-menu-background-color:green;
}
:host ::content .paper-menu{
--paper-menu-background-color:green;
}
:host ::content #paper-menu{
--paper-menu-background-color:green;
}
</style>
<div id='my_menu_bar_div'>
<content></content>
</div>
</template>
</dom-module>
I tried debugger and it seems CSS variable sham and related values are taking effect before initPolymer() and standard CSS directives like "display:inline-block;".
Edit3
Hi, Günter Zöchbauer.
In response to your "This doesn't look right.", I double checked.
But I think css variable sham is the thing to blame. I mean, as I said first, the standard CSS directives are working on the distributed content.
Under shady DOM, the <content> tag doesn’t appear in the DOM tree.
Styles are rewritten to remove the ::content pseudo-element, and any
combinator immediately to the left of ::content.
The description is a little lacking, but from examples I assume it's telling me to have selectors to the right and the left of the ::content pseudo element and I think I always had that right.
Digging deeper requires javascript knowledge and I don't have that, I know javascript is the foundation of web but I'm no web programmer and want to cover wide before diving deep, so I will give up on this.
<dom-module id="my-menu-bar">
<template>
<style>
:host .content-wrapper > ::content div{
/* These CSS variables do not work*/
--paper-menu-background-color:blue;
--paper-item{
background-color:red;
}
/*The below works alright*/
/*background-color:green;*/
/*color:red;*/
}
:host .content-wrapper > ::content .special{
/* This and the above should have
the same scope of selection, but this one
does not work at all.
Encapsulation playing a trick idk.*/
/*background-color:green;*/
/*color:red;*/
}
:host ::content div{
/*works*/
/*background-color:green;*/
}
:host ::content {
/* does not work*/
/*background-color:green;*/
}
:host ::content paper-menu{
/*works but custom property and color*/
/*color:blue;*/
display:inline-block;
top:0;
vertical-align: text-top;
}
:host ::content paper-item{
/*works*/
/*color:blue;*/
}
</style>
<div class='content-wrapper'>
<content></content>
</div>
</template>
</dom-module>
Edit4
After a long and futile search, I believe I found it.
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-301/?redirect_from_locale=pt
What's conceptually bizarre about insertion points is that they don't
physically move DOM. The host's nodes stay intact. Insertion points
merely re-project nodes from the host into the shadow tree. It's a
presentation/rendering thing: "Move these nodes over here" "Render
these nodes at this location."
You cannot traverse the DOM into a <content>.
If I could set the value of a CSS variable for an outer light dom from within a shadow dom, that would break the encapsulation. While Color etc belongs to content pseudo element, css variables and mixins are macro that insert values into css place holders.

To make this work in shady DOM (default) you need to wrap the <content> tag in another tag and include this wrapper in the selector.
See https://www.polymer-project.org/1.0/docs/devguide/styling.html#styling-distributed-children-content (first example for more details)
If this still doesn't work it might be a limitation of the CSS variables shim.
<dom-module id="my-element">
<template>
<style>
/* styling elements distributed to content (via ::content) requires */
/* selecting the parent of the <content> element for compatibility with */
/* shady DOM . This can be :host or a wrapper element. */
.content-wrapper > ::content .special {
background: orange;
}
</style>
<div class="content-wrapper"><content></content></div>
</template>
</dom-module>

Related

Polymer Dart Custom Element not executing

It appears that my Polymer Dart custom elements that were once working now stopped firing. Dartium displays in localhost the h1 tag but not my custom elements.
The only Dart Editor error/warning I get is:
"(from html5lib) Unexpected start tag (link). Expected DOCTYPE. See http://goo.gl/5HPeuP#polymer_40 for details."
This warning message appears on every
<link rel="import" href="packages/polymer/polymer.html">
but as best I can see this is a known issue which should not impede application execution.
My troubleshooting efforts to date include:
- Running pub cache repair from command line
- Manually deleting package cache directory and running pub get again.
- Downloading and running polymer-and-dart-codelab-master.zip (I get the same behavior)
How can I diagnose this issue?
Pubspec.yaml contents:
name: mpower
description: Sample app built with the polymer.dart package
environment:
sdk: '>=1.2.0 <2.0.0'
dependencies:
polymer: '>=0.15.1 <0.16.0'
dev_dependencies:
unittest: '>=0.10.0 <0.11.0'
transformers:
- polymer:
entry_points:
- web/index.html
Index.html Contents:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mosaic mPower</title>
<link rel="import" href="est_list.html">
<link rel="stylesheet" href="app.css">
</head>
<body>
<h1>Mosaic mPower</h1>
<est-list></est-list>
<script type="application/dart">export 'package:polymer/init.dart';</script>
</body>
</html>
est-list.html
<link rel="import" href="packages/polymer/polymer.html">
<link rel="import" href="est_form.html">
<link rel="import" href="est_element.html">
<polymer-element name="est-list">
<template>
<style>
select {
margin-bottom: 30px;
display: inline;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 2px;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
-webkit-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
}
</style>
<div>
<label>Filter: </label>
<select value="{{filterValue}}" on-change="{{filter}}">
<option template repeat="{{filter in filters}}">
{{filter}}
</option>
</select>
</div>
<div on-estvalidated="{{addEst}}"
on-formnotneeded="{{resetForm}}">
<est-form est="{{newEst}}"></est-form>
</div>
<div on-deleteest="{{deleteEst}}"
on-levelchanged="{{filter}}">
<template repeat="{{est in filteredEsts}}">
<est-element est="{{est}}"></est-element>
</template>
</div>
</template>
<script type="application/dart" src="est_list.dart"></script>
est-list.dart
import 'package:polymer/polymer.dart';
import 'model.dart' show Est;
import 'dart:html' show Event, Node;
/*
* Class to represent a collectionon-est of Est objects.
*/
#CustomTag('est-list')
class EstList extends PolymerElement {
static const ALL = "all";
/*
* Field for a new Est object.
*/
#observable Est newEst = new Est();
/*
* Collection of ests. The source of truth for all ests in this app.
*/
#observable List<Est> ests = toObservable([]);
/*
* Sets the new est form to default to the intermediate level.
*/
String get defaultCustomer => Est.CUSTOMERS[0];
/*
* List of filter values. Includes the levels defined in the model, as well
* as a filter to return all ests.
*/
final List<String> filters = [ALL]..addAll(Est.CUSTOMERS);
/*
* String that stores the value used to filter ests.
*/
#observable String filterValue = ALL;
/*
* The list of filtered ests.
*/
#observable List<Est> filteredEsts = toObservable([]);
/*
* Named constructor. Sets initial value of filtered ests and sets
* the new est's customer to the default.
*/
EstList.created() : super.created() {
filteredEsts = ests;
newEst.customer = defaultCustomer;
}
/*
* Replaces the existing new Est, causing the new est form to reset.
*/
resetForm() {
newEst = new Est();
newEst.customer = defaultCustomer;
}
/*
* Adds a est to the ests list and resets the new est form. This
* triggers estsChanged().
*/
addEst(Event e, var detail, Node sender) {
e.preventDefault();
ests.add(detail['est']);
resetForm();
}
/*
* Removes a est from the ests list. This triggers estsChanged().
*/
deleteEst(Event e, var detail, Node sender) {
var est = detail['est'];
ests.remove(est);
}
/*
* Calculates the ests to display when using a filter.
*/
filter() {
if (filterValue == ALL) {
filteredEsts = ests;
return;
}
filteredEsts = ests.where((est) {
return est.customer == filterValue;
}).toList();
}
/*
* Refreshes the filtered ests list every time the ests list changes.
*/
estsChanged() {
filter();
}
}
As mentioned in the comment,
this is caused by an expired Dartium.
Sadly it doesn't show a message to tell about it.
Star this open issue http://dartbug.com/18560 for updates.

Blinking during of rendering pages with custom elements (FOUC issue)

I use dart-polymer package to create custom elements. I have noticed that there is some blinking during of page with the custom elements loading. This effect also is visible for the very simple ClickCounter app. Is there any way to avoid this vexing blinking?
The issue is good described in Wikipedia http://en.wikipedia.org/wiki/Flash_of_unstyled_content
The suggested solution from http://www.polymer-project.org/docs/polymer/styling.html#fouc-prevention does not work for the simple application (polymer: '0.10.0-pre.2')..
<html>
<head>
<title>Click Counter</title>
<!-- import the click-counter -->
<link rel="import" href="packages/polymer/polymer.html">
<link rel="import" href="clickcounter.html">
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
</head>
<body unresolved>
<h1>CC</h1>
<p>Hello world from Dart!</p>
<div id="sample_container_id">
<click-counter count="5"></click-counter>
</div>
</body>
</html>
<polymer-element name="click-counter" attributes="count">
<template>
<style>
div {
font-size: 24pt;
text-align: center;
margin-top: 140px;
}
button {
font-size: 24pt;
margin-bottom: 20px;
}
</style>
<div>
<button on-click="{{increment}}">Click me</button><br>
<span>(click count: {{count}})</span>
</div>
</template>
<script type="application/dart" src="clickcounter.dart"></script>
</polymer-element>
import 'package:polymer/polymer.dart';
/**
* A Polymer click counter element.
*/
#CustomTag('click-counter')
class ClickCounter extends PolymerElement {
#published int count = 0;
ClickCounter.created() : super.created() {
}
void increment() {
count++;
}
}
see also the created issue in code.google.com https://code.google.com/p/dart/issues/detail?id=17498
Polymer 0.9.5
The class names to use are polymer-veiled (hidden) and polymer-unveil (during unveil transition)
If it is different than in Polymer.js it is probably subject of change but as of PolymerDart 0.9.0 it should work.
The relevant code is in packages/polymer/src/boot.dart.
Polymer 0.10.0
Polymer 0.10.0-pre.1 uses already the unresolved attribute like explained here
Polymer - Styling reference - FOUC prevention
You need to add a version constraint in pubspec.yaml to get the development version like
polymer: ">=0.10.0-pre.1"

How to style distributed nodes in Dart Polymer

I'm trying to style distributed nodes in Dart Polymer with no luck. I'm using the example at:
http://www.polymer-project.org/articles/styling-elements.html#style-distributed
as a starting point. However, I can't even get that working once ported to Dart. Here is my code:
<polymer-element name="test-element">
<template>
<style>
content[select="p"]::content * { /* anything distributed here */
font-weight: bold;
}
/* #polyfill p:first-child */
::content p:first-child {
color: red;
}
/* #polyfill footer > p */
::content footer > p {
color: green;
}
/* #polyfill :host > p */
::content > p { /* scope relative selector */
color: blue;
}
</style>
<content select="p"></content>
<content></content>
</template>
<script type="application/dart" src="testelement.dart"></script>
</polymer-element>
.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sample app</title>
<link rel="stylesheet" href="testpolymer.css">
<!-- import the test-element -->
<link rel="import" href="testelement.html">
<script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
</head>
<body>
<h1>TestPolymer</h1>
<p>Hello world from Dart!</p>
<test-element>
<p>I'm red and bold</p>
<p>I'm blue and bold</p>
<footer>
<p>I'm also red</p>
<p>I'm green</p>
<span>I'm black</span>
</footer>
</test-element>
</body>
</html>
The output has no styling applied and is just black text for everything. Any ideas what I'm doing wrong?
polymer-elements polymer-flex-layout / polymer-flex-layout.css still use
::-webkit-distributed(p) {
color: red;
}
which also works in my recent version of Dartium.
I have no idea when the new selectors take effect.
Other polymer-elements that make use of this selector but have recently switched to ::content
polymer-ui-field
polymer-ui-menu-item
polymer-ui-nav-arrow
polymer-ui-pages
polymer-ui-sidebar
polymer-ui-toolbar
You can browse the history to find the previous webkit-distributed selector examples.
I guess they use Chromium which may be a little ahead of Dartium.

How do you style a custom element's tag from within the element?

I'm trying to style a custom element tag, and can't seem to do it from within the element's <style> tag, or at least I don't know what selector to use. I've tried the custom element's tag name and template, but neither work.
<polymer-element name="my-test" constructor="MyTest">
<template>
<style>
my-test {
border: solid 1px #888; /* doesn't work */
}
.title {
color: blue; /* works */
}
</style>
<div class="title">{{ title }}</div>
</template>
I'm using polymer.dart, so there may be some lag in its implementation, but I'd like to know how it should work in polymer.js.
I think what you want is the #hostcss selector.
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/#toc-style-host
As mentioned in another answer, to style the host of the shadow DOM, use #host selector. In the case of a custom element, the host of the custom element is itself.
Here is an example of how to style the host element, or the custom element itself, from within a custom element's <style> tag.
<!DOCTYPE html>
<html>
<head>
<title>index</title>
<script src="packages/polymer/boot.js"></script>
</head>
<body>
<polymer-element name="my-element">
<template>
<style>
#host {
my-element {
display: block;
border: 1px solid black;
}
}
p {
color: red;
}
#message {
color: pink;
}
.important {
color: green;
}
</style>
<p>Inside element, should be red</p>
<div id="message">
The message should be pink
</div>
<div class="important">
Important is green
</div>
<div>
<content></content>
</div>
</template>
<script type="application/dart" src="index.dart"></script>
</polymer-element>
<p>outside of element, should be black</p>
<div id="message">
The outside message should be black
</div>
<div class="important">
Outside important is black
</div>
<my-element>Hello from content</my-element>
<!-- If the script is just an empty main, it's OK to include inline. -->
<!-- Otherwise, put the app into a separate .dart file. -->
<script type="application/dart">main() {}</script>
</body>
</html>
Notice the #host block in the style:
#host {
my-element {
display: block;
border: 1px solid black;
}
}
Because this particular custom element does not extend any element, it does not default to a block.
Here is what it looks like when styled:

html/css -- trying to center image and ignore body margins

Foo.html:
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="testStyle.css" />
</head>
<body>
The appearance of the text is good. This image should be centered, but it isn't:
<img class="centerblock" src="ice cream cone and dish.png" width="320" height="200"></img>
</body>
TestStyle.css:
body {margin-left:30px;}
body {margin-right:30px;}
.centerblock {
margin-left: auto;
margin-right: auto;
display: block;
}
Result:
Try:
.centerblock {
position:fixed;
top:10px;
left: 10px;
}
Maybe that can help, Although i don't know what can happen if you turn the phone.
I would make that main content area to fit to the edge of display and define all align properties for each element.
It's never very smart to do:
body {margin-left:30px;}
body {margin-right:30px;}
There is also option:
.main-container {
margin: 0 auto;
}
That also centers all the content but i think, also would not solve your problem.

Resources