Commit 8d068c21 authored by Pascal Hartig's avatar Pascal Hartig

Vendor Polymer components

parent 1fc9fbea
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"dependencies": { "dependencies": {
"jquery": "~2.1.0", "jquery": "~2.1.0",
"bootstrap": "~3.2.0", "bootstrap": "~3.2.0",
"paper-tabs": "Polymer/paper-tabs#~0.3.5" "paper-tabs": "Polymer/paper-tabs#~0.4.0"
}, },
"devDependencies": { "devDependencies": {
"prefixfree": "91790e8aff6d807cd62018479db2307e1972b92a" "prefixfree": "91790e8aff6d807cd62018479db2307e1972b92a"
......
{
"name": "core-selection",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
},
"homepage": "https://github.com/Polymer/core-selection",
"version": "0.4.1",
"_release": "0.4.1",
"_resolution": {
"type": "version",
"tag": "0.4.1",
"commit": "dd6919363a49f1f4ff52fa0dffef88e2bdfbbfdc"
},
"_source": "git://github.com/Polymer/core-selection.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-selection"
}
\ No newline at end of file
core-selection
==============
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-selection) for more information.
{
"name": "core-selection",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
}
}
\ No newline at end of file
<!--
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
-->
<!--
@group Polymer Core Elements
The `<core-selection>` element is used to manage selection state. It has no
visual appearance and is typically used in conjunction with another element.
For example, [core-selector](#core-selector)
use a `<core-selection>` to manage selection.
To mark an item as selected, call the `select(item)` method on
`<core-selection>`. The item itself is an argument to this method.
The `<core-selection>`element manages selection state for any given set of
items. When an item is selected, the `core-select` event is fired.
The attribute `multi` indicates if multiple items can be selected at once.
Example:
<polymer-element name="selection-example">
<template>
<style>
polyfill-next-selector { content: ':host > .selected'; }
::content > .selected {
font-weight: bold;
font-style: italic;
}
</style>
<ul on-tap="{{itemTapAction}}">
<content></content>
</ul>
<core-selection id="selection" multi
on-core-select="{{selectAction}}"></core-selection>
</template>
<script>
Polymer('selection-example', {
itemTapAction: function(e, detail, sender) {
this.$.selection.select(e.target);
},
selectAction: function(e, detail, sender) {
detail.item.classList.toggle('selected', detail.isSelected);
}
});
</script>
</polymer-element>
<selection-example>
<li>Red</li>
<li>Green</li>
<li>Blue</li>
</selection-example>
@element core-selection
-->
<!--
Fired when an item's selection state is changed. This event is fired both
when an item is selected or deselected. The `isSelected` detail property
contains the selection state.
@event core-select
@param {Object} detail
@param {boolean} detail.isSelected true for selection and false for de-selection
@param {Object} detail.item the item element
-->
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="core-selection" attributes="multi" hidden>
<script>
Polymer('core-selection', {
/**
* If true, multiple selections are allowed.
*
* @attribute multi
* @type boolean
* @default false
*/
multi: false,
ready: function() {
this.clear();
},
clear: function() {
this.selection = [];
},
/**
* Retrieves the selected item(s).
* @method getSelection
* @returns Returns the selected item(s). If the multi property is true,
* getSelection will return an array, otherwise it will return
* the selected item or undefined if there is no selection.
*/
getSelection: function() {
return this.multi ? this.selection : this.selection[0];
},
/**
* Indicates if a given item is selected.
* @method isSelected
* @param {any} item The item whose selection state should be checked.
* @returns Returns true if `item` is selected.
*/
isSelected: function(item) {
return this.selection.indexOf(item) >= 0;
},
setItemSelected: function(item, isSelected) {
if (item !== undefined && item !== null) {
if (isSelected) {
this.selection.push(item);
} else {
var i = this.selection.indexOf(item);
if (i >= 0) {
this.selection.splice(i, 1);
}
}
this.fire("core-select", {isSelected: isSelected, item: item});
}
},
/**
* Set the selection state for a given `item`. If the multi property
* is true, then the selected state of `item` will be toggled; otherwise
* the `item` will be selected.
* @method select
* @param {any} item: The item to select.
*/
select: function(item) {
if (this.multi) {
this.toggle(item);
} else if (this.getSelection() !== item) {
this.setItemSelected(this.getSelection(), false);
this.setItemSelected(item, true);
}
},
/**
* Toggles the selection state for `item`.
* @method toggle
* @param {any} item: The item to toggle.
*/
toggle: function(item) {
this.setItemSelected(item, !this.isSelected(item));
}
});
</script>
</polymer-element>
<!DOCTYPE html>
<!--
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>
<title>Selection</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-selection.html">
</head>
<body unresolved>
<polymer-element name="selection-example">
<template>
<style>
polyfill-next-selector { content: 'ul > *'; }
::content > * {
cursor: pointer;
}
polyfill-next-selector { content: 'ul > .selected'; }
::content > .selected {
font-weight: bold;
font-style: italic;
}
</style>
<ul on-tap="{{itemTapAction}}">
<content></content>
</ul>
<core-selection id="selection" multi on-core-select="{{selectAction}}"></core-selection>
</template>
<script>
Polymer('selection-example', {
itemTapAction: function(e, detail, sender) {
this.$.selection.select(e.target);
},
selectAction: function(e, detail, sender) {
detail.item.classList.toggle('selected', detail.isSelected);
}
});
</script>
</polymer-element>
<selection-example>
<li>Red</li>
<li>Green</li>
<li>Blue</li>
</selection-example>
</body>
</html>
<!doctype html>
<!--
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
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
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
-->
<html>
<head>
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page></core-component-page>
</body>
</html>
{
"name": "core-selector",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-selection": "Polymer/core-selection#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
},
"homepage": "https://github.com/Polymer/core-selector",
"version": "0.4.1",
"_release": "0.4.1",
"_resolution": {
"type": "version",
"tag": "0.4.1",
"commit": "7d2a5d5b127d0ed3feb7bcb0bdaaeb95c4499cc9"
},
"_source": "git://github.com/Polymer/core-selector.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-selector"
}
\ No newline at end of file
core-selector
==============
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-selector) for more information.
{
"name": "core-selector",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-selection": "Polymer/core-selection#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
}
}
\ No newline at end of file
<!--
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
-->
<!--
@group Polymer Core Elements
`<core-selector>` is used to manage a list of elements that can be selected.
The attribute `selected` indicates which item element is being selected.
The attribute `multi` indicates if multiple items can be selected at once.
Tapping on the item element would fire `core-activate` event. Use
`core-select` event to listen for selection changes.
Example:
<core-selector selected="0">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</core-selector>
`<core-selector>` is not styled. Use the `core-selected` CSS class to style the selected element.
<style>
.item.core-selected {
background: #eee;
}
</style>
...
<core-selector>
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</core-selector>
@element core-selector
@status stable
@homepage github.io
-->
<!--
Fired when an item's selection state is changed. This event is fired both
when an item is selected or deselected. The `isSelected` detail property
contains the selection state.
@event core-select
@param {Object} detail
@param {boolean} detail.isSelected true for selection and false for deselection
@param {Object} detail.item the item element
-->
<!--
Fired when an item element is tapped.
@event core-activate
@param {Object} detail
@param {Object} detail.item the item element
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../core-selection/core-selection.html">
<polymer-element name="core-selector"
attributes="selected multi valueattr selectedClass selectedProperty selectedAttribute selectedItem selectedModel selectedIndex notap excludedLocalNames target itemsSelector activateEvent">
<template>
<core-selection id="selection" multi="{{multi}}" on-core-select="{{selectionSelect}}"></core-selection>
<content id="items" select="*"></content>
</template>
<script>
Polymer('core-selector', {
/**
* Gets or sets the selected element. Default to use the index
* of the item element.
*
* If you want a specific attribute value of the element to be
* used instead of index, set "valueattr" to that attribute name.
*
* Example:
*
* <core-selector valueattr="label" selected="foo">
* <div label="foo"></div>
* <div label="bar"></div>
* <div label="zot"></div>
* </core-selector>
*
* In multi-selection this should be an array of values.
*
* Example:
*
* <core-selector id="selector" valueattr="label" multi>
* <div label="foo"></div>
* <div label="bar"></div>
* <div label="zot"></div>
* </core-selector>
*
* this.$.selector.selected = ['foo', 'zot'];
*
* @attribute selected
* @type Object
* @default null
*/
selected: null,
/**
* If true, multiple selections are allowed.
*
* @attribute multi
* @type boolean
* @default false
*/
multi: false,
/**
* Specifies the attribute to be used for "selected" attribute.
*
* @attribute valueattr
* @type string
* @default 'name'
*/
valueattr: 'name',
/**
* Specifies the CSS class to be used to add to the selected element.
*
* @attribute selectedClass
* @type string
* @default 'core-selected'
*/
selectedClass: 'core-selected',
/**
* Specifies the property to be used to set on the selected element
* to indicate its active state.
*
* @attribute selectedProperty
* @type string
* @default ''
*/
selectedProperty: '',
/**
* Specifies the attribute to set on the selected element to indicate
* its active state.
*
* @attribute selectedAttribute
* @type string
* @default 'active'
*/
selectedAttribute: 'active',
/**
* Returns the currently selected element. In multi-selection this returns
* an array of selected elements.
* Note that you should not use this to set the selection. Instead use
* `selected`.
*
* @attribute selectedItem
* @type Object
* @default null
*/
selectedItem: null,
/**
* In single selection, this returns the model associated with the
* selected element.
* Note that you should not use this to set the selection. Instead use
* `selected`.
*
* @attribute selectedModel
* @type Object
* @default null
*/
selectedModel: null,
/**
* In single selection, this returns the selected index.
* Note that you should not use this to set the selection. Instead use
* `selected`.
*
* @attribute selectedIndex
* @type number
* @default -1
*/
selectedIndex: -1,
/**
* Nodes with local name that are in the list will not be included
* in the selection items. In the following example, `items` returns four
* `core-item`'s and doesn't include `h3` and `hr`.
*
* <core-selector excludedLocalNames="h3 hr">
* <h3>Header</h3>
* <core-item>Item1</core-item>
* <core-item>Item2</core-item>
* <hr>
* <core-item>Item3</core-item>
* <core-item>Item4</core-item>
* </core-selector>
*
* @attribute excludedLocalNames
* @type string
* @default ''
*/
excludedLocalNames: '',
/**
* The target element that contains items. If this is not set
* core-selector is the container.
*
* @attribute target
* @type Object
* @default null
*/
target: null,
/**
* This can be used to query nodes from the target node to be used for
* selection items. Note this only works if `target` is set
* and is not `core-selector` itself.
*
* Example:
*
* <core-selector target="{{$.myForm}}" itemsSelector="input[type=radio]"></core-selector>
* <form id="myForm">
* <label><input type="radio" name="color" value="red"> Red</label> <br>
* <label><input type="radio" name="color" value="green"> Green</label> <br>
* <label><input type="radio" name="color" value="blue"> Blue</label> <br>
* <p>color = {{color}}</p>
* </form>
*
* @attribute itemsSelector
* @type string
* @default ''
*/
itemsSelector: '',
/**
* The event that would be fired from the item element to indicate
* it is being selected.
*
* @attribute activateEvent
* @type string
* @default 'tap'
*/
activateEvent: 'tap',
/**
* Set this to true to disallow changing the selection via the
* `activateEvent`.
*
* @attribute notap
* @type boolean
* @default false
*/
notap: false,
defaultExcludedLocalNames: 'template',
ready: function() {
this.activateListener = this.activateHandler.bind(this);
this.itemFilter = this.filterItem.bind(this);
this.excludedLocalNamesChanged();
this.observer = new MutationObserver(this.updateSelected.bind(this));
if (!this.target) {
this.target = this;
}
},
/**
* Returns an array of all items.
*
* @property items
*/
get items() {
if (!this.target) {
return [];
}
var nodes = this.target !== this ? (this.itemsSelector ?
this.target.querySelectorAll(this.itemsSelector) :
this.target.children) : this.$.items.getDistributedNodes();
return Array.prototype.filter.call(nodes, this.itemFilter);
},
filterItem: function(node) {
return !this._excludedNames[node.localName];
},
excludedLocalNamesChanged: function() {
this._excludedNames = {};
var s = this.defaultExcludedLocalNames;
if (this.excludedLocalNames) {
s += ' ' + this.excludedLocalNames;
}
s.split(/\s+/g).forEach(function(n) {
this._excludedNames[n] = 1;
}, this);
},
targetChanged: function(old) {
if (old) {
this.removeListener(old);
this.observer.disconnect();
this.clearSelection();
}
if (this.target) {
this.addListener(this.target);
this.observer.observe(this.target, {childList: true});
this.updateSelected();
}
},
addListener: function(node) {
Polymer.addEventListener(node, this.activateEvent, this.activateListener);
},
removeListener: function(node) {
Polymer.removeEventListener(node, this.activateEvent, this.activateListener);
},
/**
* Returns the selected item(s). If the `multi` property is true,
* this will return an array, otherwise it will return
* the selected item or undefined if there is no selection.
*/
get selection() {
return this.$.selection.getSelection();
},
selectedChanged: function() {
this.updateSelected();
},
updateSelected: function() {
this.validateSelected();
if (this.multi) {
this.clearSelection();
this.selected && this.selected.forEach(function(s) {
this.valueToSelection(s);
}, this);
} else {
this.valueToSelection(this.selected);
}
},
validateSelected: function() {
// convert to an array for multi-selection
if (this.multi && !Array.isArray(this.selected) &&
this.selected !== null && this.selected !== undefined) {
this.selected = [this.selected];
}
},
clearSelection: function() {
if (this.multi) {
this.selection.slice().forEach(function(s) {
this.$.selection.setItemSelected(s, false);
}, this);
} else {
this.$.selection.setItemSelected(this.selection, false);
}
this.selectedItem = null;
this.$.selection.clear();
},
valueToSelection: function(value) {
var item = (value === null || value === undefined) ?
null : this.items[this.valueToIndex(value)];
this.$.selection.select(item);
},
updateSelectedItem: function() {
this.selectedItem = this.selection;
},
selectedItemChanged: function() {
if (this.selectedItem) {
var t = this.selectedItem.templateInstance;
this.selectedModel = t ? t.model : undefined;
} else {
this.selectedModel = null;
}
this.selectedIndex = this.selectedItem ?
parseInt(this.valueToIndex(this.selected)) : -1;
},
valueToIndex: function(value) {
// find an item with value == value and return it's index
for (var i=0, items=this.items, c; (c=items[i]); i++) {
if (this.valueForNode(c) == value) {
return i;
}
}
// if no item found, the value itself is probably the index
return value;
},
valueForNode: function(node) {
return node[this.valueattr] || node.getAttribute(this.valueattr);
},
// events fired from <core-selection> object
selectionSelect: function(e, detail) {
this.updateSelectedItem();
if (detail.item) {
this.applySelection(detail.item, detail.isSelected);
}
},
applySelection: function(item, isSelected) {
if (this.selectedClass) {
item.classList.toggle(this.selectedClass, isSelected);
}
if (this.selectedProperty) {
item[this.selectedProperty] = isSelected;
}
if (this.selectedAttribute && item.setAttribute) {
if (isSelected) {
item.setAttribute(this.selectedAttribute, '');
} else {
item.removeAttribute(this.selectedAttribute);
}
}
},
// event fired from host
activateHandler: function(e) {
if (!this.notap) {
var i = this.findDistributedTarget(e.target, this.items);
if (i >= 0) {
var item = this.items[i];
var s = this.valueForNode(item) || i;
if (this.multi) {
if (this.selected) {
this.addRemoveSelected(s);
} else {
this.selected = [s];
}
} else {
this.selected = s;
}
this.asyncFire('core-activate', {item: item});
}
}
},
addRemoveSelected: function(value) {
var i = this.selected.indexOf(value);
if (i >= 0) {
this.selected.splice(i, 1);
} else {
this.selected.push(value);
}
this.valueToSelection(value);
},
findDistributedTarget: function(target, nodes) {
// find first ancestor of target (including itself) that
// is in nodes, if any
while (target && target != this) {
var i = Array.prototype.indexOf.call(nodes, target);
if (i >= 0) {
return i;
}
target = target.parentNode;
}
},
selectIndex: function(index) {
var item = this.items[index];
if (item) {
this.selected = this.valueForNode(item) || index;
return item;
}
},
/**
* Selects the previous item. This should be used in single selection only.
*
* @method selectPrevious
* @param {boolean} wrap if true and it is already at the first item, wrap to the end
* @returns the previous item or undefined if there is none
*/
selectPrevious: function(wrap) {
var i = wrap && !this.selectedIndex ? this.items.length - 1 : this.selectedIndex - 1;
return this.selectIndex(i);
},
/**
* Selects the next item. This should be used in single selection only.
*
* @method selectNext
* @param {boolean} wrap if true and it is already at the last item, wrap to the front
* @returns the next item or undefined if there is none
*/
selectNext: function(wrap) {
var i = wrap && this.selectedIndex >= this.items.length - 1 ? 0 : this.selectedIndex + 1;
return this.selectIndex(i);
}
});
</script>
</polymer-element>
<!DOCTYPE html>
<!--
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>
<title>Selector</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-selector.html">
</head>
<body unresolved>
<polymer-element name="selector-examples">
<template>
<style>
.list {
display: block;
border: 1px solid #ccc;
border-bottom: none;
background: #666;
color: white;
list-style: none;
margin: 0;
padding: 0;
}
.list > * {
height: 40px;
line-height: 40px;
padding: 0 20px;
border-bottom: 1px solid #ccc;
}
.list > *.core-selected {
background: #333;
}
li {
height: 30px;
}
li.core-selected:after {
content: "\2713";
position: absolute;
padding-left: 10px;
}
</style>
<h2>basic</h2>
<core-selector class="list" selected="0">
<div>Item 0</div>
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
</core-selector>
<h2>multi-selection</h2>
<core-selector class="list" selected="{{multiSelected}}" multi>
<div>Item 0</div>
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
</core-selector>
<h2>list</h2>
<core-selector target="{{$.list}}" selected="0"></core-selector>
<ul id="list">
<li>Item 0</li>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
<h2>binding of a group of radio buttons to a variable</h2>
<core-selector target="{{$.myForm}}" itemsSelector="input[type=radio]"
selected="{{color}}" valueattr="value" selectedProperty="checked"
activateEvent="change"></core-selector>
<form id="myForm">
<label><input type="radio" name="color" value="red"> Red</label> <br>
<label><input type="radio" name="color" value="green"> Green</label> <br>
<label><input type="radio" name="color" value="blue"> Blue</label> <br>
<p>color = {{color}}</p>
</form>
</template>
<script>
Polymer('selector-examples', {
ready: function() {
this.multiSelected = [1, 3];
this.color = 'green';
}
});
</script>
</polymer-element>
<selector-examples></selector-examples>
</body>
</html>
<!doctype html>
<!--
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
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
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
-->
<html>
<head>
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page></core-component-page>
</body>
</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
-->
<x-meta id="core-selector" label="Selector" group="Core" isContainer>
<template>
<core-selector selected="0" style="width:100%;height:50px;"></core-selector>
</template>
<template>
<link rel="import" href="core-selector.html">
</template>
</x-meta>
\ No newline at end of file
{
"name": "paper-ripple",
"private": true,
"dependencies": {
"core-icon": "Polymer/core-icon#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"font-roboto": "Polymer/font-roboto#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools"
},
"homepage": "https://github.com/Polymer/paper-ripple",
"version": "0.4.1",
"_release": "0.4.1",
"_resolution": {
"type": "version",
"tag": "0.4.1",
"commit": "1a6458e7495c8f640651a5c42019f51eeb458e29"
},
"_source": "git://github.com/Polymer/paper-ripple.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/paper-ripple"
}
\ No newline at end of file
paper-ripple
============
See the [component page](http://www.polymer-project.org/docs/elements/paper-elements.html#paper-ripple) for more information.
{
"name": "paper-ripple",
"private": true,
"dependencies": {
"core-icon": "Polymer/core-icon#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"font-roboto": "Polymer/font-roboto#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools"
}
}
\ No newline at end of file
<!--
@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
-->
<!doctype html>
<html>
<head>
<title>paper-ripple</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-icons/core-icons.html">
<link rel="import" href="paper-ripple.html">
<link rel="import" href="../font-roboto/roboto.html">
<link rel="import" href="../core-icon/core-icon.html">
<style shim-shadowdom>
body {
background-color: #f9f9f9;
font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-touch-callout: none;
}
section {
padding: 30px 25px;
}
section > * {
margin: 10px
}
/* Button */
.button {
display: inline-block;
position: relative;
width: 120px;
height: 32px;
line-height: 32px;
border-radius: 2px;
font-size: 0.9em;
background-color: #fff;
color: #646464;
}
.button > paper-ripple {
border-radius: 2px;
overflow: hidden;
}
.button.narrow {
width: 60px;
}
.button.grey {
background-color: #eee;
}
.button.blue {
background-color: #4285f4;
color: #fff;
}
.button.green {
background-color: #0f9d58;
color: #fff;
}
.button.raised {
transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);
transition-delay: 0.2s;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
}
.button.raised:active {
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2);
transition-delay: 0s;
}
/* Icon Button */
.icon-button {
position: relative;
display: inline-block;
width: 56px;
height: 56px;
}
.icon-button > core-icon {
margin: 16px;
transition: -webkit-transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.icon-button:hover > core-icon {
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
.icon-button > paper-ripple {
overflow: hidden;
color: #646464;
}
.icon-button.red > core-icon::shadow path {
fill: #db4437;
}
.icon-button.red > paper-ripple {
color: #db4437;
}
.icon-button.blue > core-icon::shadow path {
fill: #4285f4;
}
.icon-button.blue > paper-ripple {
color: #4285f4;
}
/* FAB */
.fab {
position: relative;
display: inline-block;
width: 56px;
height: 56px;
border-radius: 50%;
color: #fff;
overflow: hidden;
transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);
transition-delay: 0.2s;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
}
.fab.red {
background-color: #d23f31;
}
.fab.blue {
background-color: #4285f4;
}
.fab.green {
background-color: #0f9d58;
}
.fab:active {
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2);
transition-delay: 0s;
}
.fab > core-icon {
margin: 16px;
}
.fab > core-icon::shadow path {
fill: #fff;
}
/* Menu */
.menu {
display: inline-block;
width: 180px;
background-color: #fff;
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2);
}
.item {
position: relative;
height: 48px;
line-height: 48px;
color: #646464;
font-size: 0.9em;
}
.menu.blue > .item {
color: #4285f4;
}
/* Card, Dialog */
.card, .dialog {
position: relative;
display: inline-block;
width: 300px;
height: 240px;
vertical-align: top;
background-color: #fff;
box-shadow: 0 12px 15px 0 rgba(0, 0, 0, 0.24);
}
.dialog {
box-sizing: border-box;
padding: 16px;
}
.dialog > .content {
height: 170px;
font-size: 0.9em;
}
.dialog > .content > .title {
font-size: 1.3em;
}
.dialog > .button {
width: 90px;
float: right;
}
.card.image {
background: url(http://lorempixel.com/300/240/nature/);
color: #fff;
}
/* Misc */
.center {
text-align: center;
}
.label {
padding: 0 16px;
}
.label-blue {
color: #4285f4;
}
.label-red {
color: #d23f31;
}
</style>
</head>
<body unresolved>
<section>
<div class="button raised">
<div class="center" fit>SUBMIT</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="button raised grey">
<div class="center" fit>CANCEL</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="button raised blue">
<div class="center" fit>COMPOSE</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="button raised green">
<div class="center" fit>OK</div>
<paper-ripple fit></paper-ripple>
</div>
</section>
<section>
<div class="button raised grey narrow">
<div class="center" fit>+1</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="button raised grey narrow label-blue">
<div class="center" fit>+1</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="button raised grey narrow label-red">
<div class="center" fit>+1</div>
<paper-ripple fit></paper-ripple>
</div>
</section>
<section>
<div class="icon-button">
<core-icon icon="menu"></core-icon>
<paper-ripple class="circle recenteringTouch" fit></paper-ripple>
</div>
<div class="icon-button">
<core-icon icon="more-vert"></core-icon>
<paper-ripple class="circle recenteringTouch" fit></paper-ripple>
</div>
<div class="icon-button red">
<core-icon icon="delete"></core-icon>
<paper-ripple class="circle recenteringTouch" fit></paper-ripple>
</div>
<div class="icon-button blue">
<core-icon icon="account-box"></core-icon>
<paper-ripple class="circle recenteringTouch" fit></paper-ripple>
</div>
</section>
<section>
<div class="fab red">
<core-icon icon="add"></core-icon>
<paper-ripple class="circle recenteringTouch" fit></paper-ripple>
</div>
<div class="fab blue">
<core-icon icon="mail"></core-icon>
<paper-ripple class="circle recenteringTouch" fit></paper-ripple>
</div>
<div class="fab green">
<core-icon icon="create"></core-icon>
<paper-ripple class="circle recenteringTouch" fit></paper-ripple>
</div>
</section>
<section>
<div class="menu">
<div class="item">
<div class="label" fit>Mark as unread</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="item">
<div class="label" fit>Mark as important</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="item">
<div class="label" fit>Add to Tasks</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="item">
<div class="label" fit>Create event</div>
<paper-ripple fit></paper-ripple>
</div>
</div>
<div class="menu blue">
<div class="item">
<div class="label" fit>Import</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="item">
<div class="label" fit>Export</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="item">
<div class="label" fit>Print</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="item">
<div class="label" fit>Restore contacts</div>
<paper-ripple fit></paper-ripple>
</div>
</div>
</section>
<section>
<div class="dialog">
<div class="content">
<div class="title">Permission</div><br>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</div>
</div>
<div class="button label-blue">
<div class="center" fit>ACCEPT</div>
<paper-ripple fit></paper-ripple>
</div>
<div class="button">
<div class="center" fit>DECLINE</div>
<paper-ripple fit></paper-ripple>
</div>
</div>
<div class="card">
<paper-ripple class="recenteringTouch" fit></paper-ripple>
</div>
<div class="card image">
<paper-ripple class="recenteringTouch" fit></paper-ripple>
</div>
</section>
</body>
</html>
<!doctype html>
<!--
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
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
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
-->
<html>
<head>
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page></core-component-page>
</body>
</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
-->
<x-meta id="paper-ripple" label="Ripple" group="Paper">
<template>
<paper-ripple style="width: 300px; height: 300px;"></paper-ripple>
</template>
<template id="imports">
<link rel="import" href="paper-ripple.html">
</template>
</x-meta>
<!--
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
-->
<!--
`paper-ripple` provides a visual effect that other paper elements can
use to simulate a rippling effect emanating from the point of contact. The
effect can be visualized as a concentric circle with motion.
Example:
<paper-ripple></paper-ripple>
`paper-ripple` listens to "down" and "up" events so it would display ripple
effect when touches on it. You can also defeat the default behavior and
manually route the down and up actions to the ripple element. Note that it is
important if you call downAction() you will have to make sure to call upAction()
so that `paper-ripple` would end the animation loop.
Example:
<paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple>
...
downAction: function(e) {
this.$.ripple.downAction({x: e.x, y: e.y});
},
upAction: function(e) {
this.$.ripple.upAction();
}
Styling ripple effect:
Use CSS color property to style the ripple:
paper-ripple {
color: #4285f4;
}
Note that CSS color property is inherited so it is not required to set it on
the `paper-ripple` element directly.
Apply `recenteringTouch` class to make the recentering rippling effect.
<paper-ripple class="recenteringTouch"></paper-ripple>
Apply `circle` class to make the rippling effect within a circle.
<paper-ripple class="circle"></paper-ripple>
@group Paper Elements
@element paper-ripple
@homepage github.io
-->
<link rel="import" href="../polymer/polymer.html" >
<polymer-element name="paper-ripple" attributes="initialOpacity opacityDecayVelocity">
<template>
<style>
:host {
display: block;
position: relative;
}
:host-context([noink]) {
pointer-events: none;
}
#bg, #waves, .wave-container, .wave {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#bg, .wave {
opacity: 0;
}
#waves, .wave {
overflow: hidden;
}
.wave-container, .wave {
border-radius: 50%;
}
:host(.circle) #bg,
:host(.circle) #waves {
border-radius: 50%;
}
:host(.circle) .wave-container {
overflow: hidden;
}
</style>
<div id="bg"></div>
<div id="waves">
</div>
</template>
<script>
(function() {
var waveMaxRadius = 150;
//
// INK EQUATIONS
//
function waveRadiusFn(touchDownMs, touchUpMs, anim) {
// Convert from ms to s.
var touchDown = touchDownMs / 1000;
var touchUp = touchUpMs / 1000;
var totalElapsed = touchDown + touchUp;
var ww = anim.width, hh = anim.height;
// use diagonal size of container to avoid floating point math sadness
var waveRadius = Math.min(Math.sqrt(ww * ww + hh * hh), waveMaxRadius) * 1.1 + 5;
var duration = 1.1 - .2 * (waveRadius / waveMaxRadius);
var tt = (totalElapsed / duration);
var size = waveRadius * (1 - Math.pow(80, -tt));
return Math.abs(size);
}
function waveOpacityFn(td, tu, anim) {
// Convert from ms to s.
var touchDown = td / 1000;
var touchUp = tu / 1000;
var totalElapsed = touchDown + touchUp;
if (tu <= 0) { // before touch up
return anim.initialOpacity;
}
return Math.max(0, anim.initialOpacity - touchUp * anim.opacityDecayVelocity);
}
function waveOuterOpacityFn(td, tu, anim) {
// Convert from ms to s.
var touchDown = td / 1000;
var touchUp = tu / 1000;
// Linear increase in background opacity, capped at the opacity
// of the wavefront (waveOpacity).
var outerOpacity = touchDown * 0.3;
var waveOpacity = waveOpacityFn(td, tu, anim);
return Math.max(0, Math.min(outerOpacity, waveOpacity));
}
// Determines whether the wave should be completely removed.
function waveDidFinish(wave, radius, anim) {
var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
// If the wave opacity is 0 and the radius exceeds the bounds
// of the element, then this is finished.
return waveOpacity < 0.01 && radius >= Math.min(wave.maxRadius, waveMaxRadius);
};
function waveAtMaximum(wave, radius, anim) {
var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp, anim);
return waveOpacity >= anim.initialOpacity && radius >= Math.min(wave.maxRadius, waveMaxRadius);
}
//
// DRAWING
//
function drawRipple(ctx, x, y, radius, innerAlpha, outerAlpha) {
// Only animate opacity and transform
if (outerAlpha !== undefined) {
ctx.bg.style.opacity = outerAlpha;
}
ctx.wave.style.opacity = innerAlpha;
var s = radius / (ctx.containerSize / 2);
var dx = x - (ctx.containerWidth / 2);
var dy = y - (ctx.containerHeight / 2);
ctx.wc.style.webkitTransform = 'translate3d(' + dx + 'px,' + dy + 'px,0)';
ctx.wc.style.transform = 'translate3d(' + dx + 'px,' + dy + 'px,0)';
// 2d transform for safari because of border-radius and overflow:hidden clipping bug.
// https://bugs.webkit.org/show_bug.cgi?id=98538
ctx.wave.style.webkitTransform = 'scale(' + s + ',' + s + ')';
ctx.wave.style.transform = 'scale3d(' + s + ',' + s + ',1)';
}
//
// SETUP
//
function createWave(elem) {
var elementStyle = window.getComputedStyle(elem);
var fgColor = elementStyle.color;
var inner = document.createElement('div');
inner.style.backgroundColor = fgColor;
inner.classList.add('wave');
var outer = document.createElement('div');
outer.classList.add('wave-container');
outer.appendChild(inner);
var container = elem.$.waves;
container.appendChild(outer);
elem.$.bg.style.backgroundColor = fgColor;
var wave = {
bg: elem.$.bg,
wc: outer,
wave: inner,
waveColor: fgColor,
maxRadius: 0,
isMouseDown: false,
mouseDownStart: 0.0,
mouseUpStart: 0.0,
tDown: 0,
tUp: 0
};
return wave;
}
function removeWaveFromScope(scope, wave) {
if (scope.waves) {
var pos = scope.waves.indexOf(wave);
scope.waves.splice(pos, 1);
// FIXME cache nodes
wave.wc.remove();
}
};
// Shortcuts.
var pow = Math.pow;
var now = Date.now;
if (window.performance && performance.now) {
now = performance.now.bind(performance);
}
function cssColorWithAlpha(cssColor, alpha) {
var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
if (typeof alpha == 'undefined') {
alpha = 1;
}
if (!parts) {
return 'rgba(255, 255, 255, ' + alpha + ')';
}
return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')';
}
function dist(p1, p2) {
return Math.sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
}
function distanceFromPointToFurthestCorner(point, size) {
var tl_d = dist(point, {x: 0, y: 0});
var tr_d = dist(point, {x: size.w, y: 0});
var bl_d = dist(point, {x: 0, y: size.h});
var br_d = dist(point, {x: size.w, y: size.h});
return Math.max(tl_d, tr_d, bl_d, br_d);
}
Polymer('paper-ripple', {
/**
* The initial opacity set on the wave.
*
* @attribute initialOpacity
* @type number
* @default 0.25
*/
initialOpacity: 0.25,
/**
* How fast (opacity per second) the wave fades out.
*
* @attribute opacityDecayVelocity
* @type number
* @default 0.8
*/
opacityDecayVelocity: 0.8,
backgroundFill: true,
pixelDensity: 2,
eventDelegates: {
down: 'downAction',
up: 'upAction'
},
ready: function() {
this.waves = [];
},
downAction: function(e) {
var wave = createWave(this);
this.cancelled = false;
wave.isMouseDown = true;
wave.tDown = 0.0;
wave.tUp = 0.0;
wave.mouseUpStart = 0.0;
wave.mouseDownStart = now();
var rect = this.getBoundingClientRect();
var width = rect.width;
var height = rect.height;
var touchX = e.x - rect.left;
var touchY = e.y - rect.top;
wave.startPosition = {x:touchX, y:touchY};
if (this.classList.contains("recenteringTouch")) {
wave.endPosition = {x: width / 2, y: height / 2};
wave.slideDistance = dist(wave.startPosition, wave.endPosition);
}
wave.containerSize = Math.max(width, height);
wave.containerWidth = width;
wave.containerHeight = height;
wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, {w: width, h: height});
// The wave is circular so constrain its container to 1:1
wave.wc.style.top = (wave.containerHeight - wave.containerSize) / 2 + 'px';
wave.wc.style.left = (wave.containerWidth - wave.containerSize) / 2 + 'px';
wave.wc.style.width = wave.containerSize + 'px';
wave.wc.style.height = wave.containerSize + 'px';
this.waves.push(wave);
if (!this._loop) {
this._loop = this.animate.bind(this, {
width: width,
height: height
});
requestAnimationFrame(this._loop);
}
// else there is already a rAF
},
upAction: function() {
for (var i = 0; i < this.waves.length; i++) {
// Declare the next wave that has mouse down to be mouse'ed up.
var wave = this.waves[i];
if (wave.isMouseDown) {
wave.isMouseDown = false
wave.mouseUpStart = now();
wave.mouseDownStart = 0;
wave.tUp = 0.0;
break;
}
}
this._loop && requestAnimationFrame(this._loop);
},
cancel: function() {
this.cancelled = true;
},
animate: function(ctx) {
var shouldRenderNextFrame = false;
var deleteTheseWaves = [];
// The oldest wave's touch down duration
var longestTouchDownDuration = 0;
var longestTouchUpDuration = 0;
// Save the last known wave color
var lastWaveColor = null;
// wave animation values
var anim = {
initialOpacity: this.initialOpacity,
opacityDecayVelocity: this.opacityDecayVelocity,
height: ctx.height,
width: ctx.width
}
for (var i = 0; i < this.waves.length; i++) {
var wave = this.waves[i];
if (wave.mouseDownStart > 0) {
wave.tDown = now() - wave.mouseDownStart;
}
if (wave.mouseUpStart > 0) {
wave.tUp = now() - wave.mouseUpStart;
}
// Determine how long the touch has been up or down.
var tUp = wave.tUp;
var tDown = wave.tDown;
longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown);
longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp);
// Obtain the instantenous size and alpha of the ripple.
var radius = waveRadiusFn(tDown, tUp, anim);
var waveAlpha = waveOpacityFn(tDown, tUp, anim);
var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha);
lastWaveColor = wave.waveColor;
// Position of the ripple.
var x = wave.startPosition.x;
var y = wave.startPosition.y;
// Ripple gravitational pull to the center of the canvas.
if (wave.endPosition) {
// This translates from the origin to the center of the view based on the max dimension of
var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) );
x += translateFraction * (wave.endPosition.x - wave.startPosition.x);
y += translateFraction * (wave.endPosition.y - wave.startPosition.y);
}
// If we do a background fill fade too, work out the correct color.
var bgFillColor = null;
if (this.backgroundFill) {
var bgFillAlpha = waveOuterOpacityFn(tDown, tUp, anim);
bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha);
}
// Draw the ripple.
drawRipple(wave, x, y, radius, waveAlpha, bgFillAlpha);
// Determine whether there is any more rendering to be done.
var maximumWave = waveAtMaximum(wave, radius, anim);
var waveDissipated = waveDidFinish(wave, radius, anim);
var shouldKeepWave = !waveDissipated || maximumWave;
var shouldRenderWaveAgain = !waveDissipated && !maximumWave;
shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain;
if (!shouldKeepWave || this.cancelled) {
deleteTheseWaves.push(wave);
}
}
if (shouldRenderNextFrame) {
requestAnimationFrame(this._loop);
}
for (var i = 0; i < deleteTheseWaves.length; ++i) {
var wave = deleteTheseWaves[i];
removeWaveFromScope(this, wave);
}
if (!this.waves.length && this._loop) {
// clear the background color
this.$.bg.style.backgroundColor = null;
this._loop = null;
this.fire('core-transitionend');
}
}
});
})();
</script>
</polymer-element>
<!--
@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 http-equiv="Content-Type" content="text/html; charset=utf-8">
<script>
//
// INK EQUATIONS
//
// Animation constants.
var globalSpeed = 1;
var waveOpacityDecayVelocity = 0.8 / globalSpeed; // opacity per second.
var waveInitialOpacity = 0.25;
var waveLingerOnTouchUp = 0.2;
var waveMaxRadius = 150;
// TODOs:
// - rather than max distance to corner, use hypotenuos(sp) (diag)
// - use quadratic for the fall off, move fast at the beginning,
// - on cancel, immediately fade out, reverse the direction
function waveRadiusFn(touchDownMs, touchUpMs, ww, hh) {
// Convert from ms to s.
var touchDown = touchDownMs / 1000;
var touchUp = touchUpMs / 1000;
var totalElapsed = touchDown + touchUp;
var waveRadius = Math.min(Math.max(ww, hh), waveMaxRadius) * 1.1 + 5;
var dduration = 1.1 - .2 * (waveRadius / waveMaxRadius);
var tt = (totalElapsed / dduration);
var ssize = waveRadius * (1 - Math.pow(80, -tt));
return Math.abs(ssize);
}
function waveOpacityFn(td, tu) {
// Convert from ms to s.
var touchDown = td / 1000;
var touchUp = tu / 1000;
var totalElapsed = touchDown + touchUp;
if (tu <= 0) { // before touch up
return waveInitialOpacity;
}
return Math.max(0, waveInitialOpacity - touchUp * waveOpacityDecayVelocity);
}
function waveOuterOpacityFn(td, tu) {
// Convert from ms to s.
var touchDown = td / 1000;
var touchUp = tu / 1000;
// Linear increase in background opacity, capped at the opacity
// of the wavefront (waveOpacity).
var outerOpacity = touchDown * 0.3;
var waveOpacity = waveOpacityFn(td, tu);
return Math.max(0, Math.min(outerOpacity, waveOpacity));
}
function waveGravityToCenterPercentageFn(td, tu, r) {
// Convert from ms to s.
var touchDown = td / 1000;
var touchUp = tu / 1000;
var totalElapsed = touchDown + touchUp;
return Math.min(1.0, touchUp * 6);
}
// Determines whether the wave should be completely removed.
function waveDidFinish(wave, radius) {
var waveOpacity = waveOpacityFn(wave.tDown, wave.tUp);
// Does not linger any more.
// var lingerTimeMs = waveLingerOnTouchUp * 1000;
// If the wave opacity is 0 and the radius exceeds the bounds
// of the element, then this is finished.
if (waveOpacity < 0.01 && radius >= wave.maxRadius) {
return true;
}
return false;
};
//
// DRAWING
//
function animateIcon() {
var el = document.getElementById('button_toolbar0');
el.classList.add('animate');
setTimeout(function(){
el.classList.remove('animate');
el.classList.toggle('selected');
}, 500);
}
function drawRipple(canvas, x, y, radius, innerColor, outerColor, innerColorAlpha, outerColorAlpha) {
var ctx = canvas.getContext('2d');
if (outerColor) {
ctx.fillStyle = outerColor;
ctx.fillRect(0,0,canvas.width, canvas.height);
}
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = innerColor;
ctx.fill();
}
function drawLabel(canvas, label, fontSize, color, alignment) {
var ctx = canvas.getContext('2d');
ctx.font= fontSize + 'px Helvetica';
var metrics = ctx.measureText(label);
var width = metrics.width;
var height = metrics.height;
ctx.fillStyle = color;
var xPos = (canvas.width/2 - width)/2;
if (alignment === 'left') { xPos = 16; }
ctx.fillText(label, xPos, canvas.height/2 - (canvas.height/2 - fontSize +2) / 2);
}
//
// BUTTON SETUP
//
function createWave(elem) {
var elementStyle = window.getComputedStyle(elem);
var fgColor = elementStyle.color;
var wave = {
waveColor: fgColor,
maxRadius: 0,
isMouseDown: false,
mouseDownStart: 0.0,
mouseUpStart: 0.0,
tDown: 0,
tUp: 0
};
return wave;
}
function removeWaveFromScope(scope, wave) {
if (scope.waves) {
var pos = scope.waves.indexOf(wave);
scope.waves.splice(pos, 1);
}
};
function setUpPaperByClass( classname ) {
var elems = document.querySelectorAll( classname );
[].forEach.call( elems, function( el ) {
setUpPaper(el);
});
}
function setUpPaper(elem) {
var pixelDensity = 2;
var elementStyle = window.getComputedStyle(elem);
var fgColor = elementStyle.color;
var bgColor = elementStyle.backgroundColor;
elem.width = elem.clientWidth;
elem.setAttribute('width', elem.clientWidth * pixelDensity + "px");
elem.setAttribute('height', elem.clientHeight * pixelDensity + "px");
var isButton = elem.classList.contains( 'button' ) || elem.classList.contains( 'button_floating' ) | elem.classList.contains( 'button_menu' );
var isToolbarButton = elem.classList.contains( 'button_toolbar' );
elem.getContext('2d').scale(pixelDensity, pixelDensity)
var scope = {
backgroundFill: true,
element: elem,
label: 'Button',
waves: [],
};
scope.label = elem.getAttribute('value') || elementStyle.content;
scope.labelFontSize = elementStyle.fontSize.split("px")[0];
drawLabel(elem, scope.label, scope.labelFontSize, fgColor, elem.style.textAlign);
//
// RENDER FOR EACH FRAME
//
var onFrame = function() {
var shouldRenderNextFrame = false;
// Clear the canvas
var ctx = elem.getContext('2d');
ctx.clearRect(0, 0, elem.width, elem.height);
var deleteTheseWaves = [];
// The oldest wave's touch down duration
var longestTouchDownDuration = 0;
var longestTouchUpDuration = 0;
// Save the last known wave color
var lastWaveColor = null;
for (var i = 0; i < scope.waves.length; i++) {
var wave = scope.waves[i];
if (wave.mouseDownStart > 0) {
wave.tDown = now() - wave.mouseDownStart;
}
if (wave.mouseUpStart > 0) {
wave.tUp = now() - wave.mouseUpStart;
}
// Determine how long the touch has been up or down.
var tUp = wave.tUp;
var tDown = wave.tDown;
longestTouchDownDuration = Math.max(longestTouchDownDuration, tDown);
longestTouchUpDuration = Math.max(longestTouchUpDuration, tUp);
// Obtain the instantenous size and alpha of the ripple.
var radius = waveRadiusFn(tDown, tUp, elem.width, elem.height);
var waveAlpha = waveOpacityFn(tDown, tUp);
var waveColor = cssColorWithAlpha(wave.waveColor, waveAlpha);
lastWaveColor = wave.waveColor;
// Position of the ripple.
var x = wave.startPosition.x;
var y = wave.startPosition.y;
// Ripple gravitational pull to the center of the canvas.
if (wave.endPosition) {
var translateFraction = waveGravityToCenterPercentageFn(tDown, tUp, wave.maxRadius);
// This translates from the origin to the center of the view based on the max dimension of
var translateFraction = Math.min(1, radius / wave.containerSize * 2 / Math.sqrt(2) );
x += translateFraction * (wave.endPosition.x - wave.startPosition.x);
y += translateFraction * (wave.endPosition.y - wave.startPosition.y);
}
// If we do a background fill fade too, work out the correct color.
var bgFillColor = null;
if (scope.backgroundFill) {
var bgFillAlpha = waveOuterOpacityFn(tDown, tUp);
bgFillColor = cssColorWithAlpha(wave.waveColor, bgFillAlpha);
}
// Draw the ripple.
drawRipple(elem, x, y, radius, waveColor, bgFillColor);
// Determine whether there is any more rendering to be done.
var shouldRenderWaveAgain = !waveDidFinish(wave, radius);
shouldRenderNextFrame = shouldRenderNextFrame || shouldRenderWaveAgain;
if (!shouldRenderWaveAgain) {
deleteTheseWaves.push(wave);
}
}
if (shouldRenderNextFrame) {
window.requestAnimationFrame(onFrame);
} else {
// If there is nothing to draw, clear any drawn waves now because
// we're not going to get another requestAnimationFrame any more.
var ctx = elem.getContext('2d');
ctx.clearRect(0, 0, elem.width, elem.height);
}
// Draw the label at the very last point so it is on top of everything.
drawLabel(elem, scope.label, scope.labelFontSize, fgColor, elem.style.textAlign);
for (var i = 0; i < deleteTheseWaves.length; ++i) {
var wave = deleteTheseWaves[i];
removeWaveFromScope(scope, wave);
}
};
//
// MOUSE DOWN HANDLER
//
elem.addEventListener('mousedown', function(e) {
var wave = createWave(e.target);
var elem = scope.element;
wave.isMouseDown = true;
wave.tDown = 0.0;
wave.tUp = 0.0;
wave.mouseUpStart = 0.0;
wave.mouseDownStart = now();
var width = e.target.width / 2; // Retina canvas
var height = e.target.height / 2;
var touchX = e.clientX - e.target.offsetLeft - e.target.offsetParent.offsetLeft;
var touchY = e.clientY - e.target.offsetTop - e.target.offsetParent.offsetTop;
wave.startPosition = {x:touchX, y:touchY};
if (elem.classList.contains("recenteringTouch")) {
wave.endPosition = {x: width / 2, y: height / 2};
wave.slideDistance = dist(wave.startPosition, wave.endPosition);
}
wave.containerSize = Math.max(width, height);
wave.maxRadius = distanceFromPointToFurthestCorner(wave.startPosition, {w: width, h: height});
elem.classList.add("activated");
scope.waves.push(wave);
window.requestAnimationFrame(onFrame);
return false;
});
//
// MOUSE UP HANDLER
//
elem.addEventListener('mouseup', function(e) {
elem.classList.remove("activated");
for (var i = 0; i < scope.waves.length; i++) {
// Declare the next wave that has mouse down to be mouse'ed up.
var wave = scope.waves[i];
if (wave.isMouseDown) {
wave.isMouseDown = false
wave.mouseUpStart = now();
wave.mouseDownStart = 0;
wave.tUp = 0.0;
break;
}
}
return false;
});
elem.addEventListener('mouseout', function(e) {
elem.classList.remove("activated");
for (var i = 0; i < scope.waves.length; i++) {
// Declare the next wave that has mouse down to be mouse'ed up.
var wave = scope.waves[i];
if (wave.isMouseDown) {
wave.isMouseDown = false
wave.mouseUpStart = now();
wave.mouseDownStart = 0;
wave.tUp = 0.0;
wave.cancelled = true;
break;
}
}
return false;
});
return scope;
};
// Shortcuts.
var pow = Math.pow;
var now = function() { return new Date().getTime(); };
// Quad beizer where t is between 0 and 1.
function quadBezier(t, p0, p1, p2, p3) {
return pow(1 - t, 3) * p0 +
3 * pow(1 - t, 2) * t * p1 +
(1 - t) * pow(t, 2) * p2 +
pow(t, 3) * p3;
}
function easeIn(t) {
return quadBezier(t, 0.4, 0.0, 1, 1);
}
function cssColorWithAlpha(cssColor, alpha) {
var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
if (typeof alpha == 'undefined') {
alpha = 1;
}
if (!parts) {
return 'rgba(255, 255, 255, ' + alpha + ')';
}
return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')';
}
function dist(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
function distanceFromPointToFurthestCorner(point, size) {
var tl_d = dist(point, {x: 0, y: 0});
var tr_d = dist(point, {x: size.w, y: 0});
var bl_d = dist(point, {x: 0, y: size.h});
var br_d = dist(point, {x: size.w, y: size.h});
return Math.max(Math.max(tl_d, tr_d), Math.max(bl_d, br_d));
}
function toggleDialog() {
var el = document.getElementById('dialog');
el.classList.toggle("visible");
}
function toggleMenu() {
var el = document.getElementById('menu');
el.classList.toggle("visible");
}
// Initialize
function init() {
setUpPaperByClass( '.paper' );
}
window.addEventListener('DOMContentLoaded', init, false);
</script>
<style type="text/css" media="screen">
body {
background-color: #f9f9f9;
margin:0; padding:0;
font-family:sans-serif;
font-size:14px;
}
* {
-webkit-user-select: none;
cursor:default;
}
.toolbar {
background-color:#673AB7;
height:56px;
overflow:hidden;
}
#dialog {
width:250px;
height:120px;
opacity:0.0;
pointer-events:none;
-webkit-transform: scale(0.95) translate3d(0,100px,0);;
-webkit-transition: -webkit-transform 0.3s ease-out, height 0.2s ease-out, opacity 0.2s ease-out, -webkit-box-shadow .5s ease-out;
-webkit-box-shadow:0 10px 10px rgba(0,0,0,0.12), 0 5px 5px rgba(0,0,0,0.24);
-webkit-transition-delay:0.25s;
}
#dialog.visible {
pointer-events:all;
opacity:1.0;
-webkit-transform: scale(1.0) translate3d(0,0,0);;
width:250px;
height:160px;
-webkit-box-shadow:0 19px 19px rgba(0,0,0,0.30), 0 15px 6px rgba(0,0,0,0.22);
-webkit-transition-delay:0.0s;
}
.dialog {
top:120px;
right: 0;
left: 50%;
margin-left:-125px;
padding:24px 16px 20px 24px;
position:absolute;
background:white;
color:rgba(0,0,0,0.5);
margin-bottom:38px;
overflow:hidden;
}
.dialog h1 {
font-size:20px;
font-weight:normal;
padding:0; margin-top:0;
}
.dialog .button {
position:absolute;
top:160px;
right:10px;
}
/*#menu {
width:250px;
height:120px;
opacity:0.0;
pointer-events:none;
-webkit-transform: scale(0.95) translate3d(0,100px,0);;
-webkit-transition: -webkit-transform 0.3s ease-out, height 0.2s ease-out, opacity 0.2s ease-out, -webkit-box-shadow .5s ease-out;
-webkit-box-shadow:0 10px 10px rgba(0,0,0,0.12), 0 5px 5px rgba(0,0,0,0.24);
}
#menu.visible {
pointer-events:all;
opacity:1.0;
-webkit-transform: scale(1.0) translate3d(0,0,0);;
width:250px;
height:160px;
-webkit-box-shadow:0 19px 19px rgba(0,0,0,0.30), 0 15px 6px rgba(0,0,0,0.22);
}*/
.menu {
width:160px;
height:160px;
background:white;
position:absolute;
right:8px;
top: 8px;
padding:0;
opacity:0.0;
pointer-events:none;
-webkit-transform: scale(0.95) translate3d(0,0,0);;
-webkit-transition: -webkit-transform 0.3s ease-out, width 0.2s ease-out, height 0.3s ease-out, opacity 0.1s ease-out, -webkit-box-shadow .5s ease-out;
-webkit-box-shadow:0 10px 10px rgba(0,0,0,0.12), 0 5px 5px rgba(0,0,0,0.24);
-webkit-transition-delay:0.35s;
overflow:hidden;
}
.menu.visible {
width:180px;
height:192px;
pointer-events:all;
opacity:1.0;
-webkit-transform: scale(1.0) translate3d(0,0,0);;
-webkit-box-shadow:0 10px 10px rgba(0,0,0,0.12), 0 5px 5px rgba(0,0,0,0.24);
-webkit-transition-delay:0.15s;
}
.menu div {
height:48px;
padding:0;
}
.menu canvas {
height:48px;
width: 100%;
}
.button_floating {
width:56px;
height:56px;
color:#fff;
background-color:#039BE5;
border-radius:28px;
position:absolute;
top:388px;
right:40px;
}
.container {
}
.button {
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
.button_menu.container {
margin: 0px;
height: 48px;
padding: 0;
}
.button_menu {
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
text-align:left !important;
color:rgb(100,100,100);
}
.button_toolbar {
-webkit-border-radius: 84px;
color: rgb(255,255,255);
width: 80px;
height: 80px;
float:left;
margin-right:-24px;
margin-top:-12px;
background-color: rgba(0, 0, 0, 0);
}
#button_small {
color: rgb(100, 100, 100);
background-color: #ffffff;
width: 80px;
height: 32px;
}
#button_blue {
color: rgb(255, 255, 255);
background-color: #0277BD;
width: 80px;
height: 32px;
}
#button_borderless_square {
color: #ffffff;
background-color: #f9f9f9;
border: 1px solid #f0f0f0;
width: 100px;
height: 100px;
background-color: rgb(255, 255, 255, 0);
background-image:url(http://wallpaperandbackground.com/wp-content/uploads/2014/03/Field-Landscape.jpg);
background-size:cover;
}
#button_borderless {
color: #777777;
background-color: #ffffff;
width:80px;
height: 32px;
margin-right:72px;
content: "CANCEL";
}
#button_borderless_blue {
color: #4285F4;
background-color: #ffffff;
width: 64px;
height: 32px;
content:"OK";
}
#button_large {
color: rgb(255, 255, 255);
width: 100%;
height: 360px;
background-color:#81D4FA;
}
#button_toolbar1 {
content: '';
color:transparent;
margin-left:-4px;
}
#button_toolbar2 {
content: '★';
float:right;
}
#button_toolbar3 {
content: 'MENU';
font-size: 14px;
width: 88px;
height:88px;
margin-top: -16px;
color:#7FFFFF;
float:right;
margin-right:0;
}
.caption {
z-index: 100;
background-color: red;
}
#button_toolbar0.animate {
-webkit-animation: play 0.5s steps(16);
}
.button.raised {
-webkit-transition: -webkit-box-shadow 0.2s;
-webkit-transition-delay: 0.2s;
-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24);
}
.button.raised.activated {
-webkit-box-shadow: 0px 10px 10px rgba(0,0,0,0.19), 0px 6px 3px rgba(0,0,0,0.23);
-webkit-transition-delay: 0.0s;
}
.floating {
-webkit-transition: -webkit-box-shadow 0.2s;
-webkit-transition-delay: 0.2s;
-webkit-box-shadow:0 3px 3px rgba(0,0,0,0.16), 0 3px 3px rgba(0,0,0,0.23);
}
.floating.activated {
-webkit-box-shadow: 0px 14px 14px rgba(0,0,0,0.25), 0px 10px 5px rgba(0,0,0,0.22);
-webkit-transition-delay: 0.0s;
}
#title {
color:white;
font-size:20px;
line-height:58px;
margin-left:24px;
}
.content {
padding-left:72px; padding-top:24px; padding-right:144px;
line-height:20px;
color:#666;
}
@-webkit-keyframes play {
from { background-position: 0px 0px; }
to { background-position: 0px -384px; }
}
#button_toolbar0 {
pointer-events: none;
position:absolute;
top:16px;
left: 24px;
content: "\00a0";
width:24px;
height:24px;
background-image: url(data:image/png;base64,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);
}
#button_toolbar0.selected {
background-image: url(data:image/png;base64,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);
}
</style>
</head>
<body id="">
<div class="toolbar">
<div id="button_toolbar0" class="toolbar_icon"></div>
<span class="container"><canvas class="paper button_toolbar recenteringTouch" id="button_toolbar1" onclick="animateIcon()"></canvas></span>
<span id="title" style="float:left">Ripple test</span>
<span class="container"><canvas onClick="toggleMenu()" class="paper button_toolbar recenteringTouch" id="button_toolbar3"></canvas></span>
<span class="container"><canvas class="paper button_toolbar recenteringTouch" id="button_toolbar2"></canvas></span>
<span class="container"><canvas class="paper button_toolbar recenteringTouch" id="button_toolbar2"></canvas></span>
</div>
<div id="dialog" class="dialog visible">
<h1>Press mah buttons!</h1> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.
<span class="container"><canvas class="paper button" id="button_borderless" value="CANCEL"></canvas></span>
<span class="container"><canvas class="paper button" id="button_borderless_blue" onclick="toggleDialog()" value="OK"></canvas></span>
</div>
<div id="menu" class="menu visible">
<div class="container button_menu"><canvas class="paper button_menu" value="Fold" style="text-align:left"></canvas></div>
<div class="container button_menu"><canvas class="paper button_menu" value="Spindle" style="text-align:left"></canvas></div>
<div class="container button_menu"><canvas class="paper button_menu" onClick="" value="Mutilate" style="text-align:left"></canvas></div>
<div class="container button_menu"><canvas class="paper button_menu" onClick="toggleMenu()" value="Dismiss" style="text-align:left"></canvas></div>
</div>
<div class="container"><canvas class="paper button recenteringTouch" id="button_large"></canvas></div>
<div class="content" style="">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam. sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
<p></p>
<span class="container" style="margin-right:8px;"><canvas class="paper button raised" id="button_blue" value="ABORT"></canvas></span>
<span class="container" style="margin-right:8px;"><canvas class="paper button raised" id="button_small" value="RETRY"></canvas></span>
<span class="container"><canvas class="paper button raised" id="button_small" value="FAIL"></canvas></span>
<p><p>
<canvas class="paper button" id="button_borderless_square"></canvas>
</div>
<div class="container"><canvas onClick="toggleDialog()" class="paper button_floating floating recenteringTouch" id="button_floating" value="★"></canvas></div>
</body>
</html>
{
"name": "paper-tabs",
"private": true,
"dependencies": {
"core-icons": "Polymer/core-icons#^0.4.0",
"core-selector": "Polymer/core-selector#^0.4.0",
"core-toolbar": "Polymer/core-toolbar#^0.4.0",
"font-roboto": "Polymer/font-roboto#^0.4.0",
"paper-icon-button": "Polymer/paper-icon-button#^0.4.0",
"paper-ripple": "Polymer/paper-ripple#^0.4.0"
},
"homepage": "https://github.com/Polymer/paper-tabs",
"version": "0.4.1",
"_release": "0.4.1",
"_resolution": {
"type": "version",
"tag": "0.4.1",
"commit": "c4ab5a81bd0c9bf96f9d24eb45b53a31910f210f"
},
"_source": "git://github.com/Polymer/paper-tabs.git",
"_target": "~0.4.0",
"_originalSource": "Polymer/paper-tabs"
}
\ No newline at end of file
paper-tabs
============
See the [component page](http://www.polymer-project.org/docs/elements/paper-elements.html#paper-tabs) for more information.
{
"name": "paper-tabs",
"private": true,
"dependencies": {
"core-icons": "Polymer/core-icons#^0.4.0",
"core-selector": "Polymer/core-selector#^0.4.0",
"core-toolbar": "Polymer/core-toolbar#^0.4.0",
"font-roboto": "Polymer/font-roboto#^0.4.0",
"paper-icon-button": "Polymer/paper-icon-button#^0.4.0",
"paper-ripple": "Polymer/paper-ripple#^0.4.0"
}
}
\ No newline at end of file
<!--
@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
-->
<!doctype html>
<html>
<head>
<title>paper-tabs</title>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-icons/core-icons.html">
<link rel="import" href="paper-tabs.html">
<link rel="import" href="../core-toolbar/core-toolbar.html">
<link rel="import" href="../paper-icon-button/paper-icon-button.html">
<link rel="import" href="../font-roboto/roboto.html">
<style shim-shadowdom>
body {
font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial;
margin: 0;
padding: 24px;
color: #333;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-touch-callout: none;
}
paper-tabs, core-toolbar {
background-color: #00bcd4;
color: #fff;
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.2);
}
core-toolbar paper-tabs {
box-shadow: none;
}
paper-tabs[noink][nobar] paper-tab.core-selected {
color: #ffff8d;
}
paper-tabs.transparent-teal {
background-color: transparent;
color: #00bcd4;
box-shadow: none;
}
paper-tabs.transparent-teal::shadow #selectionBar {
background-color: #00bcd4;
}
paper-tabs.transparent-teal paper-tab::shadow #ink {
color: #00bcd4;
}
h3 {
font-size: 16px;
font-weight: 400;
}
</style>
</head>
<body unresolved>
<h3>A. No ink effect and no sliding bar</h3>
<paper-tabs selected="0" noink nobar>
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
<paper-tab>ITEM THREE</paper-tab>
</paper-tabs>
<br>
<br>
<h3>B. The bar slides to the selected tab</h3>
<paper-tabs selected="0" noink>
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
<paper-tab>ITEM THREE</paper-tab>
</paper-tabs>
<br>
<br>
<h3>C. Inky Tabs</h3>
<paper-tabs selected="0">
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
<paper-tab>ITEM THREE</paper-tab>
</paper-tabs>
<br>
<br>
<paper-tabs selected="0" class="transparent-teal">
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
<paper-tab>ITEM THREE</paper-tab>
</paper-tabs>
<br>
<br>
<core-toolbar class="medium-tall">
<paper-icon-button icon="menu"></paper-icon-button>
<div flex>Title</div>
<paper-icon-button icon="search"></paper-icon-button>
<paper-icon-button icon="more-vert"></paper-icon-button>
<div class="bottom fit" horizontal layout>
<paper-tabs selected="0" flex style="max-width: 600px;">
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
<paper-tab>ITEM THREE</paper-tab>
</paper-tabs>
</div>
</core-toolbar>
<br>
<br>
<core-toolbar class="tall">
<paper-tabs selected="0" class="bottom indent" style="width: 200px;" self-end>
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
</paper-tabs>
<div class="bottom" flex></div>
<paper-icon-button class="bottom" icon="search"></paper-icon-button>
</core-toolbar>
</body>
</html>
<!doctype html>
<!--
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
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
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
-->
<html>
<head>
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page sources='["paper-tabs.html", "paper-tab.html"]'></core-component-page>
</body>
</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
-->
<x-meta id="paper-tabs" label="Tabs" group="Paper" isContainer>
<template>
<paper-tabs selected="0" style="width: 480px; background-color: #00bcd4; color: #fff; box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.2);">
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
<paper-tab>ITEM THREE</paper-tab>
<paper-tab>ITEM FOUR</paper-tab>
<paper-tab>ITEM FIVE</paper-tab>
</paper-tabs>
</template>
<template id="imports">
<link rel="import" href="paper-tabs.html">
</template>
</x-meta>
<x-meta id="paper-tab" label="Tab" group="Paper">
<template>
<paper-tab style="width: 120px; height: 40px;">TAB</paper-tab>
</template>
<template id="imports">
<link rel="import" href="paper-tab.html">
</template>
</x-meta>
<x-meta id="paper-tab-panel" label="Panel with Tabs" group="Paper" isContainer>
<template>
<section layout vertical style="width:420px;height:630px;border:5px solid #ccc;">
<paper-tabs selected="0" noink nobar style="background-color:#00bcd4; color:#fff;box-shadow:0px 3px 2px rgba(0, 0, 0, 0.2);">
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
</paper-tabs>
<section flex relative>
</section>
</section>
</template>
<template id="imports">
<link rel="import" href="paper-tabs.html">
</template>
</x-meta>
/*
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
*/
:host {
display: block;
position: relative;
overflow: hidden;
}
#tabContainer {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.tab-content {
transition: opacity .1s cubic-bezier(0.4, 0.0, 1, 1), color .1s cubic-bezier(0.4, 0.0, 1, 1);
cursor: default;
pointer-events: none;
}
:host(:not(.core-selected)) .tab-content {
opacity: 0.6;
}
#ink {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
color: #ffff8d;
}
:host[noink] #ink {
pointer-events: none;
}
:host-context(paper-tabs[noink]) #ink {
pointer-events: none;
}
<!--
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
-->
<!--
`paper-tab` is styled to look like a tab. It should be used in conjunction with
`paper-tabs`.
Example:
<paper-tabs selected="0">
<paper-tab>TAB 1</paper-tab>
<paper-tab>TAB 2</paper-tab>
<paper-tab>TAB 3</paper-tab>
</paper-tabs>
Styling tab:
To change the ink color:
.pink paper-tab::shadow #ink {
color: #ff4081;
}
@group Paper Elements
@element paper-tab
@homepage github.io
-->
<link rel="import" href="../paper-ripple/paper-ripple.html">
<polymer-element name="paper-tab" attributes="noink" role="tab">
<template>
<link rel="stylesheet" href="paper-tab.css">
<div id="tabContainer" center-justified center horizontal layout>
<div class="tab-content"><content></content></div>
<paper-ripple id="ink" initialOpacity="0.95" opacityDecayVelocity="0.98"></paper-ripple>
</div>
</template>
<script>
Polymer('paper-tab', {
/**
* If true, ink ripple effect is disabled.
*
* @attribute noink
* @type boolean
* @default false
*/
noink: false
});
</script>
</polymer-element>
/*
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
*/
:host {
display: block;
position: relative;
font-size: 14px;
font-weight: 500;
height: 48px;
overflow: hidden;
}
#tabsContainer {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
white-space: nowrap;
}
#selectionBar {
position: absolute;
height: 2px;
bottom: 0;
left: 0;
width: 0;
background-color: #ffff8d;
transition: width, left;
}
#selectionBar[hidden] {
display: hidden;
}
#selectionBar.expand {
transition-duration: 0.15s;
transition-timing-function: cubic-bezier(0.4, 0.0, 1, 1);
}
#selectionBar.contract {
transition-duration: 0.18s;
transition-timing-function: cubic-bezier(0.0, 0.0, 0.2, 1);
}
polyfill-next-selector { content: '#tabsContainer > *:not(#selectionBar)'; }
::content > * {
-ms-flex: 1;
-webkit-flex: 1;
flex: 1;
}
<!--
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
-->
<!--
`paper-tabs` is a `core-selector` styled to look like tabs. Tabs make it easy to
explore and switch between different views or functional aspects of an app, or
to browse categorized data sets.
Use `selected` property to get or set the selected tab.
Example:
<paper-tabs selected="0">
<paper-tab>TAB 1</paper-tab>
<paper-tab>TAB 2</paper-tab>
<paper-tab>TAB 3</paper-tab>
</paper-tabs>
See <a href="#paper-tab">paper-tab</a> for more information about
`paper-tab`.
Styling tabs:
To change the sliding bar color:
paper-tabs.pink::shadow #selectionBar {
background-color: #ff4081;
}
@group Paper Elements
@element paper-tabs
@extends core-selector
@homepage github.io
-->
<link rel="import" href="../core-selector/core-selector.html">
<link rel="import" href="paper-tab.html">
<polymer-element name="paper-tabs" extends="core-selector" attributes="noink nobar" role="tablist">
<template>
<link rel="stylesheet" href="paper-tabs.css">
<div id="tabsContainer" horizontal layout>
<shadow></shadow>
<div id="selectionBar" hidden?="{{nobar}}" on-transitionend="{{barTransitionEnd}}"></div>
</div>
</template>
<script>
Polymer('paper-tabs', {
/**
* If true, ink effect is disabled.
*
* @attribute noink
* @type boolean
* @default false
*/
noink: false,
/**
* If true, the bottom bar to indicate the selected tab will not be shown.
*
* @attribute nobar
* @type boolean
* @default false
*/
nobar: false,
activateEvent: 'down',
nostretch: false,
selectedIndexChanged: function(old) {
var s = this.$.selectionBar.style;
if (!this.selectedItem) {
s.width = 0;
s.left = 0;
return;
}
var w = 100 / this.items.length;
if (this.nostretch || old === null || old === -1) {
s.width = w + '%';
s.left = this.selectedIndex * w + '%';
return;
}
var m = 5;
this.$.selectionBar.classList.add('expand');
if (old < this.selectedIndex) {
s.width = w + w * (this.selectedIndex - old) - m + '%';
this._transitionCounter = 1;
} else {
s.width = w + w * (old - this.selectedIndex) - m + '%';
s.left = this.selectedIndex * w + m + '%';
this._transitionCounter = 2;
}
},
barTransitionEnd: function(e) {
this._transitionCounter--;
var cl = this.$.selectionBar.classList;
if (cl.contains('expand') && !this._transitionCounter) {
cl.remove('expand');
cl.add('contract');
var s = this.$.selectionBar.style;
var w = 100 / this.items.length;
s.width = w + '%';
s.left = this.selectedIndex * w + '%';
} else if (cl.contains('contract')) {
cl.remove('contract');
}
}
});
</script>
</polymer-element>
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "polymer",
"private": true,
"dependencies": {
"platform": "Polymer/platform#^0.4.0",
"core-component-page": "Polymer/core-component-page#^0.4.0"
},
"homepage": "https://github.com/Polymer/polymer",
"version": "0.4.1",
"_release": "0.4.1",
"_resolution": {
"type": "version",
"tag": "0.4.1",
"commit": "c0c8865f5a8f51d48712621f222ac97f00427f66"
},
"_source": "git://github.com/Polymer/polymer.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/polymer"
}
\ No newline at end of file
# Polymer
[![Analytics](https://ga-beacon.appspot.com/UA-39334307-2/Polymer/polymer/README)](https://github.com/igrigorik/ga-beacon)
Build Status: [http://build.chromium.org/p/client.polymer/waterfall](http://build.chromium.org/p/client.polymer/waterfall)
## Brief Overview
For more detailed info goto [http://polymer-project.org/](http://polymer-project.org/).
Polymer is a new type of library for the web, designed to leverage the existing browser infrastructure to provide the encapsulation and extendability currently only available in JS libraries.
Polymer is based on a set of future technologies, including [Shadow DOM](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html), [Custom Elements](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html) and Model Driven Views. Currently these technologies are implemented as polyfills or shims, but as browsers adopt these features natively, the platform code that drives Polymer evacipates, leaving only the value-adds.
## Tools & Testing
For running tests or building minified files, consult the [tooling information](http://www.polymer-project.org/resources/tooling-strategy.html).
{
"name": "polymer",
"private": true,
"dependencies": {
"platform": "Polymer/platform#^0.4.0",
"core-component-page": "Polymer/core-component-page#^0.4.0"
}
}
\ No newline at end of file
BUILD LOG
---------
Build Time: 2014-09-18T12:47:15
NODEJS INFORMATION
==================
nodejs: v0.10.32
chai: 1.9.1
grunt: 0.4.5
grunt-audit: 0.0.3
grunt-concat-sourcemap: 0.4.3
grunt-contrib-concat: 0.4.0
grunt-contrib-uglify: 0.5.1
grunt-karma: 0.8.3
grunt-string-replace: 0.2.7
karma: 0.12.23
karma-crbot-reporter: 0.0.4
karma-ie-launcher: 0.1.5
karma-mocha: 0.1.9
karma-firefox-launcher: 0.1.3
karma-safari-launcher: 0.1.1
karma-script-launcher: 0.1.0
mocha: 1.21.4
REPO REVISIONS
==============
polymer-expressions: a1c43d70986be0031206b68f3e17cbf11dbc56e2
polymer-gestures: 1257576a2fe1d7bb507b0c491d30b464eb03311e
polymer-dev: 1d45ec8e7de4495d26610f2dd73b81bfad2a381f
BUILD HASHES
============
build/polymer.js: c80909695c132ccf1700bae8e9c51e78ede0cc74
\ No newline at end of file
<!--
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
-->
<style shim-shadowdom>
/*******************************
Flex Layout
*******************************/
html /deep/ [layout][horizontal], html /deep/ [layout][vertical] {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
html /deep/ [layout][horizontal][inline], html /deep/ [layout][vertical][inline] {
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
}
html /deep/ [layout][horizontal] {
-ms-flex-direction: row;
-webkit-flex-direction: row;
flex-direction: row;
}
html /deep/ [layout][horizontal][reverse] {
-ms-flex-direction: row-reverse;
-webkit-flex-direction: row-reverse;
flex-direction: row-reverse;
}
html /deep/ [layout][vertical] {
-ms-flex-direction: column;
-webkit-flex-direction: column;
flex-direction: column;
}
html /deep/ [layout][vertical][reverse] {
-ms-flex-direction: column-reverse;
-webkit-flex-direction: column-reverse;
flex-direction: column-reverse;
}
html /deep/ [layout][wrap] {
-ms-flex-wrap: wrap;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
html /deep/ [layout][wrap-reverse] {
-ms-flex-wrap: wrap-reverse;
-webkit-flex-wrap: wrap-reverse;
flex-wrap: wrap-reverse;
}
html /deep/ [flex] {
-ms-flex: 1 1 0.000000001px;
-webkit-flex: 1;
flex: 1;
-webkit-flex-basis: 0.000000001px;
flex-basis: 0.000000001px;
}
html /deep/ [vertical][layout] > [flex][auto-vertical], html /deep/ [vertical][layout]::shadow [flex][auto-vertical] {
-ms-flex: 1 1 auto;
-webkit-flex-basis: auto;
flex-basis: auto;
}
html /deep/ [flex][auto] {
-ms-flex: 1 1 auto;
-webkit-flex-basis: auto;
flex-basis: auto;
}
html /deep/ [flex][none] {
-ms-flex: none;
-webkit-flex: none;
flex: none;
}
html /deep/ [flex][one] {
-ms-flex: 1;
-webkit-flex: 1;
flex: 1;
}
html /deep/ [flex][two] {
-ms-flex: 2;
-webkit-flex: 2;
flex: 2;
}
html /deep/ [flex][three] {
-ms-flex: 3;
-webkit-flex: 3;
flex: 3;
}
html /deep/ [flex][four] {
-ms-flex: 4;
-webkit-flex: 4;
flex: 4;
}
html /deep/ [flex][five] {
-ms-flex: 5;
-webkit-flex: 5;
flex: 5;
}
html /deep/ [flex][six] {
-ms-flex: 6;
-webkit-flex: 6;
flex: 6;
}
html /deep/ [flex][seven] {
-ms-flex: 7;
-webkit-flex: 7;
flex: 7;
}
html /deep/ [flex][eight] {
-ms-flex: 8;
-webkit-flex: 8;
flex: 8;
}
html /deep/ [flex][nine] {
-ms-flex: 9;
-webkit-flex: 9;
flex: 9;
}
html /deep/ [flex][ten] {
-ms-flex: 10;
-webkit-flex: 10;
flex: 10;
}
html /deep/ [flex][eleven] {
-ms-flex: 11;
-webkit-flex: 11;
flex: 11;
}
html /deep/ [flex][twelve] {
-ms-flex: 12;
-webkit-flex: 12;
flex: 12;
}
/* alignment in cross axis */
html /deep/ [layout][start] {
-ms-flex-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
}
html /deep/ [layout][center], html /deep/ [layout][center-center] {
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
html /deep/ [layout][end] {
-ms-flex-align: end;
-webkit-align-items: flex-end;
align-items: flex-end;
}
/* alignment in main axis */
html /deep/ [layout][start-justified] {
-ms-flex-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
}
html /deep/ [layout][center-justified], html /deep/ [layout][center-center] {
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
html /deep/ [layout][end-justified] {
-ms-flex-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
html /deep/ [layout][around-justified] {
-ms-flex-pack: distribute;
-webkit-justify-content: space-around;
justify-content: space-around;
}
html /deep/ [layout][justified] {
-ms-flex-pack: justify;
-webkit-justify-content: space-between;
justify-content: space-between;
}
/* self alignment */
html /deep/ [self-start] {
-ms-align-self: flex-start;
-webkit-align-self: flex-start;
align-self: flex-start;
}
html /deep/ [self-center] {
-ms-align-self: center;
-webkit-align-self: center;
align-self: center;
}
html /deep/ [self-end] {
-ms-align-self: flex-end;
-webkit-align-self: flex-end;
align-self: flex-end;
}
html /deep/ [self-stretch] {
-ms-align-self: stretch;
-webkit-align-self: stretch;
align-self: stretch;
}
/*******************************
Other Layout
*******************************/
html /deep/ [block] {
display: block;
}
/* ie support for hidden */
html /deep/ [hidden] {
display: none !important;
}
html /deep/ [relative] {
position: relative;
}
html /deep/ [fit] {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
body[fullbleed] {
margin: 0;
height: 100vh;
}
/*******************************
Other
*******************************/
html /deep/ [segment], html /deep/ segment {
display: block;
position: relative;
-webkit-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
margin: 1em 0.5em;
padding: 1em;
background-color: white;
-webkit-box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
border-radius: 5px 5px 5px 5px;
}
</style>
\ No newline at end of file
<!--
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
-->
<link rel="import" href="layout.html">
<script src="polymer.js"></script>
<!--<link rel="import" href="../polymer-dev/polymer.html">-->
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment