mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
688 lines
18 KiB
HTML
688 lines
18 KiB
HTML
<!doctype html>
|
|
<!--
|
|
@license
|
|
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
Code distributed by Google as part of the polymer project is also
|
|
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
-->
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
|
<script src="../../../web-component-tester/browser.js"></script>
|
|
<link rel="import" href="../../polymer.html">
|
|
</head>
|
|
<body>
|
|
|
|
<simple-element></simple-element>
|
|
<simple-element></simple-element>
|
|
|
|
<x-scope></x-scope>
|
|
|
|
<dom-module id="x-grand-child-scope">
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
padding: 8px;
|
|
}
|
|
|
|
#scope {
|
|
border: var(--scope-var);
|
|
}
|
|
|
|
#child {
|
|
border: var(--child-scope-var);
|
|
}
|
|
|
|
#me {
|
|
border: var(--grand-child-scope-var);
|
|
}
|
|
|
|
</style>
|
|
|
|
<template>
|
|
<div id="me">x-grand-child-scope</div>
|
|
<div id="scope">From x-scope</div>
|
|
<div id="child">From x-child-scope</div>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-grand-child-scope'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-host-property">
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
padding: 8px;
|
|
border: var(--scope-var);
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
Host property
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-host-property'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-child-scope">
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
padding: 8px;
|
|
}
|
|
|
|
:root {
|
|
--gc4-scope: 5px solid green;
|
|
}
|
|
|
|
#me {
|
|
border: var(--child-scope-var);
|
|
}
|
|
|
|
#gc2 {
|
|
--grand-child-scope-var: 4px solid seagreen;
|
|
}
|
|
|
|
#gc4 {
|
|
--grand-child-scope-var:
|
|
var(--gc4-scope);
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<div id="me">x-child-scope</div>
|
|
<x-grand-child-scope id="gc1"></x-grand-child-scope>
|
|
<x-grand-child-scope id="gc2"></x-grand-child-scope>
|
|
<x-grand-child-scope id="gc3"></x-grand-child-scope>
|
|
<x-grand-child-scope id="gc4"></x-grand-child-scope>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-child-scope'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-overrides">
|
|
<style>
|
|
:host {
|
|
border: 1px dashed gray;
|
|
margin: 8px;
|
|
padding: 8px;
|
|
display: block;
|
|
--grand-child-scope-var: var(--rename);
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
overrides:
|
|
<x-grand-child-scope id="gc1"></x-grand-child-scope>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-overrides'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-overrides2">
|
|
<style>
|
|
:host {
|
|
border: 1px dashed gray;
|
|
margin: 8px;
|
|
padding: 8px;
|
|
display: block;
|
|
}
|
|
|
|
:root {
|
|
--grand-child-scope-var: var(--rename);
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
overrides:
|
|
<x-grand-child-scope id="gc1"></x-grand-child-scope>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-overrides2'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-late">
|
|
<style>
|
|
:host {
|
|
border: var(--late);
|
|
display: block;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
late
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-late'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-overrides3">
|
|
<style>
|
|
:host {
|
|
border: 1px dashed gray;
|
|
margin: 8px;
|
|
padding: 8px;
|
|
display: block;
|
|
}
|
|
|
|
:root {
|
|
--fillin: 16px;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
overrides:
|
|
<x-late id="late"></x-late>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-overrides3'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-has-def">
|
|
<style>
|
|
:host {
|
|
border: var(--border, --defaultBorder);
|
|
margin: 8px;
|
|
padding: 8px;
|
|
display: block;
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
Element with default variable.
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({is: 'x-has-def'});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-has-if">
|
|
<style>
|
|
.iffy {
|
|
border: var(--scope-var);
|
|
}
|
|
</style>
|
|
|
|
<template>
|
|
<template is="dom-if" if="{{gogo}}">
|
|
<div class="iffy">iffy</div>
|
|
</template>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({
|
|
is: 'x-has-if',
|
|
properties: {
|
|
gogo: {value: true}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-button">
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
border: var(--button-border);
|
|
}
|
|
</style>
|
|
<template>
|
|
Button!
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({
|
|
is: 'x-button',
|
|
extends: 'button'
|
|
});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-dynamic">
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
margin: 20px;
|
|
border: var(--dynamic);
|
|
}
|
|
</style>
|
|
<template>
|
|
Dynamic
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({
|
|
is: 'x-dynamic'
|
|
});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-scope">
|
|
<style>
|
|
:host {
|
|
x--invalid: 15px solid gray;
|
|
display: block;
|
|
padding: 8px;
|
|
--scope-var: 1px solid black;
|
|
--fallback: 7px solid orange;
|
|
--default1: var(--undefined, 6px solid yellow);
|
|
--default2: var(--undefined, --fallback);
|
|
--default3: var(--undefined, rgb(128, 200, 250));
|
|
--defaultBorder: 22px solid green;
|
|
--a: 10px;
|
|
--b: 5px;
|
|
--primary-color: rgb(128, 128, 128);
|
|
--late: var(--fillin);
|
|
|
|
--button-border: 16px solid tomato;
|
|
--after: 17px solid brown;
|
|
|
|
--end-term: 19px solid blue}
|
|
|
|
:root{--ws-term: 18px solid orange}
|
|
|
|
#me {
|
|
border: var(--scope-var);
|
|
}
|
|
|
|
x-child-scope {
|
|
--child-scope-var: 2px solid orange;
|
|
--grand-child-scope-var: 3px solid steelblue;
|
|
}
|
|
|
|
x-child-scope.special {
|
|
--child-scope-var: 12px solid orange;
|
|
}
|
|
|
|
#applyDefault1 {
|
|
border: var(--undefined, 6px solid yellow);
|
|
}
|
|
|
|
#applyDefault2 {
|
|
border: var(--undefined, --fallback);
|
|
}
|
|
|
|
#default1 {
|
|
border: var(--default1);
|
|
}
|
|
|
|
#default2 {
|
|
border: var(--default2);
|
|
}
|
|
|
|
#default3 {
|
|
padding: 8px;
|
|
background-color: var(--default3);
|
|
}
|
|
|
|
#defaultElement2 {
|
|
--defaultBorder: 23px solid goldenrod;
|
|
}
|
|
|
|
#overrides1a, #overrides1b, #overrides2 {
|
|
--rename: 8px solid navy;
|
|
}
|
|
|
|
#overrides1b, #overrides2 {
|
|
--grand-child-scope-var: 9px solid orange;
|
|
}
|
|
|
|
#overridesConcrete {
|
|
border: var(--scope-var);
|
|
border: 4px solid steelblue;
|
|
}
|
|
|
|
#calc {
|
|
border: solid red;
|
|
border-width: calc(var(--a) + var(--b));
|
|
}
|
|
|
|
#shadow {
|
|
box-shadow: 10px 10px 10px var(--primary-color);
|
|
-webkit-box-shadow: 10px 10px 10px var(--primary-color);
|
|
}
|
|
|
|
x-host-property {
|
|
border: 10px solid purple;
|
|
}
|
|
|
|
#invalid {
|
|
border: var(--invalid);
|
|
}
|
|
|
|
#after::after {
|
|
content: 'after';
|
|
border: var(--after);
|
|
}
|
|
|
|
#wsTerm {
|
|
border: var(--ws-term)
|
|
}
|
|
|
|
#endTerm {border: var(--end-term)}
|
|
</style>
|
|
|
|
<template>
|
|
<div id="me">x-scope</div>
|
|
<x-child-scope id="child"></x-child-scope>
|
|
<x-child-scope id="child2"></x-child-scope>
|
|
<x-overrides id="overrides1a"></x-overrides>
|
|
<x-overrides id="overrides1b"></x-overrides>
|
|
<x-overrides2 id="overrides2"></x-overrides2>
|
|
<x-overrides3 id="overrides3"></x-overrides3>
|
|
<div id="overridesConcrete">override concrete</div>
|
|
<button id="button" is="x-button"></button>
|
|
<div id="default1">default</div>
|
|
<div id="default2">var default</div>
|
|
<div id="default3">tricky property rgb(...) default</div>
|
|
<x-has-def id="defaultElement1"></x-has-def>
|
|
<x-has-def id="defaultElement2"></x-has-def>
|
|
<div id="applyDefault1">default</div>
|
|
<div id="applyDefault2">var default</div>
|
|
<div id="calc">Calc</div>
|
|
<div id="shadow">Shadow</div>
|
|
<div id="invalid">invalid</div>
|
|
<x-host-property id="hostProp"></x-host-property>
|
|
<x-has-if id="iffy"></x-has-if>
|
|
<div id="after"></div>
|
|
<x-dynamic id="dynamic"></x-dynamic>
|
|
<div id="wsTerm">new line var</div>
|
|
<div id="endTerm">end var</div>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({
|
|
is: 'x-scope'
|
|
});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<dom-module id="x-inside">
|
|
<style>
|
|
:host {
|
|
display: inline-block;
|
|
border: var(--border) solid orange;
|
|
height: 10px;
|
|
width: 10px;
|
|
background-color: tomato;
|
|
}
|
|
</style>
|
|
<template>
|
|
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({
|
|
is: 'x-inside'
|
|
});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
|
|
<dom-module id="simple-element">
|
|
<style>
|
|
:host {
|
|
display: block;
|
|
}
|
|
|
|
x-inside {
|
|
color: var(--dne);
|
|
--border: 10px;
|
|
}
|
|
</style>
|
|
<template>
|
|
<x-inside id="inner"></x-inside>
|
|
</template>
|
|
<script>
|
|
HTMLImports.whenReady(function() {
|
|
Polymer({
|
|
is: 'simple-element'
|
|
});
|
|
});
|
|
</script>
|
|
</dom-module>
|
|
|
|
<script>
|
|
suite('scoped-styling-var', function() {
|
|
|
|
function assertComputed(element, value, pseudo) {
|
|
var name = 'border-top-width';
|
|
var computed = element.getComputedStyleValue && !pseudo ?
|
|
element.getComputedStyleValue(name) :
|
|
getComputedStyle(element, pseudo)[name];
|
|
assert.equal(computed, value, 'computed style incorrect');
|
|
}
|
|
|
|
function assertStylePropertyValue(element, name, includeValue) {
|
|
var value = element.getComputedStyleValue(name);
|
|
assert.include(value, includeValue);
|
|
}
|
|
|
|
var styled = document.querySelector('x-scope');
|
|
|
|
test('mutiple elements in document', function() {
|
|
var e$ = document.querySelectorAll('simple-element');
|
|
assertComputed(e$[0].$.inner, '10px');
|
|
assertComputed(e$[1].$.inner, '10px');
|
|
});
|
|
|
|
test('simple variables calculated correctly between scopes', function() {
|
|
assertStylePropertyValue(styled, '--scope-var', '1px');
|
|
//
|
|
var child = styled.$.child;
|
|
assertStylePropertyValue(child, '--scope-var', '1px');
|
|
assertStylePropertyValue(child, '--child-scope-var', '2px');
|
|
assertStylePropertyValue(child, '--grand-child-scope-var', '3px');
|
|
//
|
|
var gc1 = child.$.gc1;
|
|
assertStylePropertyValue(gc1, '--scope-var', '1px');
|
|
assertStylePropertyValue(gc1, '--child-scope-var', '2px');
|
|
assertStylePropertyValue(gc1, '--grand-child-scope-var', '3px');
|
|
//
|
|
var gc2 = child.$.gc2;
|
|
assertStylePropertyValue(gc2, '--scope-var', '1px');
|
|
assertStylePropertyValue(gc2, '--child-scope-var', '2px');
|
|
assertStylePropertyValue(gc2, '--grand-child-scope-var', '4px');
|
|
//
|
|
var gc3 = child.$.gc3;
|
|
assertStylePropertyValue(gc3, '--scope-var', '1px');
|
|
assertStylePropertyValue(gc3, '--child-scope-var', '2px');
|
|
assertStylePropertyValue(gc3, '--grand-child-scope-var', '3px');
|
|
|
|
});
|
|
|
|
test('invalid variables not parsed', function() {
|
|
assert.notProperty(styled._styleProperties, 'x--invalid');
|
|
assertComputed(styled.$.invalid, '0px');
|
|
});
|
|
|
|
test('simple variables applied correctly between scopes', function() {
|
|
assertComputed(styled.$.me, '1px');
|
|
assertComputed(styled.$.child.$.me, '2px');
|
|
assertComputed(styled.$.child.$.gc1.$.me, '3px');
|
|
assertComputed(styled.$.child.$.gc1.$.scope, '1px');
|
|
assertComputed(styled.$.child.$.gc1.$.child, '2px');
|
|
assertComputed(styled.$.child.$.gc2.$.me, '4px');
|
|
assertComputed(styled.$.child.$.gc2.$.scope, '1px');
|
|
assertComputed(styled.$.child.$.gc2.$.child, '2px');
|
|
});
|
|
|
|
test('variable can be set to another variable', function() {
|
|
var gc4 = styled.$.child.$.gc4;
|
|
assertStylePropertyValue(gc4, '--grand-child-scope-var', '5px');
|
|
assertComputed(gc4.$.me, '5px');
|
|
});
|
|
|
|
test('variable default values can be assigned to other variables', function() {
|
|
assertStylePropertyValue(styled, '--default1', '6px');
|
|
assertStylePropertyValue(styled, '--default2', '7px');
|
|
assertComputed(styled.$.default1, '6px');
|
|
assertComputed(styled.$.default2, '7px');
|
|
assertComputed(styled.$.applyDefault1, '6px');
|
|
assertComputed(styled.$.applyDefault2, '7px');
|
|
});
|
|
|
|
test('variable literal defaults can contain one (...)', function() {
|
|
var b = getComputedStyle(styled.$.default3).backgroundColor;
|
|
assert.match(b, /rgb\(128/, 'literal fallback containin (...) not set');
|
|
});
|
|
|
|
test('variable values can be used with calc', function() {
|
|
assertComputed(styled.$.calc, '15px');
|
|
});
|
|
|
|
test('variable values can be used with box-shadow', function() {
|
|
var b = getComputedStyle(styled.$.shadow).boxShadow;
|
|
assert.match(b, /rgb\(128/, 'box shadow not set correctly');
|
|
});
|
|
|
|
test('host properties can be overridden with outer scope styles', function() {
|
|
assertComputed(styled.$.hostProp, '10px');
|
|
});
|
|
|
|
test('updateStyles changes property values and using style cache', function() {
|
|
styled.$.child.classList.add('special');
|
|
var l = document.querySelectorAll('style').length;
|
|
styled.updateStyles();
|
|
if (styled.shadyRoot) {
|
|
assert.equal(document.querySelectorAll('style').length, l+4);
|
|
}
|
|
assertComputed(styled.$.child.$.me, '12px');
|
|
styled.$.child.classList.remove('special');
|
|
styled.updateStyles();
|
|
if (styled.shadyRoot) {
|
|
assert.equal(document.querySelectorAll('style').length, l);
|
|
}
|
|
assertComputed(styled.$.child.$.me, '2px');
|
|
});
|
|
|
|
test('updateStyles changes own properties based on customStyle changes', function() {
|
|
styled.$.child.customStyle['--child-scope-var'] = '30px solid orange';
|
|
styled.$.child.updateStyles();
|
|
assertComputed(styled.$.child.$.me, '30px');
|
|
styled.$.child.customStyle = {};
|
|
styled.$.child.updateStyles();
|
|
assertComputed(styled.$.child.$.me, '2px');
|
|
});
|
|
|
|
test('updateStyles with properties argument changes styles', function() {
|
|
styled.$.child.updateStyles({'--child-scope-var': '26px solid seagreen'});
|
|
assertComputed(styled.$.child.$.me, '26px');
|
|
styled.$.child.customStyle = {};
|
|
styled.$.child.updateStyles();
|
|
assertComputed(styled.$.child.$.me, '2px');
|
|
});
|
|
|
|
test('styles update based on root customStyle changes', function() {
|
|
assertComputed(styled.$.dynamic, '0px');
|
|
Polymer.StyleDefaults.customStyle['--dynamic'] = '4px solid navy';
|
|
Polymer.updateStyles();
|
|
assertComputed(styled.$.dynamic, '4px');
|
|
Polymer.updateStyles({'--dynamic': '6px solid gray'});
|
|
assertComputed(styled.$.dynamic, '6px');
|
|
});
|
|
|
|
test('null customStyles unapply', function() {
|
|
styled.$.dynamic.updateStyles({'--dynamic': '8px solid black'});
|
|
assertComputed(styled.$.dynamic, '8px');
|
|
styled.$.dynamic.updateStyles({'--dynamic': null});
|
|
assertComputed(styled.$.dynamic, '6px');
|
|
styled.$.dynamic.updateStyles({'--dynamic': '8px solid black'});
|
|
assertComputed(styled.$.dynamic, '8px');
|
|
styled.$.dynamic.updateStyles({'--dynamic': null});
|
|
assertComputed(styled.$.dynamic, '6px');
|
|
});
|
|
|
|
test('style properties with dom-if', function() {
|
|
var e = styled.$.iffy;
|
|
var c = Polymer.dom(e.root).querySelector('.iffy');
|
|
assert.ok(c, 'dom-if did not stamp');
|
|
assertComputed(c, '1px');
|
|
});
|
|
|
|
test('variable precedence and overrides', function() {
|
|
// renamed property applied
|
|
var o1a = styled.$.overrides1a;
|
|
assertStylePropertyValue(o1a, '--rename', '8px');
|
|
assertStylePropertyValue(o1a, '--grand-child-scope-var', '8px');
|
|
assertComputed(o1a.$.gc1.$.me, '8px');
|
|
// :host property overridden by outer scope
|
|
var o1b = styled.$.overrides1b;
|
|
assertStylePropertyValue(o1b, '--rename', '8px');
|
|
assertStylePropertyValue(o1b, '--grand-child-scope-var', '9px');
|
|
assertComputed(o1b.$.gc1.$.me, '9px');
|
|
// own scope property overrides outer scope
|
|
var o2 = styled.$.overrides2;
|
|
assertStylePropertyValue(o2, '--rename', '8px');
|
|
assertStylePropertyValue(o2, '--grand-child-scope-var', '8px');
|
|
assertComputed(o2.$.gc1.$.me, '8px');
|
|
|
|
// late bound property does *not* resolve using inherited value
|
|
var o3 = styled.$.overrides3;
|
|
assert.equal(o3._styleProperties['--late'], '', 'property should not be late bound');
|
|
assertStylePropertyValue(o3, '--fillin', '16px');
|
|
assertComputed(o3.$.late, '0px');
|
|
|
|
});
|
|
|
|
test('type extension elements consume properties in :host rules', function() {
|
|
assertComputed(styled.$.button, '16px');
|
|
});
|
|
|
|
test('pseudo-elements can consume custom properties', function() {
|
|
assertComputed(styled.$.after, '17px', '::after');
|
|
});
|
|
|
|
test('elements using only variable defaults are styled properly', function() {
|
|
assertComputed(styled.$.defaultElement1, '22px');
|
|
assertComputed(styled.$.defaultElement2, '23px');
|
|
});
|
|
|
|
test('vars with trailing new line or } apply', function() {
|
|
assertComputed(styled.$.wsTerm, '18px');
|
|
assertComputed(styled.$.endTerm, '19px');
|
|
});
|
|
|
|
// TODO(sorvell): fix for #1761 was reverted; include test once this issue is addressed
|
|
// test('var values can be overridden by subsequent concrete properties', function() {
|
|
// assertComputed(styled.$.overridesConcrete, '4px');
|
|
// });
|
|
|
|
});
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|