How to use CSS variable in same rule that declares it - html

In my custom element's definition, I have the following code:
<dom-module id="dom-element">
<style>
p {
--test: brown;
color: var(--test);
}
</style>
<template>
<p>I'm a DOM element. This is my local DOM!</p>
</template>
<script>
Polymer({
is: "dom-element"
});
</script>
</dom-module>
However, the CSS custom property isn't working. Polymer just turns this:
p {
--test: brown;
color: var(--test);
}
into this:
p {
color: ;
}
But I want the output to be:
p {
color: brown;
}
The demo can be found here: http://plnkr.co/edit/ogMVPKNvc7SYISomWPWm?p=preview
If I don't use Polymer, and create the custom element in pure JavaScript, the CSS custom property works as expected.
I have searched Google, but didn't find something related. What's the problem here? How can I use the CSS custom property with Polymer?

Polymer 1's CSS shim (enabled by default) apparently doesn't handle the CSS variable declaration in the same rule that uses it, so you'd have to move the declaration to :host in this scenario.
<!-- inside dom-module's template -->
<style>
:host {
--test: brown;
}
p {
color: var(--test);
}
</style>
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo'
});
});
<head>
<base href="https://polygit.org/polymer+1.7.1/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<style>
:host {
--test: brown;
}
p {
color: var(--test);
}
</style>
<p>Hello world</p>
</template>
</dom-module>
</body>
However, you can enable native CSS properties in Polymer with a global setting (useNativeCSSProperties) declared before importing polymer.html, which would allow your code to work as-is:
<script>window.Polymer = {lazyRegister: true, useNativeCSSProperties: true};</script>
<!-- import polymer.html here -->
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo'
});
});
<head>
<script>window.Polymer = {dom: 'shadow', lazyRegister: 'max', useNativeCSSProperties: true};</script>
<base href="https://polygit.org/polymer+1.7.1/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<style>
p {
--test: brown;
color: var(--test);
}
</style>
<p>Hello world</p>
</template>
</dom-module>
</body>
codepen

Related

Polymer 1.x: How to remove whitespace from paper-menu inside paper-dialog?

I want this...
Below is a paper-dialog implementation. It contains whitespace at the top and bottom of the dialog element. I want to eliminate the white space.
http://jsbin.com/bupicetoma/1/edit?html,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-dialog/paper-dialog.html" rel="import">
<link href="paper-menu/paper-menu.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style>
--paper-menu {
margin: 0 !important;
padding: 0 !important;
}
paper-menu {
padding: 0 !important;
}
paper-item:hover {
background-color: red;
}
paper-item {
--paper-item: {
cursor: pointer;
margin: 0;
};
}
</style>
<button on-tap="show">Show</button>
<paper-dialog id="dia">
<paper-menu>
<paper-item>Item 1</paper-item>
<paper-item>Item 2</paper-item>
<paper-item>Item 3</paper-item>
</paper-menu>
</paper-dialog>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {},
show: function() {
this.$.dia.open();
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
... to resemble this.
I want the paper-menu inside the dialog to look like the following paper-menu without any whitespace.
http://jsbin.com/hovayitela/1/edit?html,output
<!doctype html>
<head>
<meta charset="utf-8">
<base href="https://polygit.org/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<link href="paper-menu/paper-menu.html" rel="import">
<link href="paper-item/paper-item.html" rel="import">
</head>
<body>
<dom-module id="x-element">
<template>
<style>
--paper-menu {
margin: 0 !important;
padding: 0 !important;
}
paper-menu {
padding: 0 !important;
}
paper-item:hover {
background-color: red;
}
paper-item {
--paper-item: {
cursor: pointer;
margin: 0;
};
}
</style>
<paper-menu>
<paper-item>Item 1</paper-item>
<paper-item>Item 2</paper-item>
<paper-item>Item 3</paper-item>
</paper-menu>
</template>
<script>
(function(){
Polymer({
is: "x-element",
properties: {},
show: function() {
this.$.dia.open();
}
});
})();
</script>
</dom-module>
<x-element></x-element>
</body>
How can I accomplish this?
Your CSS mixin (--paper-menu) should be declared inside a rule (it's currently outside any rules). I would move that into the paper-menu rule:
paper-menu {
margin: 0 !important;
padding: 0 !important;
}
jsbin
FYI, that whitespace is from paper-dialog-shared-styles.html.

Scroll to bottom automatically using vanilla Javascript/CSS - Polymer

I don't want to use JQuery to do this. Currently, I've created a listview using Polymer. I'm using <template is="dom-repeat"> inside a parent div with a class of list.
The CSS is as follows. As I add new items to the list, I would like the list to scroll to the bottom automatically. Is that possible?
.list {
#apply(--layout-flex);
#apply(--layout-vertical);
position: relative;
overflow: auto;
}
You can set the div's scrollTop to scrollHeight in order to automatically scroll to the bottom:
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
properties: {
items: {
type: Array,
value: () => []
}
},
_addItem: function() {
this.push('items', this.items.length+1);
Polymer.RenderStatus.afterNextRender(this, () => {
this.$.list.scrollTop = this.$.list.scrollHeight;
});
}
});
});
<head>
<base href="https://polygit.org/polymer+1.7.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<style>
#list {
border: solid 1px gray;
width: 100%;
height: 100px;
overflow: auto;
}
</style>
<button on-tap="_addItem">Add item</button>
<div id="list">
<template is="dom-repeat" items="[[items]]">
<div>[[item]]</div>
</template>
</div>
</template>
</dom-module>
</body>
codepen

Cannot apply style to anchor tag when assigning to innerHTML

I'm assigning a string that contains anchor tags to an element's innerHTML. I need to style these, however, I am not sure how to do so. Here's an example using Polymer.dom and updateStyles as suggested by this StackOverflow post:
Polymer({
is: 'x-foo',
properties: {
value: {
type: String,
value: 'Hello',
observer: 'setValue'
}
},
setValue: function() {
Polymer.dom(this).innerHTML = this.value;
this.updateStyles();
}
});
<base href="https://polygit.org/polymer+:1.4.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<dom-module id="x-foo">
<style>
a {
color: red;
}
</style>
<template>
<content></content>
</template>
</dom-module>
<x-foo></x-foo>
And here's a link to the jsfiddle:
https://jsfiddle.net/cbelden/xamfhe52/
You don't need to call updateStyles(). Your dom-module style should be using ::content to target the distributed nodes:
<style>
::content a {
color: red;
}
</style>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-foo',
properties: {
value: {
type: String,
value: 'Hello',
observer: 'setValue'
}
},
setValue: function() {
Polymer.dom(this).innerHTML = this.value;
//this.updateStyles(); // not needed
}
});
});
<base href="https://polygit.org/polymer+:1.4.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link href="polymer/polymer.html" rel="import">
<dom-module id="x-foo">
<style>
::content a {
color: red;
}
</style>
<template>
<content></content>
</template>
</dom-module>
<x-foo></x-foo>

Polymer: how to handle a style dynamically

Hey i'm trying to create a simple drag and drop. Is that possible to style an element dynamically. My code will be more explicit:
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="wireframe-view">
<template>
<div on-tap="handleTap"
style$=width:{{ width }}px; background-color:red;
>Hello, World</div>
</template>
<script>
Polymer({
is: "wireframe-view",
handleTap: function() {
this.width = 200;
}
});
</script>
This should change the width in my "style" propertie :/
If the property value contains spaces quotes are required.
style$="width:{{ width }}px; background-color:red";
Here is a method for dynamically updating the style based on the value of a bound data attribute.
<link rel="import" href="../bower_components/polymer/polymer.html">
<dom-module id="conditional-css-example">
<style>
#tapContainer {
width: 100px;
background-color:white;
}
#tapContainer[data-tap-status$="tapped"] {
width: 200px;
background-color:red;
}
</style>
<template>
<div id="tapContainer" data-tap-status$="[[tapStatus]]" on-tap="handleTap">Tap Me!</div>
</template>
<script>
Polymer({
is: "conditional-css-example",
properties: {
tapStatus: String;
},
handleTap: function() {
this.tapStatus='tapped';
}
});
</script>

Uncaught TypeError: this.$.selector.clearSelection is not a function

Here is my layout. Without iron-list it works, but with it it gives me the error
Uncaught TypeError: this.$.selector.clearSelection is not a function
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../common-settings-service/common-settings-service.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html"/>
<link rel="import" href="../bower_components/paper-material/paper-material.html"/>
<link rel="import" href="../bower_components/iron-list/iron-list.html">
<link rel="import" href="../bower_components/iron-flex-layout/iron-flex-layout.html">
<dom-module id="common-settings">
<style>
:host {
display: block;
}
paper-material {
background: #FFFFFF;
}
.container {
#apply(--layout-horizontal);
}
.windowItem {
#apply(--layout-horizontal);
}
.list {
#apply(--layout-flex);
#apply(--layout-vertical);
}
.item {
#apply(--layout-horizontal);
margin: 16px 16px 0 16px;
padding: 20px;
border-radius: 8px;
background-color: white;
border: 1px solid #ddd;
}
</style>
<template>
<common-settings-service
id="commonSettings"
url="/board_service/common_settings/"
settings="{{settings}}"/>
<paper-material elevation="1">
<div class="container">
<h3> Настройки обработки</h3>
<h4>Окна</h4>
<div class="list">
<iron-list items="[[settings.timeWindows]]" as="item">
<template>
<div class="item">
Name: <span>[[item]]</span>
</div>
</template>
</iron-list>
</div>
While I don't know how to show you live demo I've been able to debug a little iron-list code. The problem is with the last line.
clearSelection: function() {
function unselect(item) {
var model = this._getModelFromItem(item);
if (model) {
model[this.selectedAs] = false;
}
}
if (Array.isArray(this.selectedItems)) {
this.selectedItems.forEach(unselect, this);
} else if (this.selectedItem) {
unselect.call(this, this.selectedItem);
}
this.$.selector.clearSelection();
},
Debugging shows that there is really no such function in selector. And this selector is actually array-selector element from polymer library. And it have such function in the source code.
Ok, so I've found the reason for this. They've changed API beetween 1.0.9 and 1.1.1. My polymer was version 1.0.9 and that's why it haven't worked.
I've updated all polymer elements to the latest version and now it works.