Skip to content

Instantly share code, notes, and snippets.

@elsplatto
Created October 15, 2014 07:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elsplatto/3ef95637f48aaf38cf39 to your computer and use it in GitHub Desktop.
Save elsplatto/3ef95637f48aaf38cf39 to your computer and use it in GitHub Desktop.
QSuper Prototype V2
This gist exceeds the recommended number of files (~10). To access all files, please clone this gist.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="IdProvider" IDEtalkID="F770E3C0E64B20AC77D3D4918AD5EC48" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/qsuper-2.iml" filepath="$PROJECT_DIR$/qsuper-2.iml" />
</modules>
</component>
</project>
<component name="DependencyValidationManager">
<state>
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</state>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<TaskOptions isEnabled="true">
<option name="arguments" value="--no-cache --update $FileName$:$FileNameWithoutExtension$.css" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" value="Compiles .sass files into .css files" />
<option name="exitCodeBehavior" value="ERROR" />
<option name="fileExtension" value="sass" />
<option name="immediateSync" value="true" />
<option name="name" value="SASS" />
<option name="output" value="../css/$FileNameWithoutExtension$.css" />
<option name="outputFilters">
<array />
</option>
<option name="outputFromStdout" value="false" />
<option name="passParentEnvs" value="true" />
<option name="program" value="/usr/bin/sass" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="true" />
<option name="workingDir" value="$FileDir$" />
<envs />
</TaskOptions>
</component>
</project>
{
"name": "qsuper-2",
"version": "0.0.0",
"authors": [
"Jason Taikato <jasontaikato@gmail.com>"
],
"description": "QSuper Prototype using Polymer",
"main": "index.html",
"keywords": [
"QSuper",
"Prototype",
"Polymer"
],
"license": "MIT",
"homepage": "index.html",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"polymer": "Polymer/polymer#~0.4.2",
"core-elements": "Polymer/core-elements#~0.4.2",
"paper-elements": "Polymer/paper-elements#~0.4.2",
"notification-elements": "PolymerLabs/notification-elements#~0.4.0",
"chart-elements": "robdodson/chart-elements#~0.1.1"
}
}
{
"name": "chart-elements",
"version": "0.1.1",
"keywords": "seed, polymer, web-components",
"main": "chart-elements.html",
"dependencies": {
"polymer": "Polymer/polymer#>=0.4.0 <1.0.0",
"chartjs": "~1.0.1-beta.4"
},
"homepage": "https://github.com/robdodson/chart-elements",
"_release": "0.1.1",
"_resolution": {
"type": "version",
"tag": "v0.1.1",
"commit": "b212e2016fb29107cc6789a9e192b9871a276069"
},
"_source": "git://github.com/robdodson/chart-elements.git",
"_target": "~0.1.1",
"_originalSource": "robdodson/chart-elements",
"_direct": true
}
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# Change these settings to your own preference
indent_style = space
indent_size = 2
# We recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
node_modules
dist
.sass-cache
.tmp
.DS_Store
.bowerrc
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"jquery": true
}
{
"name": "chart-elements",
"version": "0.1.1",
"keywords": "seed, polymer, web-components",
"main": "chart-elements.html",
"dependencies": {
"polymer": "Polymer/polymer#>=0.4.0 <1.0.0",
"chartjs": "~1.0.1-beta.4"
}
}
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="chart-js-import.html">
<!--
A bar chart is a way of showing data as bars.
It is sometimes used to show trend data, and the comparison of multiple data sets side by side.
##### Example
<chart-bar width="400" height="200"
labels="['Jan','Feb','Mar','Apr','May','Jun','Jul']",
values="[[65,59,90,81,56,55,40], [28,48,40,19,96,27,100]]"
colors="['253,180,92','247,70,74','70,191,189','148,159,177','77,83,96']">
</chart-bar>
@element chart-bar
@blurb A bar chart is a way of showing data as bars.
@status alpha
@homepage http://robdodson.github.io/chart-elements
-->
<polymer-element name="chart-bar" attributes="width height labels values colors">
<template>
<canvas id="canvas" width="{{width}}" height="{{height}}"></canvas>
</template>
<script>
Polymer({
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
values: [
[65,59,90,81,56,55,40],
[28,48,40,19,96,27,100]
],
colors: [
"253,180,92",
"247,70,74",
"70,191,189",
"148,159,177",
"77,83,96"
],
observe: {
labels: 'updateChart',
colors: 'updateChart',
values: 'updateChart'
},
updateChart: function() {
if (this.chart) {
this.chart.destroy();
}
this.datasets = [];
this.values.forEach(function (val, i) {
this.datasets.push({
fillColor: "rgba(" + this.colors[i] + ",0.5)",
strokeColor: "rgba(" + this.colors[i] + ",1)",
data: this.values[i]
});
}, this);
this.data = { labels: this.labels, datasets: this.datasets };
this.ctx = this.$.canvas.getContext('2d');
this.chart = new Chart(this.ctx).Bar(this.data);
}
});
</script>
</polymer-element>
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="chart-js-import.html">
<!--
Pie and doughnut charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows a the proportional value of each piece of data.
They are excellent at showing the relational proportions between data.
Pie and doughnut charts in are effectively the same class in Chart.js, but have one different default value - their percentageInnerCutout. This equates what percentage of the inner should be cut out. This defaults to 0 for pie charts, and 50 for doughnuts.
They are also registered under two aliases in the Chart core. Other than their different default value, and different alias, they are exactly the same.
##### Example
<chart-doughnut values="[30, 50, 100, 40, 120]"></chart-doughnut>
@element chart-doughnut
@blurb A chart for showing the relational proportions between data.
@status alpha
@homepage http://robdodson.github.io/chart-elements
-->
<polymer-element name="chart-doughnut" attributes="width height values colors">
<template>
<canvas id="canvas" width="{{width}}" height="{{height}}"></canvas>
</template>
<script>
Polymer({
values: [30, 50, 100, 40, 120],
colors: ["#F7464A", "#46BFBD", "#FDB45C", "#949FB1", "#4D5360"],
observe: {
colors: 'updateChart',
values: 'updateChart'
},
updateChart: function () {
if(this.chart){
this.chart.destroy();
}
this.data = [];
this.values.forEach(function (val, i) {
this.data.push({ color: this.colors[i], value: val });
}, this);
this.ctx = this.$.canvas.getContext('2d');
this.chart = new Chart(this.ctx).Doughnut(this.data);
}
});
</script>
</polymer-element>
<link rel="import" href="chart-bar.html">
<link rel="import" href="chart-doughnut.html">
<link rel="import" href="chart-line.html">
<link rel="import" href="chart-pie.html">
<link rel="import" href="chart-polar-area.html">
<link rel="import" href="chart-radar.html">
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="chart-js-import.html">
<!--
A line chart is a way of plotting data points on a line.
Often, it is used to show trend data, and the comparison of two data sets.
##### Example
<chart-line width="400" height="200"
labels="['Monday','Tuesday','Wednesday','thursday','Friday','Saturday','Sunday']"
values="[[10,14,20,25,13,9,40]]"
colors="['253,180,92','247,70,74','70,191,189','148,159,177','77,83,96']">
</chart-line>
@element chart-line
@blurb A line chart is a way of plotting data points on a line.
@status alpha
@homepage http://robdodson.github.io/chart-elements
-->
<polymer-element name="chart-line" attributes="width height labels values colors">
<template>
<canvas id="canvas" width="{{width}}" height="{{height}}"></canvas>
</template>
<script>
Polymer({
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
values: [
[65,59,90,81,56,55,40],
[28,48,40,19,96,27,100]
],
colors: [
"253,180,92",
"247,70,74",
"70,191,189",
"148,159,177",
"77,83,96"
],
observe: {
labels: 'updateChart',
colors: 'updateChart',
values: 'updateChart'
},
updateChart:function(){
if(this.chart){
this.chart.destroy();
}
this.datasets = [];
this.values.forEach(function (val, i) {
this.datasets.push({
fillColor: "rgba(" + this.colors[i] + ",0.5)",
strokeColor: "rgba(" + this.colors[i] + ",1)",
pointColor: "rgba(" + this.colors[i] + ",1)",
pointStrokeColor: "#fff",
data: this.values[i]
});
}, this);
this.data = { labels: this.labels, datasets: this.datasets };
this.ctx = this.$.canvas.getContext('2d');
this.chart = new Chart(this.ctx).Line(this.data);
}
});
</script>
</polymer-element>
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="chart-js-import.html">
<!--
Pie and doughnut charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows a the proportional value of each piece of data.
They are excellent at showing the relational proportions between data.
Pie and doughnut charts in are effectively the same class in Chart.js, but have one different default value - their percentageInnerCutout. This equates what percentage of the inner should be cut out. This defaults to 0 for pie charts, and 50 for doughnuts.
They are also registered under two aliases in the Chart core. Other than their different default value, and different alias, they are exactly the same.
##### Example
<chart-pie values="[20, 30, 100]"></chart-pie>
@element chart-pie
@blurb A chart for showing the relational proportions between data.
@status alpha
@homepage http://robdodson.github.io/chart-elements
-->
<polymer-element name="chart-pie" attributes="width height values colors">
<template>
<style>
:host {
display: inline-block;
}
</style>
<canvas id="canvas" width="{{width}}" height="{{height}}"></canvas>
</template>
<script>
Polymer({
values: [30, 50, 100, 40, 120],
colors: ["#F7464A", "#46BFBD", "#FDB45C", "#949FB1", "#4D5360"],
observe: {
colors: 'updateChart',
values: 'updateChart'
},
updateChart: function () {
if(this.chart){
this.chart.destroy();
}
this.data = [];
this.values.forEach(function (val, i) {
this.data.push({ color: this.colors[i], value: val });
}, this);
this.ctx = this.$.canvas.getContext('2d');
this.chart = new Chart(this.ctx).Pie(this.data);
}
});
</script>
</polymer-element>
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="chart-js-import.html">
<!--
Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value.
This type of chart is often useful when we want to show a comparison data similar to a pie chart, but also show a scale of values for context.
##### Example
<chart-polar-area values="[30, 90, 18, 58, 82]"></chart-polar-area>
@element chart-polar-area
@blurb Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value.
@status alpha
@homepage http://robdodson.github.io/chart-elements
-->
<polymer-element name="chart-polar-area" attributes="width height values colors">
<template>
<canvas id="canvas" width="{{width}}" height="{{height}}"></canvas>
</template>
<script>
Polymer("chart-polar-area", {
values: [30, 90, 18, 58, 82],
colors: ["#46BFBD", "#FDB45C", "#949FB1", "#4D5360", "#F7464A"],
observe: {
labels: 'updateChart',
colors: 'updateChart',
values: 'updateChart'
},
updateChart: function () {
if(this.chart){
this.chart.destroy();
}
this.data = [];
this.values.forEach(function (val, i) {
this.data.push({ color: this.colors[i], value: val });
}, this);
this.ctx = this.$.canvas.getContext('2d');
this.chart = new Chart(this.ctx).PolarArea(this.data);
}
});
</script>
</polymer-element>
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="chart-js-import.html">
<!--
A radar chart is a way of showing multiple data points and the variation between them.
They are often useful for comparing the points of two or more different data sets.
##### Example
<chart-radar labels="['Jan','Feb','Mar','Apr','May','Jun','Jul']"
values="[[65,59,90,81,56,55,40], [28,48,40,19,96,27,100]]",
colors= "['253,180,92','247,70,74','70,191,189','148,159,177','77,83,96']">
</chart-radar>
@element chart-radar
@blurb A radar chart is a way of showing multiple data points and the variation between them.
@status alpha
@homepage http://robdodson.github.io/chart-elements
-->
<polymer-element name="chart-radar" attributes="width height labels values colors">
<template>
<canvas id="canvas" width="{{width}}" height="{{height}}"></canvas>
</template>
<script>
Polymer({
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
values: [
[65,59,90,81,56,55,40],
[28,48,40,19,96,27,100]
],
colors: [
"253,180,92",
"247,70,74",
"70,191,189",
"148,159,177",
"77,83,96"
],
observe: {
colors: 'updateChart',
values: 'updateChart',
labels: 'updateChart'
},
updateChart: function () {
if(this.chart){
this.chart.destroy();
}
this.datasets = [];
this.values.forEach(function (val, i) {
this.datasets.push({
fillColor: "rgba(" + this.colors[i] + ",0.5)",
strokeColor: "rgba(" + this.colors[i] + ",1)",
pointColor: "rgba(" + this.colors[i] + ",1)",
pointStrokeColor: "#fff",
data: this.values[i]
});
}, this);
this.data = { labels: this.labels, datasets: this.datasets };
this.ctx = this.$.canvas.getContext('2d');
this.chart = new Chart(this.ctx).Radar(this.data);
}
});
</script>
</polymer-element>
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>chart-elements Demo</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="chart-elements.html">
</head>
<body unresolved>
<chart-pie
width="200"
height="200"
values="[20, 30, 100]">
</chart-pie>
<chart-doughnut
width="200"
height="200"
values="[30, 50, 100, 40, 120]">
</chart-doughnut>
<chart-polar-area
width="200"
height="200"
values="[30, 90, 18, 58, 82]">
</chart-polar-area>
<chart-radar labels="['Jan','Feb','Mar','Apr','May','Jun','Jul']"
values="[[65,59,90,81,56,55,40], [28,48,40,19,96,27,100]]",
colors= "['253,180,92','247,70,74','70,191,189','148,159,177','77,83,96']">
</chart-radar>
<br>
<chart-line
width="400"
height="200"
labels="['Monday','Tuesday','Wednesday','thursday','Friday','Saturday','Sunday']"
values="[[10,14,20,25,13,9,40]]"
colors="['253,180,92','247,70,74','70,191,189','148,159,177','77,83,96']">
</chart-line>
<chart-bar
width="400"
height="200"
labels="['Jan','Feb','Mar','Apr','May','Jun','Jul']",
values="[[65,59,90,81,56,55,40], [28,48,40,19,96,27,100]]"
colors="['253,180,92','247,70,74','70,191,189','148,159,177','77,83,96']">
</chart-bar>
</body>
</html>
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<script src="../platform/platform.js"></script>
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page
moduleName="chart-elements"
sources='[
"chart-bar.html",
"chart-doughnut.html",
"chart-line.html",
"chart-pie.html",
"chart-polar-area.html",
"chart-radar.html"
]'>
</core-component-page>
</body>
</html>
{
"name": "Chart.js",
"version": "1.0.1-beta.4",
"description": "Simple HTML5 Charts using the canvas element",
"homepage": "https://github.com/nnnick/Chart.js",
"author": "nnnick",
"main": [
"Chart.min.js"
],
"dependencies": {},
"_release": "1.0.1-beta.4",
"_resolution": {
"type": "version",
"tag": "v1.0.1-beta.4",
"commit": "8b840ce56be51b61dfc2d4e40e56304c880c541b"
},
"_source": "git://github.com/nnnick/Chart.js.git",
"_target": "~1.0.1-beta.4",
"_originalSource": "chartjs"
}
.DS_Store
node_modules/*
custom/*
docs/index.md
{
"name": "Chart.js",
"version": "1.0.1-beta.4",
"description": "Simple HTML5 Charts using the canvas element",
"homepage": "https://github.com/nnnick/Chart.js",
"author": "nnnick",
"main": [
"Chart.min.js"
],
"dependencies": {}
}
/*!
* Chart.js
* http://chartjs.org/
* Version: 1.0.1-beta.4
*
* Copyright 2014 Nick Downie
* Released under the MIT license
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
*/
(function(){
"use strict";
//Declare root variable - window in the browser, global on the server
var root = this,
previous = root.Chart;
//Occupy the global variable of Chart, and create a simple base class
var Chart = function(context){
var chart = this;
this.canvas = context.canvas;
this.ctx = context;
//Variables global to the chart
var width = this.width = context.canvas.width;
var height = this.height = context.canvas.height;
this.aspectRatio = this.width / this.height;
//High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
helpers.retinaScale(this);
return this;
};
//Globally expose the defaults to allow for user updating/changing
Chart.defaults = {
global: {
// Boolean - Whether to animate the chart
animation: true,
// Number - Number of animation steps
animationSteps: 60,
// String - Animation easing effect
animationEasing: "easeOutQuart",
// Boolean - If we should show the scale at all
showScale: true,
// Boolean - If we want to override with a hard coded scale
scaleOverride: false,
// ** Required if scaleOverride is true **
// Number - The number of steps in a hard coded scale
scaleSteps: null,
// Number - The value jump in the hard coded scale
scaleStepWidth: null,
// Number - The scale starting value
scaleStartValue: null,
// String - Colour of the scale line
scaleLineColor: "rgba(0,0,0,.1)",
// Number - Pixel width of the scale line
scaleLineWidth: 1,
// Boolean - Whether to show labels on the scale
scaleShowLabels: true,
// Interpolated JS string - can access value
scaleLabel: "<%=value%>",
// Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there
scaleIntegersOnly: true,
// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
scaleBeginAtZero: false,
// String - Scale label font declaration for the scale label
scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Scale label font size in pixels
scaleFontSize: 12,
// String - Scale label font weight style
scaleFontStyle: "normal",
// String - Scale label font colour
scaleFontColor: "#666",
// Boolean - whether or not the chart should be responsive and resize when the browser does.
responsive: false,
// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
maintainAspectRatio: true,
// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
showTooltips: true,
// Array - Array of string names to attach tooltip events
tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
// String - Tooltip background colour
tooltipFillColor: "rgba(0,0,0,0.8)",
// String - Tooltip label font declaration for the scale label
tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Tooltip label font size in pixels
tooltipFontSize: 14,
// String - Tooltip font weight style
tooltipFontStyle: "normal",
// String - Tooltip label font colour
tooltipFontColor: "#fff",
// String - Tooltip title font declaration for the scale label
tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Tooltip title font size in pixels
tooltipTitleFontSize: 14,
// String - Tooltip title font weight style
tooltipTitleFontStyle: "bold",
// String - Tooltip title font colour
tooltipTitleFontColor: "#fff",
// Number - pixel width of padding around tooltip text
tooltipYPadding: 6,
// Number - pixel width of padding around tooltip text
tooltipXPadding: 6,
// Number - Size of the caret on the tooltip
tooltipCaretSize: 8,
// Number - Pixel radius of the tooltip border
tooltipCornerRadius: 6,
// Number - Pixel offset from point x to tooltip edge
tooltipXOffset: 10,
// String - Template string for single tooltips
tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
// String - Template string for single tooltips
multiTooltipTemplate: "<%= value %>",
// String - Colour behind the legend colour block
multiTooltipKeyBackground: '#fff',
// Function - Will fire on animation progression.
onAnimationProgress: function(){},
// Function - Will fire on animation completion.
onAnimationComplete: function(){}
}
};
//Create a dictionary of chart types, to allow for extension of existing types
Chart.types = {};
//Global Chart helpers object for utility methods and classes
var helpers = Chart.helpers = {};
//-- Basic js utility methods
var each = helpers.each = function(loopable,callback,self){
var additionalArgs = Array.prototype.slice.call(arguments, 3);
// Check to see if null or undefined firstly.
if (loopable){
if (loopable.length === +loopable.length){
var i;
for (i=0; i<loopable.length; i++){
callback.apply(self,[loopable[i], i].concat(additionalArgs));
}
}
else{
for (var item in loopable){
callback.apply(self,[loopable[item],item].concat(additionalArgs));
}
}
}
},
clone = helpers.clone = function(obj){
var objClone = {};
each(obj,function(value,key){
if (obj.hasOwnProperty(key)) objClone[key] = value;
});
return objClone;
},
extend = helpers.extend = function(base){
each(Array.prototype.slice.call(arguments,1), function(extensionObject) {
each(extensionObject,function(value,key){
if (extensionObject.hasOwnProperty(key)) base[key] = value;
});
});
return base;
},
merge = helpers.merge = function(base,master){
//Merge properties in left object over to a shallow clone of object right.
var args = Array.prototype.slice.call(arguments,0);
args.unshift({});
return extend.apply(null, args);
},
indexOf = helpers.indexOf = function(arrayToSearch, item){
if (Array.prototype.indexOf) {
return arrayToSearch.indexOf(item);
}
else{
for (var i = 0; i < arrayToSearch.length; i++) {
if (arrayToSearch[i] === item) return i;
}
return -1;
}
},
where = helpers.where = function(collection, filterCallback){
var filtered = [];
helpers.each(collection, function(item){
if (filterCallback(item)){
filtered.push(item);
}
});
return filtered;
},
findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){
// Default to start of the array
if (!startIndex){
startIndex = -1;
}
for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
var currentItem = arrayToSearch[i];
if (filterCallback(currentItem)){
return currentItem;
}
};
},
findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){
// Default to end of the array
if (!startIndex){
startIndex = arrayToSearch.length;
}
for (var i = startIndex - 1; i >= 0; i--) {
var currentItem = arrayToSearch[i];
if (filterCallback(currentItem)){
return currentItem;
}
};
},
inherits = helpers.inherits = function(extensions){
//Basic javascript inheritance based on the model created in Backbone.js
var parent = this;
var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };
var Surrogate = function(){ this.constructor = ChartElement;};
Surrogate.prototype = parent.prototype;
ChartElement.prototype = new Surrogate();
ChartElement.extend = inherits;
if (extensions) extend(ChartElement.prototype, extensions);
ChartElement.__super__ = parent.prototype;
return ChartElement;
},
noop = helpers.noop = function(){},
uid = helpers.uid = (function(){
var id=0;
return function(){
return "chart-" + id++;
};
})(),
warn = helpers.warn = function(str){
//Method for warning of errors
if (window.console && typeof window.console.warn == "function") console.warn(str);
},
amd = helpers.amd = (typeof root.define == 'function' && root.define.amd),
//-- Math methods
isNumber = helpers.isNumber = function(n){
return !isNaN(parseFloat(n)) && isFinite(n);
},
max = helpers.max = function(array){
return Math.max.apply( Math, array );
},
min = helpers.min = function(array){
return Math.min.apply( Math, array );
},
cap = helpers.cap = function(valueToCap,maxValue,minValue){
if(isNumber(maxValue)) {
if( valueToCap > maxValue ) {
return maxValue;
}
}
else if(isNumber(minValue)){
if ( valueToCap < minValue ){
return minValue;
}
}
return valueToCap;
},
getDecimalPlaces = helpers.getDecimalPlaces = function(num){
if (num%1!==0 && isNumber(num)){
return num.toString().split(".")[1].length;
}
else {
return 0;
}
},
toRadians = helpers.radians = function(degrees){
return degrees * (Math.PI/180);
},
// Gets the angle from vertical upright to the point about a centre.
getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){
var distanceFromXCenter = anglePoint.x - centrePoint.x,
distanceFromYCenter = anglePoint.y - centrePoint.y,
radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);
//If the segment is in the top left quadrant, we need to add another rotation to the angle
if (distanceFromXCenter < 0 && distanceFromYCenter < 0){
angle += Math.PI*2;
}
return {
angle: angle,
distance: radialDistanceFromCenter
};
},
aliasPixel = helpers.aliasPixel = function(pixelWidth){
return (pixelWidth % 2 === 0) ? 0 : 0.5;
},
splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){
//Props to Rob Spencer at scaled innovation for his post on splining between points
//http://scaledinnovation.com/analytics/splines/aboutSplines.html
var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),
d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),
fa=t*d01/(d01+d12),// scaling factor for triangle Ta
fb=t*d12/(d01+d12);
return {
inner : {
x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),
y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)
},
outer : {
x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),
y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)
}
};
},
calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){
return Math.floor(Math.log(val) / Math.LN10);
},
calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){
//Set a minimum step of two - a point at the top of the graph, and a point at the base
var minSteps = 2,
maxSteps = Math.floor(drawingSize/(textSize * 1.5)),
skipFitting = (minSteps >= maxSteps);
var maxValue = max(valuesArray),
minValue = min(valuesArray);
// We need some degree of seperation here to calculate the scales if all the values are the same
// Adding/minusing 0.5 will give us a range of 1.
if (maxValue === minValue){
maxValue += 0.5;
// So we don't end up with a graph with a negative start value if we've said always start from zero
if (minValue >= 0.5 && !startFromZero){
minValue -= 0.5;
}
else{
// Make up a whole number above the values
maxValue += 0.5;
}
}
var valueRange = Math.abs(maxValue - minValue),
rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),
graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
graphRange = graphMax - graphMin,
stepValue = Math.pow(10, rangeOrderOfMagnitude),
numberOfSteps = Math.round(graphRange / stepValue);
//If we have more space on the graph we'll use it to give more definition to the data
while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {
if(numberOfSteps > maxSteps){
stepValue *=2;
numberOfSteps = Math.round(graphRange/stepValue);
// Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.
if (numberOfSteps % 1 !== 0){
skipFitting = true;
}
}
//We can fit in double the amount of scale points on the scale
else{
//If user has declared ints only, and the step value isn't a decimal
if (integersOnly && rangeOrderOfMagnitude >= 0){
//If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float
if(stepValue/2 % 1 === 0){
stepValue /=2;
numberOfSteps = Math.round(graphRange/stepValue);
}
//If it would make it a float break out of the loop
else{
break;
}
}
//If the scale doesn't have to be an int, make the scale more granular anyway.
else{
stepValue /=2;
numberOfSteps = Math.round(graphRange/stepValue);
}
}
}
if (skipFitting){
numberOfSteps = minSteps;
stepValue = graphRange / numberOfSteps;
}
return {
steps : numberOfSteps,
stepValue : stepValue,
min : graphMin,
max : graphMin + (numberOfSteps * stepValue)
};
},
/* jshint ignore:start */
// Blows up jshint errors based on the new Function constructor
//Templating methods
//Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
template = helpers.template = function(templateString, valuesObject){
// If templateString is function rather than string-template - call the function for valuesObject
if(templateString instanceof Function){
return templateString(valuesObject);
}
var cache = {};
function tmpl(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] = cache[str] :
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'") +
"');}return p.join('');"
);
// Provide some basic currying to the user
return data ? fn( data ) : fn;
}
return tmpl(templateString,valuesObject);
},
/* jshint ignore:end */
generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){
var labelsArray = new Array(numberOfSteps);
if (labelTemplateString){
each(labelsArray,function(val,index){
labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});
});
}
return labelsArray;
},
//--Animation methods
//Easing functions adapted from Robert Penner's easing equations
//http://www.robertpenner.com/easing/
easingEffects = helpers.easingEffects = {
linear: function (t) {
return t;
},
easeInQuad: function (t) {
return t * t;
},
easeOutQuad: function (t) {
return -1 * t * (t - 2);
},
easeInOutQuad: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t;
return -1 / 2 * ((--t) * (t - 2) - 1);
},
easeInCubic: function (t) {
return t * t * t;
},
easeOutCubic: function (t) {
return 1 * ((t = t / 1 - 1) * t * t + 1);
},
easeInOutCubic: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;
return 1 / 2 * ((t -= 2) * t * t + 2);
},
easeInQuart: function (t) {
return t * t * t * t;
},
easeOutQuart: function (t) {
return -1 * ((t = t / 1 - 1) * t * t * t - 1);
},
easeInOutQuart: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;
return -1 / 2 * ((t -= 2) * t * t * t - 2);
},
easeInQuint: function (t) {
return 1 * (t /= 1) * t * t * t * t;
},
easeOutQuint: function (t) {
return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
},
easeInOutQuint: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;
return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
},
easeInSine: function (t) {
return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
},
easeOutSine: function (t) {
return 1 * Math.sin(t / 1 * (Math.PI / 2));
},
easeInOutSine: function (t) {
return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
},
easeInExpo: function (t) {
return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
},
easeOutExpo: function (t) {
return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
},
easeInOutExpo: function (t) {
if (t === 0) return 0;
if (t === 1) return 1;
if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));
return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
},
easeInCirc: function (t) {
if (t >= 1) return t;
return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
},
easeOutCirc: function (t) {
return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
},
easeInOutCirc: function (t) {
if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
},
easeInElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0) return 0;
if ((t /= 1) == 1) return 1;
if (!p) p = 1 * 0.3;
if (a < Math.abs(1)) {
a = 1;
s = p / 4;
} else s = p / (2 * Math.PI) * Math.asin(1 / a);
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
},
easeOutElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0) return 0;
if ((t /= 1) == 1) return 1;
if (!p) p = 1 * 0.3;
if (a < Math.abs(1)) {
a = 1;
s = p / 4;
} else s = p / (2 * Math.PI) * Math.asin(1 / a);
return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
},
easeInOutElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0) return 0;
if ((t /= 1 / 2) == 2) return 1;
if (!p) p = 1 * (0.3 * 1.5);
if (a < Math.abs(1)) {
a = 1;
s = p / 4;
} else s = p / (2 * Math.PI) * Math.asin(1 / a);
if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
},
easeInBack: function (t) {
var s = 1.70158;
return 1 * (t /= 1) * t * ((s + 1) * t - s);
},
easeOutBack: function (t) {
var s = 1.70158;
return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
},
easeInOutBack: function (t) {
var s = 1.70158;
if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
},
easeInBounce: function (t) {
return 1 - easingEffects.easeOutBounce(1 - t);
},
easeOutBounce: function (t) {
if ((t /= 1) < (1 / 2.75)) {
return 1 * (7.5625 * t * t);
} else if (t < (2 / 2.75)) {
return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
} else if (t < (2.5 / 2.75)) {
return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
} else {
return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
}
},
easeInOutBounce: function (t) {
if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;
return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
}
},
//Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
requestAnimFrame = helpers.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
return window.setTimeout(callback, 1000 / 60);
};
})(),
cancelAnimFrame = helpers.cancelAnimFrame = (function(){
return window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.oCancelAnimationFrame ||
window.msCancelAnimationFrame ||
function(callback) {
return window.clearTimeout(callback, 1000 / 60);
};
})(),
animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){
var currentStep = 0,
easingFunction = easingEffects[easingString] || easingEffects.linear;
var animationFrame = function(){
currentStep++;
var stepDecimal = currentStep/totalSteps;
var easeDecimal = easingFunction(stepDecimal);
callback.call(chartInstance,easeDecimal,stepDecimal, currentStep);
onProgress.call(chartInstance,easeDecimal,stepDecimal);
if (currentStep < totalSteps){
chartInstance.animationFrame = requestAnimFrame(animationFrame);
} else{
onComplete.apply(chartInstance);
}
};
requestAnimFrame(animationFrame);
},
//-- DOM methods
getRelativePosition = helpers.getRelativePosition = function(evt){
var mouseX, mouseY;
var e = evt.originalEvent || evt,
canvas = evt.currentTarget || evt.srcElement,
boundingRect = canvas.getBoundingClientRect();
if (e.touches){
mouseX = e.touches[0].clientX - boundingRect.left;
mouseY = e.touches[0].clientY - boundingRect.top;
}
else{
mouseX = e.clientX - boundingRect.left;
mouseY = e.clientY - boundingRect.top;
}
return {
x : mouseX,
y : mouseY
};
},
addEvent = helpers.addEvent = function(node,eventType,method){
if (node.addEventListener){
node.addEventListener(eventType,method);
} else if (node.attachEvent){
node.attachEvent("on"+eventType, method);
} else {
node["on"+eventType] = method;
}
},
removeEvent = helpers.removeEvent = function(node, eventType, handler){
if (node.removeEventListener){
node.removeEventListener(eventType, handler, false);
} else if (node.detachEvent){
node.detachEvent("on"+eventType,handler);
} else{
node["on" + eventType] = noop;
}
},
bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){
// Create the events object if it's not already present
if (!chartInstance.events) chartInstance.events = {};
each(arrayOfEvents,function(eventName){
chartInstance.events[eventName] = function(){
handler.apply(chartInstance, arguments);
};
addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);
});
},
unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {
each(arrayOfEvents, function(handler,eventName){
removeEvent(chartInstance.chart.canvas, eventName, handler);
});
},
getMaximumWidth = helpers.getMaximumWidth = function(domNode){
var container = domNode.parentNode;
// TODO = check cross browser stuff with this.
return container.clientWidth;
},
getMaximumHeight = helpers.getMaximumHeight = function(domNode){
var container = domNode.parentNode;
// TODO = check cross browser stuff with this.
return container.clientHeight;
},
getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
retinaScale = helpers.retinaScale = function(chart){
var ctx = chart.ctx,
width = chart.canvas.width,
height = chart.canvas.height;
if (window.devicePixelRatio) {
ctx.canvas.style.width = width + "px";
ctx.canvas.style.height = height + "px";
ctx.canvas.height = height * window.devicePixelRatio;
ctx.canvas.width = width * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
}
},
//-- Canvas methods
clear = helpers.clear = function(chart){
chart.ctx.clearRect(0,0,chart.width,chart.height);
},
fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){
return fontStyle + " " + pixelSize+"px " + fontFamily;
},
longestText = helpers.longestText = function(ctx,font,arrayOfStrings){
ctx.font = font;
var longest = 0;
each(arrayOfStrings,function(string){
var textWidth = ctx.measureText(string).width;
longest = (textWidth > longest) ? textWidth : longest;
});
return longest;
},
drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
};
//Store a reference to each instance - allowing us to globally resize chart instances on window resize.
//Destroy method on the chart will remove the instance of the chart from this reference.
Chart.instances = {};
Chart.Type = function(data,options,chart){
this.options = options;
this.chart = chart;
this.id = uid();
//Add the chart instance to the global namespace
Chart.instances[this.id] = this;
// Initialize is always called when a chart type is created
// By default it is a no op, but it should be extended
if (options.responsive){
this.resize();
}
this.initialize.call(this,data);
};
//Core methods that'll be a part of every chart type
extend(Chart.Type.prototype,{
initialize : function(){return this;},
clear : function(){
clear(this.chart);
return this;
},
stop : function(){
// Stops any current animation loop occuring
helpers.cancelAnimFrame.call(root, this.animationFrame);
return this;
},
resize : function(callback){
this.stop();
var canvas = this.chart.canvas,
newWidth = getMaximumWidth(this.chart.canvas),
newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
canvas.width = this.chart.width = newWidth;
canvas.height = this.chart.height = newHeight;
retinaScale(this.chart);
if (typeof callback === "function"){
callback.apply(this, Array.prototype.slice.call(arguments, 1));
}
return this;
},
reflow : noop,
render : function(reflow){
if (reflow){
this.reflow();
}
if (this.options.animation && !reflow){
helpers.animationLoop(
this.draw,
this.options.animationSteps,
this.options.animationEasing,
this.options.onAnimationProgress,
this.options.onAnimationComplete,
this
);
}
else{
this.draw();
this.options.onAnimationComplete.call(this);
}
return this;
},
generateLegend : function(){
return template(this.options.legendTemplate,this);
},
destroy : function(){
this.clear();
unbindEvents(this, this.events);
delete Chart.instances[this.id];
},
showTooltip : function(ChartElements, forceRedraw){
// Only redraw the chart if we've actually changed what we're hovering on.
if (typeof this.activeElements === 'undefined') this.activeElements = [];
var isChanged = (function(Elements){
var changed = false;
if (Elements.length !== this.activeElements.length){
changed = true;
return changed;
}
each(Elements, function(element, index){
if (element !== this.activeElements[index]){
changed = true;
}
}, this);
return changed;
}).call(this, ChartElements);
if (!isChanged && !forceRedraw){
return;
}
else{
this.activeElements = ChartElements;
}
this.draw();
if (ChartElements.length > 0){
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
if (this.datasets && this.datasets.length > 1) {
var dataArray,
dataIndex;
for (var i = this.datasets.length - 1; i >= 0; i--) {
dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
dataIndex = indexOf(dataArray, ChartElements[0]);
if (dataIndex !== -1){
break;
}
}
var tooltipLabels = [],
tooltipColors = [],
medianPosition = (function(index) {
// Get all the points at that particular index
var Elements = [],
dataCollection,
xPositions = [],
yPositions = [],
xMax,
yMax,
xMin,
yMin;
helpers.each(this.datasets, function(dataset){
dataCollection = dataset.points || dataset.bars || dataset.segments;
if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
Elements.push(dataCollection[dataIndex]);
}
});
helpers.each(Elements, function(element) {
xPositions.push(element.x);
yPositions.push(element.y);
//Include any colour information about the element
tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
tooltipColors.push({
fill: element._saved.fillColor || element.fillColor,
stroke: element._saved.strokeColor || element.strokeColor
});
}, this);
yMin = min(yPositions);
yMax = max(yPositions);
xMin = min(xPositions);
xMax = max(xPositions);
return {
x: (xMin > this.chart.width/2) ? xMin : xMax,
y: (yMin + yMax)/2
};
}).call(this, dataIndex);
new Chart.MultiTooltip({
x: medianPosition.x,
y: medianPosition.y,
xPadding: this.options.tooltipXPadding,
yPadding: this.options.tooltipYPadding,
xOffset: this.options.tooltipXOffset,
fillColor: this.options.tooltipFillColor,
textColor: this.options.tooltipFontColor,
fontFamily: this.options.tooltipFontFamily,
fontStyle: this.options.tooltipFontStyle,
fontSize: this.options.tooltipFontSize,
titleTextColor: this.options.tooltipTitleFontColor,
titleFontFamily: this.options.tooltipTitleFontFamily,
titleFontStyle: this.options.tooltipTitleFontStyle,
titleFontSize: this.options.tooltipTitleFontSize,
cornerRadius: this.options.tooltipCornerRadius,
labels: tooltipLabels,
legendColors: tooltipColors,
legendColorBackground : this.options.multiTooltipKeyBackground,
title: ChartElements[0].label,
chart: this.chart,
ctx: this.chart.ctx
}).draw();
} else {
each(ChartElements, function(Element) {
var tooltipPosition = Element.tooltipPosition();
new Chart.Tooltip({
x: Math.round(tooltipPosition.x),
y: Math.round(tooltipPosition.y),
xPadding: this.options.tooltipXPadding,
yPadding: this.options.tooltipYPadding,
fillColor: this.options.tooltipFillColor,
textColor: this.options.tooltipFontColor,
fontFamily: this.options.tooltipFontFamily,
fontStyle: this.options.tooltipFontStyle,
fontSize: this.options.tooltipFontSize,
caretHeight: this.options.tooltipCaretSize,
cornerRadius: this.options.tooltipCornerRadius,
text: template(this.options.tooltipTemplate, Element),
chart: this.chart
}).draw();
}, this);
}
}
return this;
},
toBase64Image : function(){
return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
}
});
Chart.Type.extend = function(extensions){
var parent = this;
var ChartType = function(){
return parent.apply(this,arguments);
};
//Copy the prototype object of the this class
ChartType.prototype = clone(parent.prototype);
//Now overwrite some of the properties in the base class with the new extensions
extend(ChartType.prototype, extensions);
ChartType.extend = Chart.Type.extend;
if (extensions.name || parent.prototype.name){
var chartName = extensions.name || parent.prototype.name;
//Assign any potential default values of the new chart type
//If none are defined, we'll use a clone of the chart type this is being extended from.
//I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
//doesn't define some defaults of their own.
var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults);
Chart.types[chartName] = ChartType;
//Register this new chart type in the Chart prototype
Chart.prototype[chartName] = function(data,options){
var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});
return new ChartType(data,config,this);
};
} else{
warn("Name not provided for this chart, so it hasn't been registered");
}
return parent;
};
Chart.Element = function(configuration){
extend(this,configuration);
this.initialize.apply(this,arguments);
this.save();
};
extend(Chart.Element.prototype,{
initialize : function(){},
restore : function(props){
if (!props){
extend(this,this._saved);
} else {
each(props,function(key){
this[key] = this._saved[key];
},this);
}
return this;
},
save : function(){
this._saved = clone(this);
delete this._saved._saved;
return this;
},
update : function(newProps){
each(newProps,function(value,key){
this._saved[key] = this[key];
this[key] = value;
},this);
return this;
},
transition : function(props,ease){
each(props,function(value,key){
this[key] = ((value - this._saved[key]) * ease) + this._saved[key];
},this);
return this;
},
tooltipPosition : function(){
return {
x : this.x,
y : this.y
};
},
hasValue: function(){
return isNumber(this.value);
}
});
Chart.Element.extend = inherits;
Chart.Point = Chart.Element.extend({
display: true,
inRange: function(chartX,chartY){
var hitDetectionRange = this.hitDetectionRadius + this.radius;
return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));
},
draw : function(){
if (this.display){
var ctx = this.ctx;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.closePath();
ctx.strokeStyle = this.strokeColor;
ctx.lineWidth = this.strokeWidth;
ctx.fillStyle = this.fillColor;
ctx.fill();
ctx.stroke();
}
//Quick debug for bezier curve splining
//Highlights control points and the line between them.
//Handy for dev - stripped in the min version.
// ctx.save();
// ctx.fillStyle = "black";
// ctx.strokeStyle = "black"
// ctx.beginPath();
// ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);
// ctx.fill();
// ctx.beginPath();
// ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);
// ctx.fill();
// ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);
// ctx.lineTo(this.x, this.y);
// ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);
// ctx.stroke();
// ctx.restore();
}
});
Chart.Arc = Chart.Element.extend({
inRange : function(chartX,chartY){
var pointRelativePosition = helpers.getAngleFromPoint(this, {
x: chartX,
y: chartY
});
//Check if within the range of the open/close angle
var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);
return (betweenAngles && withinRadius);
//Ensure within the outside of the arc centre, but inside arc outer
},
tooltipPosition : function(){
var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
return {
x : this.x + (Math.cos(centreAngle) * rangeFromCentre),
y : this.y + (Math.sin(centreAngle) * rangeFromCentre)
};
},
draw : function(animationPercent){
var easingDecimal = animationPercent || 1;
var ctx = this.ctx;
ctx.beginPath();
ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);
ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);
ctx.closePath();
ctx.strokeStyle = this.strokeColor;
ctx.lineWidth = this.strokeWidth;
ctx.fillStyle = this.fillColor;
ctx.fill();
ctx.lineJoin = 'bevel';
if (this.showStroke){
ctx.stroke();
}
}
});
Chart.Rectangle = Chart.Element.extend({
draw : function(){
var ctx = this.ctx,
halfWidth = this.width/2,
leftX = this.x - halfWidth,
rightX = this.x + halfWidth,
top = this.base - (this.base - this.y),
halfStroke = this.strokeWidth / 2;
// Canvas doesn't allow us to stroke inside the width so we can
// adjust the sizes to fit if we're setting a stroke on the line
if (this.showStroke){
leftX += halfStroke;
rightX -= halfStroke;
top += halfStroke;
}
ctx.beginPath();
ctx.fillStyle = this.fillColor;
ctx.strokeStyle = this.strokeColor;
ctx.lineWidth = this.strokeWidth;
// It'd be nice to keep this class totally generic to any rectangle
// and simply specify which border to miss out.
ctx.moveTo(leftX, this.base);
ctx.lineTo(leftX, top);
ctx.lineTo(rightX, top);
ctx.lineTo(rightX, this.base);
ctx.fill();
if (this.showStroke){
ctx.stroke();
}
},
height : function(){
return this.base - this.y;
},
inRange : function(chartX,chartY){
return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);
}
});
Chart.Tooltip = Chart.Element.extend({
draw : function(){
var ctx = this.chart.ctx;
ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
this.xAlign = "center";
this.yAlign = "above";
//Distance between the actual element.y position and the start of the tooltip caret
var caretPadding = 2;
var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
tooltipRectHeight = this.fontSize + 2*this.yPadding,
tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;
if (this.x + tooltipWidth/2 >this.chart.width){
this.xAlign = "left";
} else if (this.x - tooltipWidth/2 < 0){
this.xAlign = "right";
}
if (this.y - tooltipHeight < 0){
this.yAlign = "below";
}
var tooltipX = this.x - tooltipWidth/2,
tooltipY = this.y - tooltipHeight;
ctx.fillStyle = this.fillColor;
switch(this.yAlign)
{
case "above":
//Draw a caret above the x/y
ctx.beginPath();
ctx.moveTo(this.x,this.y - caretPadding);
ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
ctx.closePath();
ctx.fill();
break;
case "below":
tooltipY = this.y + caretPadding + this.caretHeight;
//Draw a caret below the x/y
ctx.beginPath();
ctx.moveTo(this.x, this.y + caretPadding);
ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
ctx.closePath();
ctx.fill();
break;
}
switch(this.xAlign)
{
case "left":
tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
break;
case "right":
tooltipX = this.x - (this.cornerRadius + this.caretHeight);
break;
}
drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
ctx.fill();
ctx.fillStyle = this.textColor;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
}
});
Chart.MultiTooltip = Chart.Element.extend({
initialize : function(){
this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);
this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;
this.ctx.font = this.titleFont;
var titleWidth = this.ctx.measureText(this.title).width,
//Label has a legend square as well so account for this.
labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,
longestTextWidth = max([labelWidth,titleWidth]);
this.width = longestTextWidth + (this.xPadding*2);
var halfHeight = this.height/2;
//Check to ensure the height will fit on the canvas
//The three is to buffer form the very
if (this.y - halfHeight < 0 ){
this.y = halfHeight;
} else if (this.y + halfHeight > this.chart.height){
this.y = this.chart.height - halfHeight;
}
//Decide whether to align left or right based on position on canvas
if (this.x > this.chart.width/2){
this.x -= this.xOffset + this.width;
} else {
this.x += this.xOffset;
}
},
getLineHeight : function(index){
var baseLineHeight = this.y - (this.height/2) + this.yPadding,
afterTitleIndex = index-1;
//If the index is zero, we're getting the title
if (index === 0){
return baseLineHeight + this.titleFontSize/2;
} else{
return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;
}
},
draw : function(){
drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
var ctx = this.ctx;
ctx.fillStyle = this.fillColor;
ctx.fill();
ctx.closePath();
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillStyle = this.titleTextColor;
ctx.font = this.titleFont;
ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
ctx.font = this.font;
helpers.each(this.labels,function(label,index){
ctx.fillStyle = this.textColor;
ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
//A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
//ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
//Instead we'll make a white filled block to put the legendColour palette over.
ctx.fillStyle = this.legendColorBackground;
ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
ctx.fillStyle = this.legendColors[index].fill;
ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
},this);
}
});
Chart.Scale = Chart.Element.extend({
initialize : function(){
this.fit();
},
buildYLabels : function(){
this.yLabels = [];
var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
for (var i=0; i<=this.steps; i++){
this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
}
this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;
},
addXLabel : function(label){
this.xLabels.push(label);
this.valuesCount++;
this.fit();
},
removeXLabel : function(){
this.xLabels.shift();
this.valuesCount--;
this.fit();
},
// Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use
fit: function(){
// First we need the width of the yLabels, assuming the xLabels aren't rotated
// To do that we need the base line at the top and base of the chart, assuming there is no x label rotation
this.startPoint = (this.display) ? this.fontSize : 0;
this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels
// Apply padding settings to the start and end point.
this.startPoint += this.padding;
this.endPoint -= this.padding;
// Cache the starting height, so can determine if we need to recalculate the scale yAxis
var cachedHeight = this.endPoint - this.startPoint,
cachedYLabelWidth;
// Build the current yLabels so we have an idea of what size they'll be to start
/*
* This sets what is returned from calculateScaleRange as static properties of this class:
*
this.steps;
this.stepValue;
this.min;
this.max;
*
*/
this.calculateYRange(cachedHeight);
// With these properties set we can now build the array of yLabels
// and also the width of the largest yLabel
this.buildYLabels();
this.calculateXLabelRotation();
while((cachedHeight > this.endPoint - this.startPoint)){
cachedHeight = this.endPoint - this.startPoint;
cachedYLabelWidth = this.yLabelWidth;
this.calculateYRange(cachedHeight);
this.buildYLabels();
// Only go through the xLabel loop again if the yLabel width has changed
if (cachedYLabelWidth < this.yLabelWidth){
this.calculateXLabelRotation();
}
}
},
calculateXLabelRotation : function(){
//Get the width of each grid by calculating the difference
//between x offsets between 0 and 1.
this.ctx.font = this.font;
var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
firstRotated,
lastRotated;
this.xScalePaddingRight = lastWidth/2 + 3;
this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;
this.xLabelRotation = 0;
if (this.display){
var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),
cosRotation,
firstRotatedWidth;
this.xLabelWidth = originalLabelWidth;
//Allow 3 pixels x2 padding either side for label readability
var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
//Max label rotate should be 90 - also act as a loop counter
while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){
cosRotation = Math.cos(toRadians(this.xLabelRotation));
firstRotated = cosRotation * firstWidth;
lastRotated = cosRotation * lastWidth;
// We're right aligning the text now.
if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){
this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
}
this.xScalePaddingRight = this.fontSize/2;
this.xLabelRotation++;
this.xLabelWidth = cosRotation * originalLabelWidth;
}
if (this.xLabelRotation > 0){
this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;
}
}
else{
this.xLabelWidth = 0;
this.xScalePaddingRight = this.padding;
this.xScalePaddingLeft = this.padding;
}
},
// Needs to be overidden in each Chart type
// Otherwise we need to pass all the data into the scale class
calculateYRange: noop,
drawingArea: function(){
return this.startPoint - this.endPoint;
},
calculateY : function(value){
var scalingFactor = this.drawingArea() / (this.min - this.max);
return this.endPoint - (scalingFactor * (value - this.min));
},
calculateX : function(index){
var isRotated = (this.xLabelRotation > 0),
// innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,
innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
valueWidth = innerWidth/(this.valuesCount - ((this.offsetGridLines) ? 0 : 1)),
valueOffset = (valueWidth * index) + this.xScalePaddingLeft;
if (this.offsetGridLines){
valueOffset += (valueWidth/2);
}
return Math.round(valueOffset);
},
update : function(newProps){
helpers.extend(this, newProps);
this.fit();
},
draw : function(){
var ctx = this.ctx,
yLabelGap = (this.endPoint - this.startPoint) / this.steps,
xStart = Math.round(this.xScalePaddingLeft);
if (this.display){
ctx.fillStyle = this.textColor;
ctx.font = this.font;
each(this.yLabels,function(labelString,index){
var yLabelCenter = this.endPoint - (yLabelGap * index),
linePositionY = Math.round(yLabelCenter);
ctx.textAlign = "right";
ctx.textBaseline = "middle";
if (this.showLabels){
ctx.fillText(labelString,xStart - 10,yLabelCenter);
}
ctx.beginPath();
if (index > 0){
// This is a grid line in the centre, so drop that
ctx.lineWidth = this.gridLineWidth;
ctx.strokeStyle = this.gridLineColor;
} else {
// This is the first line on the scale
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
}
linePositionY += helpers.aliasPixel(ctx.lineWidth);
ctx.moveTo(xStart, linePositionY);
ctx.lineTo(this.width, linePositionY);
ctx.stroke();
ctx.closePath();
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
ctx.beginPath();
ctx.moveTo(xStart - 5, linePositionY);
ctx.lineTo(xStart, linePositionY);
ctx.stroke();
ctx.closePath();
},this);
each(this.xLabels,function(label,index){
var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
// Check to see if line/bar here and decide where to place the line
linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
isRotated = (this.xLabelRotation > 0);
ctx.beginPath();
if (index > 0){
// This is a grid line in the centre, so drop that
ctx.lineWidth = this.gridLineWidth;
ctx.strokeStyle = this.gridLineColor;
} else {
// This is the first line on the scale
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
}
ctx.moveTo(linePos,this.endPoint);
ctx.lineTo(linePos,this.startPoint - 3);
ctx.stroke();
ctx.closePath();
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
// Small lines at the bottom of the base grid line
ctx.beginPath();
ctx.moveTo(linePos,this.endPoint);
ctx.lineTo(linePos,this.endPoint + 5);
ctx.stroke();
ctx.closePath();
ctx.save();
ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);
ctx.rotate(toRadians(this.xLabelRotation)*-1);
ctx.font = this.font;
ctx.textAlign = (isRotated) ? "right" : "center";
ctx.textBaseline = (isRotated) ? "middle" : "top";
ctx.fillText(label, 0, 0);
ctx.restore();
},this);
}
}
});
Chart.RadialScale = Chart.Element.extend({
initialize: function(){
this.size = min([this.height, this.width]);
this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
},
calculateCenterOffset: function(value){
// Take into account half font size + the yPadding of the top value
var scalingFactor = this.drawingArea / (this.max - this.min);
return (value - this.min) * scalingFactor;
},
update : function(){
if (!this.lineArc){
this.setScaleSize();
} else {
this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
}
this.buildYLabels();
},
buildYLabels: function(){
this.yLabels = [];
var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
for (var i=0; i<=this.steps; i++){
this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
}
},
getCircumference : function(){
return ((Math.PI*2) / this.valuesCount);
},
setScaleSize: function(){
/*
* Right, this is really confusing and there is a lot of maths going on here
* The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
*
* Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
*
* Solution:
*
* We assume the radius of the polygon is half the size of the canvas at first
* at each index we check if the text overlaps.
*
* Where it does, we store that angle and that index.
*
* After finding the largest index and angle we calculate how much we need to remove
* from the shape radius to move the point inwards by that x.
*
* We average the left and right distances to get the maximum shape radius that can fit in the box
* along with labels.
*
* Once we have that, we can find the centre point for the chart, by taking the x text protrusion
* on each side, removing that from the size, halving it and adding the left x protrusion width.
*
* This will mean we have a shape fitted to the canvas, as large as it can be with the labels
* and position it in the most space efficient manner
*
* https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
*/
// Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
// Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),
pointPosition,
i,
textWidth,
halfTextWidth,
furthestRight = this.width,
furthestRightIndex,
furthestRightAngle,
furthestLeft = 0,
furthestLeftIndex,
furthestLeftAngle,
xProtrusionLeft,
xProtrusionRight,
radiusReductionRight,
radiusReductionLeft,
maxWidthRadius;
this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
for (i=0;i<this.valuesCount;i++){
// 5px to space the text slightly out - similar to what we do in the draw function.
pointPosition = this.getPointPosition(i, largestPossibleRadius);
textWidth = this.ctx.measureText(template(this.templateString, { value: this.labels[i] })).width + 5;
if (i === 0 || i === this.valuesCount/2){
// If we're at index zero, or exactly the middle, we're at exactly the top/bottom
// of the radar chart, so text will be aligned centrally, so we'll half it and compare
// w/left and right text sizes
halfTextWidth = textWidth/2;
if (pointPosition.x + halfTextWidth > furthestRight) {
furthestRight = pointPosition.x + halfTextWidth;
furthestRightIndex = i;
}
if (pointPosition.x - halfTextWidth < furthestLeft) {
furthestLeft = pointPosition.x - halfTextWidth;
furthestLeftIndex = i;
}
}
else if (i < this.valuesCount/2) {
// Less than half the values means we'll left align the text
if (pointPosition.x + textWidth > furthestRight) {
furthestRight = pointPosition.x + textWidth;
furthestRightIndex = i;
}
}
else if (i > this.valuesCount/2){
// More than half the values means we'll right align the text
if (pointPosition.x - textWidth < furthestLeft) {
furthestLeft = pointPosition.x - textWidth;
furthestLeftIndex = i;
}
}
}
xProtrusionLeft = furthestLeft;
xProtrusionRight = Math.ceil(furthestRight - this.width);
furthestRightAngle = this.getIndexAngle(furthestRightIndex);
furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);
radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);
// Ensure we actually need to reduce the size of the chart
radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;
//this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])
this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
},
setCenterPoint: function(leftMovement, rightMovement){
var maxRight = this.width - rightMovement - this.drawingArea,
maxLeft = leftMovement + this.drawingArea;
this.xCenter = (maxLeft + maxRight)/2;
// Always vertically in the centre as the text height doesn't change
this.yCenter = (this.height/2);
},
getIndexAngle : function(index){
var angleMultiplier = (Math.PI * 2) / this.valuesCount;
// Start from the top instead of right, so remove a quarter of the circle
return index * angleMultiplier - (Math.PI/2);
},
getPointPosition : function(index, distanceFromCenter){
var thisAngle = this.getIndexAngle(index);
return {
x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,
y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter
};
},
draw: function(){
if (this.display){
var ctx = this.ctx;
each(this.yLabels, function(label, index){
// Don't draw a centre value
if (index > 0){
var yCenterOffset = index * (this.drawingArea/this.steps),
yHeight = this.yCenter - yCenterOffset,
pointPosition;
// Draw circular lines around the scale
if (this.lineWidth > 0){
ctx.strokeStyle = this.lineColor;
ctx.lineWidth = this.lineWidth;
if(this.lineArc){
ctx.beginPath();
ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);
ctx.closePath();
ctx.stroke();
} else{
ctx.beginPath();
for (var i=0;i<this.valuesCount;i++)
{
pointPosition = this.getPointPosition(i, this.calculateCenterOffset(this.min + (index * this.stepValue)));
if (i === 0){
ctx.moveTo(pointPosition.x, pointPosition.y);
} else {
ctx.lineTo(pointPosition.x, pointPosition.y);
}
}
ctx.closePath();
ctx.stroke();
}
}
if(this.showLabels){
ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
if (this.showLabelBackdrop){
var labelWidth = ctx.measureText(label).width;
ctx.fillStyle = this.backdropColor;
ctx.fillRect(
this.xCenter - labelWidth/2 - this.backdropPaddingX,
yHeight - this.fontSize/2 - this.backdropPaddingY,
labelWidth + this.backdropPaddingX*2,
this.fontSize + this.backdropPaddingY*2
);
}
ctx.textAlign = 'center';
ctx.textBaseline = "middle";
ctx.fillStyle = this.fontColor;
ctx.fillText(label, this.xCenter, yHeight);
}
}
}, this);
if (!this.lineArc){
ctx.lineWidth = this.angleLineWidth;
ctx.strokeStyle = this.angleLineColor;
for (var i = this.valuesCount - 1; i >= 0; i--) {
if (this.angleLineWidth > 0){
var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));
ctx.beginPath();
ctx.moveTo(this.xCenter, this.yCenter);
ctx.lineTo(outerPosition.x, outerPosition.y);
ctx.stroke();
ctx.closePath();
}
// Extra 3px out for some label spacing
var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);
ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
ctx.fillStyle = this.pointLabelFontColor;
var labelsCount = this.labels.length,
halfLabelsCount = this.labels.length/2,
quarterLabelsCount = halfLabelsCount/2,
upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
if (i === 0){
ctx.textAlign = 'center';
} else if(i === halfLabelsCount){
ctx.textAlign = 'center';
} else if (i < halfLabelsCount){
ctx.textAlign = 'left';
} else {
ctx.textAlign = 'right';
}
// Set the correct text baseline based on outer positioning
if (exactQuarter){
ctx.textBaseline = 'middle';
} else if (upperHalf){
ctx.textBaseline = 'bottom';
} else {
ctx.textBaseline = 'top';
}
ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);
}
}
}
}
});
// Attach global event to resize each chart instance when the browser resizes
helpers.addEvent(window, "resize", (function(){
// Basic debounce of resize function so it doesn't hurt performance when resizing browser.
var timeout;
return function(){
clearTimeout(timeout);
timeout = setTimeout(function(){
each(Chart.instances,function(instance){
// If the responsive flag is set in the chart instance config
// Cascade the resize event down to the chart.
if (instance.options.responsive){
instance.resize(instance.render, true);
}
});
}, 50);
};
})());
if (amd) {
define(function(){
return Chart;
});
} else if (typeof module === 'object' && module.exports) {
module.exports = Chart;
}
root.Chart = Chart;
Chart.noConflict = function(){
root.Chart = previous;
return Chart;
};
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
scaleBeginAtZero : true,
//Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,
//String - Colour of the grid lines
scaleGridLineColor : "rgba(0,0,0,.05)",
//Number - Width of the grid lines
scaleGridLineWidth : 1,
//Boolean - If there is a stroke on each bar
barShowStroke : true,
//Number - Pixel width of the bar stroke
barStrokeWidth : 2,
//Number - Spacing between each of the X value sets
barValueSpacing : 5,
//Number - Spacing between data sets within X values
barDatasetSpacing : 1,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
name: "Bar",
defaults : defaultConfig,
initialize: function(data){
//Expose options as a scope variable here so we can access it in the ScaleClass
var options = this.options;
this.ScaleClass = Chart.Scale.extend({
offsetGridLines : true,
calculateBarX : function(datasetCount, datasetIndex, barIndex){
//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
var xWidth = this.calculateBaseWidth(),
xAbsolute = this.calculateX(barIndex) - (xWidth/2),
barWidth = this.calculateBarWidth(datasetCount);
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
},
calculateBaseWidth : function(){
return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
},
calculateBarWidth : function(datasetCount){
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
return (baseWidth / datasetCount);
}
});
this.datasets = [];
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
this.eachBars(function(bar){
bar.restore(['fillColor', 'strokeColor']);
});
helpers.each(activeBars, function(activeBar){
activeBar.fillColor = activeBar.highlightFill;
activeBar.strokeColor = activeBar.highlightStroke;
});
this.showTooltip(activeBars);
});
}
//Declare the extension of the default point, to cater for the options passed in to the constructor
this.BarClass = Chart.Rectangle.extend({
strokeWidth : this.options.barStrokeWidth,
showStroke : this.options.barShowStroke,
ctx : this.chart.ctx
});
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets,function(dataset,datasetIndex){
var datasetObject = {
label : dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
bars : []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data,function(dataPoint,index){
//Add a new point for each piece of data, passing any required data to draw.
datasetObject.bars.push(new this.BarClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
strokeColor : dataset.strokeColor,
fillColor : dataset.fillColor,
highlightFill : dataset.highlightFill || dataset.fillColor,
highlightStroke : dataset.highlightStroke || dataset.strokeColor
}));
},this);
},this);
this.buildScale(data.labels);
this.BarClass.prototype.base = this.scale.endPoint;
this.eachBars(function(bar, index, datasetIndex){
helpers.extend(bar, {
width : this.scale.calculateBarWidth(this.datasets.length),
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y: this.scale.endPoint
});
bar.save();
}, this);
this.render();
},
update : function(){
this.scale.update();
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor', 'strokeColor']);
});
this.eachBars(function(bar){
bar.save();
});
this.render();
},
eachBars : function(callback){
helpers.each(this.datasets,function(dataset, datasetIndex){
helpers.each(dataset.bars, callback, this, datasetIndex);
},this);
},
getBarsAtEvent : function(e){
var barsArray = [],
eventPosition = helpers.getRelativePosition(e),
datasetIterator = function(dataset){
barsArray.push(dataset.bars[barIndex]);
},
barIndex;
for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
helpers.each(this.datasets, datasetIterator);
return barsArray;
}
}
}
return barsArray;
},
buildScale : function(labels){
var self = this;
var dataTotal = function(){
var values = [];
self.eachBars(function(bar){
values.push(bar.value);
});
return values;
};
var scaleOptions = {
templateString : this.options.scaleLabel,
height : this.chart.height,
width : this.chart.width,
ctx : this.chart.ctx,
textColor : this.options.scaleFontColor,
fontSize : this.options.scaleFontSize,
fontStyle : this.options.scaleFontStyle,
fontFamily : this.options.scaleFontFamily,
valuesCount : labels.length,
beginAtZero : this.options.scaleBeginAtZero,
integersOnly : this.options.scaleIntegersOnly,
calculateYRange: function(currentHeight){
var updatedRanges = helpers.calculateScaleRange(
dataTotal(),
currentHeight,
this.fontSize,
this.beginAtZero,
this.integersOnly
);
helpers.extend(this, updatedRanges);
},
xLabels : labels,
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth : this.options.scaleLineWidth,
lineColor : this.options.scaleLineColor,
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
showLabels : this.options.scaleShowLabels,
display : this.options.showScale
};
if (this.options.scaleOverride){
helpers.extend(scaleOptions, {
calculateYRange: helpers.noop,
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
});
}
this.scale = new this.ScaleClass(scaleOptions);
},
addData : function(valuesArray,label){
//Map the values array for each of the datasets
helpers.each(valuesArray,function(value,datasetIndex){
//Add a new point for each piece of data, passing any required data to draw.
this.datasets[datasetIndex].bars.push(new this.BarClass({
value : value,
label : label,
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
y: this.scale.endPoint,
width : this.scale.calculateBarWidth(this.datasets.length),
base : this.scale.endPoint,
strokeColor : this.datasets[datasetIndex].strokeColor,
fillColor : this.datasets[datasetIndex].fillColor
}));
},this);
this.scale.addXLabel(label);
//Then re-render the chart.
this.update();
},
removeData : function(){
this.scale.removeXLabel();
//Then re-render the chart.
helpers.each(this.datasets,function(dataset){
dataset.bars.shift();
},this);
this.update();
},
reflow : function(){
helpers.extend(this.BarClass.prototype,{
y: this.scale.endPoint,
base : this.scale.endPoint
});
var newScaleProps = helpers.extend({
height : this.chart.height,
width : this.chart.width
});
this.scale.update(newScaleProps);
},
draw : function(ease){
var easingDecimal = ease || 1;
this.clear();
var ctx = this.chart.ctx;
this.scale.draw(easingDecimal);
//Draw all the bars for each dataset
helpers.each(this.datasets,function(dataset,datasetIndex){
helpers.each(dataset.bars,function(bar,index){
if (bar.hasValue()){
bar.base = this.scale.endPoint;
//Transition then draw
bar.transition({
x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y : this.scale.calculateY(bar.value),
width : this.scale.calculateBarWidth(this.datasets.length)
}, easingDecimal).draw();
}
},this);
},this);
}
});
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
//Cache a local reference to Chart.helpers
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,
//String - The colour of each segment stroke
segmentStrokeColor : "#fff",
//Number - The width of each segment stroke
segmentStrokeWidth : 2,
//The percentage of the chart that we cut out of the middle.
percentageInnerCutout : 50,
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect
animationEasing : "easeOutBounce",
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
//Passing in a name registers this chart in the Chart namespace
name: "Doughnut",
//Providing a defaults will also register the deafults in the chart namespace
defaults : defaultConfig,
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
//Config is automatically merged by the core of Chart.js, and is available at this.options
initialize: function(data){
//Declare segments as a static property to prevent inheriting across the Chart type prototype
this.segments = [];
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
this.SegmentArc = Chart.Arc.extend({
ctx : this.chart.ctx,
x : this.chart.width/2,
y : this.chart.height/2
});
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
helpers.each(this.segments,function(segment){
segment.restore(["fillColor"]);
});
helpers.each(activeSegments,function(activeSegment){
activeSegment.fillColor = activeSegment.highlightColor;
});
this.showTooltip(activeSegments);
});
}
this.calculateTotal(data);
helpers.each(data,function(datapoint, index){
this.addData(datapoint, index, true);
},this);
this.render();
},
getSegmentsAtEvent : function(e){
var segmentsArray = [];
var location = helpers.getRelativePosition(e);
helpers.each(this.segments,function(segment){
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
},this);
return segmentsArray;
},
addData : function(segment, atIndex, silent){
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
value : segment.value,
outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
fillColor : segment.color,
highlightColor : segment.highlight || segment.color,
showStroke : this.options.segmentShowStroke,
strokeWidth : this.options.segmentStrokeWidth,
strokeColor : this.options.segmentStrokeColor,
startAngle : Math.PI * 1.5,
circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
label : segment.label
}));
if (!silent){
this.reflow();
this.update();
}
},
calculateCircumference : function(value){
return (Math.PI*2)*(value / this.total);
},
calculateTotal : function(data){
this.total = 0;
helpers.each(data,function(segment){
this.total += segment.value;
},this);
},
update : function(){
this.calculateTotal(this.segments);
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor']);
});
helpers.each(this.segments,function(segment){
segment.save();
});
this.render();
},
removeData: function(atIndex){
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
this.segments.splice(indexToDelete, 1);
this.reflow();
this.update();
},
reflow : function(){
helpers.extend(this.SegmentArc.prototype,{
x : this.chart.width/2,
y : this.chart.height/2
});
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
helpers.each(this.segments, function(segment){
segment.update({
outerRadius : this.outerRadius,
innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
});
}, this);
},
draw : function(easeDecimal){
var animDecimal = (easeDecimal) ? easeDecimal : 1;
this.clear();
helpers.each(this.segments,function(segment,index){
segment.transition({
circumference : this.calculateCircumference(segment.value),
outerRadius : this.outerRadius,
innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
},animDecimal);
segment.endAngle = segment.startAngle + segment.circumference;
segment.draw();
if (index === 0){
segment.startAngle = Math.PI * 1.5;
}
//Check to see if it's the last segment, if not get the next and update the start angle
if (index < this.segments.length-1){
this.segments[index+1].startAngle = segment.endAngle;
}
},this);
}
});
Chart.types.Doughnut.extend({
name : "Pie",
defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
});
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
helpers = Chart.helpers;
var defaultConfig = {
///Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,
//String - Colour of the grid lines
scaleGridLineColor : "rgba(0,0,0,.05)",
//Number - Width of the grid lines
scaleGridLineWidth : 1,
//Boolean - Whether the line is curved between points
bezierCurve : true,
//Number - Tension of the bezier curve between points
bezierCurveTension : 0.4,
//Boolean - Whether to show a dot for each point
pointDot : true,
//Number - Radius of each point dot in pixels
pointDotRadius : 4,
//Number - Pixel width of point dot stroke
pointDotStrokeWidth : 1,
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
pointHitDetectionRadius : 20,
//Boolean - Whether to show a stroke for datasets
datasetStroke : true,
//Number - Pixel width of dataset stroke
datasetStrokeWidth : 2,
//Boolean - Whether to fill the dataset with a colour
datasetFill : true,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
name: "Line",
defaults : defaultConfig,
initialize: function(data){
//Declare the extension of the default point, to cater for the options passed in to the constructor
this.PointClass = Chart.Point.extend({
strokeWidth : this.options.pointDotStrokeWidth,
radius : this.options.pointDotRadius,
display: this.options.pointDot,
hitDetectionRadius : this.options.pointHitDetectionRadius,
ctx : this.chart.ctx,
inRange : function(mouseX){
return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));
}
});
this.datasets = [];
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
this.eachPoints(function(point){
point.restore(['fillColor', 'strokeColor']);
});
helpers.each(activePoints, function(activePoint){
activePoint.fillColor = activePoint.highlightFill;
activePoint.strokeColor = activePoint.highlightStroke;
});
this.showTooltip(activePoints);
});
}
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets,function(dataset){
var datasetObject = {
label : dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
pointColor : dataset.pointColor,
pointStrokeColor : dataset.pointStrokeColor,
points : []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data,function(dataPoint,index){
//Add a new point for each piece of data, passing any required data to draw.
datasetObject.points.push(new this.PointClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
strokeColor : dataset.pointStrokeColor,
fillColor : dataset.pointColor,
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
}));
},this);
this.buildScale(data.labels);
this.eachPoints(function(point, index){
helpers.extend(point, {
x: this.scale.calculateX(index),
y: this.scale.endPoint
});
point.save();
}, this);
},this);
this.render();
},
update : function(){
this.scale.update();
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor', 'strokeColor']);
});
this.eachPoints(function(point){
point.save();
});
this.render();
},
eachPoints : function(callback){
helpers.each(this.datasets,function(dataset){
helpers.each(dataset.points,callback,this);
},this);
},
getPointsAtEvent : function(e){
var pointsArray = [],
eventPosition = helpers.getRelativePosition(e);
helpers.each(this.datasets,function(dataset){
helpers.each(dataset.points,function(point){
if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);
});
},this);
return pointsArray;
},
buildScale : function(labels){
var self = this;
var dataTotal = function(){
var values = [];
self.eachPoints(function(point){
values.push(point.value);
});
return values;
};
var scaleOptions = {
templateString : this.options.scaleLabel,
height : this.chart.height,
width : this.chart.width,
ctx : this.chart.ctx,
textColor : this.options.scaleFontColor,
fontSize : this.options.scaleFontSize,
fontStyle : this.options.scaleFontStyle,
fontFamily : this.options.scaleFontFamily,
valuesCount : labels.length,
beginAtZero : this.options.scaleBeginAtZero,
integersOnly : this.options.scaleIntegersOnly,
calculateYRange : function(currentHeight){
var updatedRanges = helpers.calculateScaleRange(
dataTotal(),
currentHeight,
this.fontSize,
this.beginAtZero,
this.integersOnly
);
helpers.extend(this, updatedRanges);
},
xLabels : labels,
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth : this.options.scaleLineWidth,
lineColor : this.options.scaleLineColor,
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
showLabels : this.options.scaleShowLabels,
display : this.options.showScale
};
if (this.options.scaleOverride){
helpers.extend(scaleOptions, {
calculateYRange: helpers.noop,
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
});
}
this.scale = new Chart.Scale(scaleOptions);
},
addData : function(valuesArray,label){
//Map the values array for each of the datasets
helpers.each(valuesArray,function(value,datasetIndex){
//Add a new point for each piece of data, passing any required data to draw.
this.datasets[datasetIndex].points.push(new this.PointClass({
value : value,
label : label,
x: this.scale.calculateX(this.scale.valuesCount+1),
y: this.scale.endPoint,
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
fillColor : this.datasets[datasetIndex].pointColor
}));
},this);
this.scale.addXLabel(label);
//Then re-render the chart.
this.update();
},
removeData : function(){
this.scale.removeXLabel();
//Then re-render the chart.
helpers.each(this.datasets,function(dataset){
dataset.points.shift();
},this);
this.update();
},
reflow : function(){
var newScaleProps = helpers.extend({
height : this.chart.height,
width : this.chart.width
});
this.scale.update(newScaleProps);
},
draw : function(ease){
var easingDecimal = ease || 1;
this.clear();
var ctx = this.chart.ctx;
// Some helper methods for getting the next/prev points
var hasValue = function(item){
return item.value !== null;
},
nextPoint = function(point, collection, index){
return helpers.findNextWhere(collection, hasValue, index) || point;
},
previousPoint = function(point, collection, index){
return helpers.findPreviousWhere(collection, hasValue, index) || point;
};
this.scale.draw(easingDecimal);
helpers.each(this.datasets,function(dataset){
var pointsWithValues = helpers.where(dataset.points, hasValue);
//Transition each point first so that the line and point drawing isn't out of sync
//We can use this extra loop to calculate the control points of this dataset also in this loop
helpers.each(dataset.points, function(point, index){
if (point.hasValue()){
point.transition({
y : this.scale.calculateY(point.value),
x : this.scale.calculateX(index)
}, easingDecimal);
}
},this);
// Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
// This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
if (this.options.bezierCurve){
helpers.each(pointsWithValues, function(point, index){
var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;
point.controlPoints = helpers.splineCurve(
previousPoint(point, pointsWithValues, index),
point,
nextPoint(point, pointsWithValues, index),
tension
);
// Prevent the bezier going outside of the bounds of the graph
// Cap puter bezier handles to the upper/lower scale bounds
if (point.controlPoints.outer.y > this.scale.endPoint){
point.controlPoints.outer.y = this.scale.endPoint;
}
else if (point.controlPoints.outer.y < this.scale.startPoint){
point.controlPoints.outer.y = this.scale.startPoint;
}
// Cap inner bezier handles to the upper/lower scale bounds
if (point.controlPoints.inner.y > this.scale.endPoint){
point.controlPoints.inner.y = this.scale.endPoint;
}
else if (point.controlPoints.inner.y < this.scale.startPoint){
point.controlPoints.inner.y = this.scale.startPoint;
}
},this);
}
//Draw the line between all the points
ctx.lineWidth = this.options.datasetStrokeWidth;
ctx.strokeStyle = dataset.strokeColor;
ctx.beginPath();
helpers.each(pointsWithValues, function(point, index){
if (index === 0){
ctx.moveTo(point.x, point.y);
}
else{
if(this.options.bezierCurve){
var previous = previousPoint(point, pointsWithValues, index);
ctx.bezierCurveTo(
previous.controlPoints.outer.x,
previous.controlPoints.outer.y,
point.controlPoints.inner.x,
point.controlPoints.inner.y,
point.x,
point.y
);
}
else{
ctx.lineTo(point.x,point.y);
}
}
}, this);
ctx.stroke();
if (this.options.datasetFill && pointsWithValues.length > 0){
//Round off the line by going to the base of the chart, back to the start, then fill.
ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);
ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);
ctx.fillStyle = dataset.fillColor;
ctx.closePath();
ctx.fill();
}
//Now draw the points over the line
//A little inefficient double looping, but better than the line
//lagging behind the point positions
helpers.each(pointsWithValues,function(point){
point.draw();
});
},this);
}
});
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
//Cache a local reference to Chart.helpers
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Show a backdrop to the scale label
scaleShowLabelBackdrop : true,
//String - The colour of the label backdrop
scaleBackdropColor : "rgba(255,255,255,0.75)",
// Boolean - Whether the scale should begin at zero
scaleBeginAtZero : true,
//Number - The backdrop padding above & below the label in pixels
scaleBackdropPaddingY : 2,
//Number - The backdrop padding to the side of the label in pixels
scaleBackdropPaddingX : 2,
//Boolean - Show line for each value in the scale
scaleShowLine : true,
//Boolean - Stroke a line around each segment in the chart
segmentShowStroke : true,
//String - The colour of the stroke on each segement.
segmentStrokeColor : "#fff",
//Number - The width of the stroke value in pixels
segmentStrokeWidth : 2,
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect.
animationEasing : "easeOutBounce",
//Boolean - Whether to animate the rotation of the chart
animateRotate : true,
//Boolean - Whether to animate scaling the chart from the centre
animateScale : false,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
//Passing in a name registers this chart in the Chart namespace
name: "PolarArea",
//Providing a defaults will also register the deafults in the chart namespace
defaults : defaultConfig,
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
//Config is automatically merged by the core of Chart.js, and is available at this.options
initialize: function(data){
this.segments = [];
//Declare segment class as a chart instance specific class, so it can share props for this instance
this.SegmentArc = Chart.Arc.extend({
showStroke : this.options.segmentShowStroke,
strokeWidth : this.options.segmentStrokeWidth,
strokeColor : this.options.segmentStrokeColor,
ctx : this.chart.ctx,
innerRadius : 0,
x : this.chart.width/2,
y : this.chart.height/2
});
this.scale = new Chart.RadialScale({
display: this.options.showScale,
fontStyle: this.options.scaleFontStyle,
fontSize: this.options.scaleFontSize,
fontFamily: this.options.scaleFontFamily,
fontColor: this.options.scaleFontColor,
showLabels: this.options.scaleShowLabels,
showLabelBackdrop: this.options.scaleShowLabelBackdrop,
backdropColor: this.options.scaleBackdropColor,
backdropPaddingY : this.options.scaleBackdropPaddingY,
backdropPaddingX: this.options.scaleBackdropPaddingX,
lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
lineColor: this.options.scaleLineColor,
lineArc: true,
width: this.chart.width,
height: this.chart.height,
xCenter: this.chart.width/2,
yCenter: this.chart.height/2,
ctx : this.chart.ctx,
templateString: this.options.scaleLabel,
valuesCount: data.length
});
this.updateScaleRange(data);
this.scale.update();
helpers.each(data,function(segment,index){
this.addData(segment,index,true);
},this);
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
helpers.each(this.segments,function(segment){
segment.restore(["fillColor"]);
});
helpers.each(activeSegments,function(activeSegment){
activeSegment.fillColor = activeSegment.highlightColor;
});
this.showTooltip(activeSegments);
});
}
this.render();
},
getSegmentsAtEvent : function(e){
var segmentsArray = [];
var location = helpers.getRelativePosition(e);
helpers.each(this.segments,function(segment){
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
},this);
return segmentsArray;
},
addData : function(segment, atIndex, silent){
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
fillColor: segment.color,
highlightColor: segment.highlight || segment.color,
label: segment.label,
value: segment.value,
outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
startAngle: Math.PI * 1.5
}));
if (!silent){
this.reflow();
this.update();
}
},
removeData: function(atIndex){
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
this.segments.splice(indexToDelete, 1);
this.reflow();
this.update();
},
calculateTotal: function(data){
this.total = 0;
helpers.each(data,function(segment){
this.total += segment.value;
},this);
this.scale.valuesCount = this.segments.length;
},
updateScaleRange: function(datapoints){
var valuesArray = [];
helpers.each(datapoints,function(segment){
valuesArray.push(segment.value);
});
var scaleSizes = (this.options.scaleOverride) ?
{
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
} :
helpers.calculateScaleRange(
valuesArray,
helpers.min([this.chart.width, this.chart.height])/2,
this.options.scaleFontSize,
this.options.scaleBeginAtZero,
this.options.scaleIntegersOnly
);
helpers.extend(
this.scale,
scaleSizes,
{
size: helpers.min([this.chart.width, this.chart.height]),
xCenter: this.chart.width/2,
yCenter: this.chart.height/2
}
);
},
update : function(){
this.calculateTotal(this.segments);
helpers.each(this.segments,function(segment){
segment.save();
});
this.render();
},
reflow : function(){
helpers.extend(this.SegmentArc.prototype,{
x : this.chart.width/2,
y : this.chart.height/2
});
this.updateScaleRange(this.segments);
this.scale.update();
helpers.extend(this.scale,{
xCenter: this.chart.width/2,
yCenter: this.chart.height/2
});
helpers.each(this.segments, function(segment){
segment.update({
outerRadius : this.scale.calculateCenterOffset(segment.value)
});
}, this);
},
draw : function(ease){
var easingDecimal = ease || 1;
//Clear & draw the canvas
this.clear();
helpers.each(this.segments,function(segment, index){
segment.transition({
circumference : this.scale.getCircumference(),
outerRadius : this.scale.calculateCenterOffset(segment.value)
},easingDecimal);
segment.endAngle = segment.startAngle + segment.circumference;
// If we've removed the first segment we need to set the first one to
// start at the top.
if (index === 0){
segment.startAngle = Math.PI * 1.5;
}
//Check to see if it's the last segment, if not get the next and update the start angle
if (index < this.segments.length - 1){
this.segments[index+1].startAngle = segment.endAngle;
}
segment.draw();
}, this);
this.scale.draw();
}
});
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
helpers = Chart.helpers;
Chart.Type.extend({
name: "Radar",
defaults:{
//Boolean - Whether to show lines for each scale point
scaleShowLine : true,
//Boolean - Whether we show the angle lines out of the radar
angleShowLineOut : true,
//Boolean - Whether to show labels on the scale
scaleShowLabels : false,
// Boolean - Whether the scale should begin at zero
scaleBeginAtZero : true,
//String - Colour of the angle line
angleLineColor : "rgba(0,0,0,.1)",
//Number - Pixel width of the angle line
angleLineWidth : 1,
//String - Point label font declaration
pointLabelFontFamily : "'Arial'",
//String - Point label font weight
pointLabelFontStyle : "normal",
//Number - Point label font size in pixels
pointLabelFontSize : 10,
//String - Point label font colour
pointLabelFontColor : "#666",
//Boolean - Whether to show a dot for each point
pointDot : true,
//Number - Radius of each point dot in pixels
pointDotRadius : 3,
//Number - Pixel width of point dot stroke
pointDotStrokeWidth : 1,
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
pointHitDetectionRadius : 20,
//Boolean - Whether to show a stroke for datasets
datasetStroke : true,
//Number - Pixel width of dataset stroke
datasetStrokeWidth : 2,
//Boolean - Whether to fill the dataset with a colour
datasetFill : true,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
},
initialize: function(data){
this.PointClass = Chart.Point.extend({
strokeWidth : this.options.pointDotStrokeWidth,
radius : this.options.pointDotRadius,
display: this.options.pointDot,
hitDetectionRadius : this.options.pointHitDetectionRadius,
ctx : this.chart.ctx
});
this.datasets = [];
this.buildScale(data);
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
this.eachPoints(function(point){
point.restore(['fillColor', 'strokeColor']);
});
helpers.each(activePointsCollection, function(activePoint){
activePoint.fillColor = activePoint.highlightFill;
activePoint.strokeColor = activePoint.highlightStroke;
});
this.showTooltip(activePointsCollection);
});
}
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets,function(dataset){
var datasetObject = {
label: dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
pointColor : dataset.pointColor,
pointStrokeColor : dataset.pointStrokeColor,
points : []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data,function(dataPoint,index){
//Add a new point for each piece of data, passing any required data to draw.
var pointPosition;
if (!this.scale.animation){
pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
}
datasetObject.points.push(new this.PointClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
strokeColor : dataset.pointStrokeColor,
fillColor : dataset.pointColor,
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
}));
},this);
},this);
this.render();
},
eachPoints : function(callback){
helpers.each(this.datasets,function(dataset){
helpers.each(dataset.points,callback,this);
},this);
},
getPointsAtEvent : function(evt){
var mousePosition = helpers.getRelativePosition(evt),
fromCenter = helpers.getAngleFromPoint({
x: this.scale.xCenter,
y: this.scale.yCenter
}, mousePosition);
var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
activePointsCollection = [];
// If we're at the top, make the pointIndex 0 to get the first of the array.
if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
pointIndex = 0;
}
if (fromCenter.distance <= this.scale.drawingArea){
helpers.each(this.datasets, function(dataset){
activePointsCollection.push(dataset.points[pointIndex]);
});
}
return activePointsCollection;
},
buildScale : function(data){
this.scale = new Chart.RadialScale({
display: this.options.showScale,
fontStyle: this.options.scaleFontStyle,
fontSize: this.options.scaleFontSize,
fontFamily: this.options.scaleFontFamily,
fontColor: this.options.scaleFontColor,
showLabels: this.options.scaleShowLabels,
showLabelBackdrop: this.options.scaleShowLabelBackdrop,
backdropColor: this.options.scaleBackdropColor,
backdropPaddingY : this.options.scaleBackdropPaddingY,
backdropPaddingX: this.options.scaleBackdropPaddingX,
lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
lineColor: this.options.scaleLineColor,
angleLineColor : this.options.angleLineColor,
angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
// Point labels at the edge of each line
pointLabelFontColor : this.options.pointLabelFontColor,
pointLabelFontSize : this.options.pointLabelFontSize,
pointLabelFontFamily : this.options.pointLabelFontFamily,
pointLabelFontStyle : this.options.pointLabelFontStyle,
height : this.chart.height,
width: this.chart.width,
xCenter: this.chart.width/2,
yCenter: this.chart.height/2,
ctx : this.chart.ctx,
templateString: this.options.scaleLabel,
labels: data.labels,
valuesCount: data.datasets[0].data.length
});
this.scale.setScaleSize();
this.updateScaleRange(data.datasets);
this.scale.buildYLabels();
},
updateScaleRange: function(datasets){
var valuesArray = (function(){
var totalDataArray = [];
helpers.each(datasets,function(dataset){
if (dataset.data){
totalDataArray = totalDataArray.concat(dataset.data);
}
else {
helpers.each(dataset.points, function(point){
totalDataArray.push(point.value);
});
}
});
return totalDataArray;
})();
var scaleSizes = (this.options.scaleOverride) ?
{
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
} :
helpers.calculateScaleRange(
valuesArray,
helpers.min([this.chart.width, this.chart.height])/2,
this.options.scaleFontSize,
this.options.scaleBeginAtZero,
this.options.scaleIntegersOnly
);
helpers.extend(
this.scale,
scaleSizes
);
},
addData : function(valuesArray,label){
//Map the values array for each of the datasets
this.scale.valuesCount++;
helpers.each(valuesArray,function(value,datasetIndex){
var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
this.datasets[datasetIndex].points.push(new this.PointClass({
value : value,
label : label,
x: pointPosition.x,
y: pointPosition.y,
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
fillColor : this.datasets[datasetIndex].pointColor
}));
},this);
this.scale.labels.push(label);
this.reflow();
this.update();
},
removeData : function(){
this.scale.valuesCount--;
this.scale.labels.shift();
helpers.each(this.datasets,function(dataset){
dataset.points.shift();
},this);
this.reflow();
this.update();
},
update : function(){
this.eachPoints(function(point){
point.save();
});
this.reflow();
this.render();
},
reflow: function(){
helpers.extend(this.scale, {
width : this.chart.width,
height: this.chart.height,
size : helpers.min([this.chart.width, this.chart.height]),
xCenter: this.chart.width/2,
yCenter: this.chart.height/2
});
this.updateScaleRange(this.datasets);
this.scale.setScaleSize();
this.scale.buildYLabels();
},
draw : function(ease){
var easeDecimal = ease || 1,
ctx = this.chart.ctx;
this.clear();
this.scale.draw();
helpers.each(this.datasets,function(dataset){
//Transition each point first so that the line and point drawing isn't out of sync
helpers.each(dataset.points,function(point,index){
if (point.hasValue()){
point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
}
},this);
//Draw the line between all the points
ctx.lineWidth = this.options.datasetStrokeWidth;
ctx.strokeStyle = dataset.strokeColor;
ctx.beginPath();
helpers.each(dataset.points,function(point,index){
if (index === 0){
ctx.moveTo(point.x,point.y);
}
else{
ctx.lineTo(point.x,point.y);
}
},this);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = dataset.fillColor;
ctx.fill();
//Now draw the points over the line
//A little inefficient double looping, but better than the line
//lagging behind the point positions
helpers.each(dataset.points,function(point){
if (point.hasValue()){
point.draw();
}
});
},this);
}
});
}).call(this);
/*!
* Chart.js
* http://chartjs.org/
* Version: 1.0.1-beta.4
*
* Copyright 2014 Nick Downie
* Released under the MIT license
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
*/
(function(){"use strict";var t=this,i=t.Chart,e=function(t){this.canvas=t.canvas,this.ctx=t;this.width=t.canvas.width,this.height=t.canvas.height;return this.aspectRatio=this.width/this.height,s.retinaScale(this),this};e.defaults={global:{animation:!0,animationSteps:60,animationEasing:"easeOutQuart",showScale:!0,scaleOverride:!1,scaleSteps:null,scaleStepWidth:null,scaleStartValue:null,scaleLineColor:"rgba(0,0,0,.1)",scaleLineWidth:1,scaleShowLabels:!0,scaleLabel:"<%=value%>",scaleIntegersOnly:!0,scaleBeginAtZero:!1,scaleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",scaleFontSize:12,scaleFontStyle:"normal",scaleFontColor:"#666",responsive:!1,maintainAspectRatio:!0,showTooltips:!0,tooltipEvents:["mousemove","touchstart","touchmove","mouseout"],tooltipFillColor:"rgba(0,0,0,0.8)",tooltipFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipFontSize:14,tooltipFontStyle:"normal",tooltipFontColor:"#fff",tooltipTitleFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",tooltipTitleFontSize:14,tooltipTitleFontStyle:"bold",tooltipTitleFontColor:"#fff",tooltipYPadding:6,tooltipXPadding:6,tooltipCaretSize:8,tooltipCornerRadius:6,tooltipXOffset:10,tooltipTemplate:"<%if (label){%><%=label%>: <%}%><%= value %>",multiTooltipTemplate:"<%= value %>",multiTooltipKeyBackground:"#fff",onAnimationProgress:function(){},onAnimationComplete:function(){}}},e.types={};var s=e.helpers={},n=s.each=function(t,i,e){var s=Array.prototype.slice.call(arguments,3);if(t)if(t.length===+t.length){var n;for(n=0;n<t.length;n++)i.apply(e,[t[n],n].concat(s))}else for(var o in t)i.apply(e,[t[o],o].concat(s))},o=s.clone=function(t){var i={};return n(t,function(e,s){t.hasOwnProperty(s)&&(i[s]=e)}),i},a=s.extend=function(t){return n(Array.prototype.slice.call(arguments,1),function(i){n(i,function(e,s){i.hasOwnProperty(s)&&(t[s]=e)})}),t},h=s.merge=function(){var t=Array.prototype.slice.call(arguments,0);return t.unshift({}),a.apply(null,t)},l=s.indexOf=function(t,i){if(Array.prototype.indexOf)return t.indexOf(i);for(var e=0;e<t.length;e++)if(t[e]===i)return e;return-1},r=(s.where=function(t,i){var e=[];return s.each(t,function(t){i(t)&&e.push(t)}),e},s.findNextWhere=function(t,i,e){e||(e=-1);for(var s=e+1;s<t.length;s++){var n=t[s];if(i(n))return n}},s.findPreviousWhere=function(t,i,e){e||(e=t.length);for(var s=e-1;s>=0;s--){var n=t[s];if(i(n))return n}},s.inherits=function(t){var i=this,e=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return i.apply(this,arguments)},s=function(){this.constructor=e};return s.prototype=i.prototype,e.prototype=new s,e.extend=r,t&&a(e.prototype,t),e.__super__=i.prototype,e}),c=s.noop=function(){},u=s.uid=function(){var t=0;return function(){return"chart-"+t++}}(),d=s.warn=function(t){window.console&&"function"==typeof window.console.warn&&console.warn(t)},p=s.amd="function"==typeof t.define&&t.define.amd,f=s.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},g=s.max=function(t){return Math.max.apply(Math,t)},m=s.min=function(t){return Math.min.apply(Math,t)},v=(s.cap=function(t,i,e){if(f(i)){if(t>i)return i}else if(f(e)&&e>t)return e;return t},s.getDecimalPlaces=function(t){return t%1!==0&&f(t)?t.toString().split(".")[1].length:0}),x=s.radians=function(t){return t*(Math.PI/180)},S=(s.getAngleFromPoint=function(t,i){var e=i.x-t.x,s=i.y-t.y,n=Math.sqrt(e*e+s*s),o=2*Math.PI+Math.atan2(s,e);return 0>e&&0>s&&(o+=2*Math.PI),{angle:o,distance:n}},s.aliasPixel=function(t){return t%2===0?0:.5}),y=(s.splineCurve=function(t,i,e,s){var n=Math.sqrt(Math.pow(i.x-t.x,2)+Math.pow(i.y-t.y,2)),o=Math.sqrt(Math.pow(e.x-i.x,2)+Math.pow(e.y-i.y,2)),a=s*n/(n+o),h=s*o/(n+o);return{inner:{x:i.x-a*(e.x-t.x),y:i.y-a*(e.y-t.y)},outer:{x:i.x+h*(e.x-t.x),y:i.y+h*(e.y-t.y)}}},s.calculateOrderOfMagnitude=function(t){return Math.floor(Math.log(t)/Math.LN10)}),C=(s.calculateScaleRange=function(t,i,e,s,n){var o=2,a=Math.floor(i/(1.5*e)),h=o>=a,l=g(t),r=m(t);l===r&&(l+=.5,r>=.5&&!s?r-=.5:l+=.5);for(var c=Math.abs(l-r),u=y(c),d=Math.ceil(l/(1*Math.pow(10,u)))*Math.pow(10,u),p=s?0:Math.floor(r/(1*Math.pow(10,u)))*Math.pow(10,u),f=d-p,v=Math.pow(10,u),x=Math.round(f/v);(x>a||a>2*x)&&!h;)if(x>a)v*=2,x=Math.round(f/v),x%1!==0&&(h=!0);else if(n&&u>=0){if(v/2%1!==0)break;v/=2,x=Math.round(f/v)}else v/=2,x=Math.round(f/v);return h&&(x=o,v=f/x),{steps:x,stepValue:v,min:p,max:p+x*v}},s.template=function(t,i){function e(t,i){var e=/\W/.test(t)?new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+t.replace(/[\r\t\n]/g," ").split("<%").join(" ").replace(/((^|%>)[^\t]*)'/g,"$1\r").replace(/\t=(.*?)%>/g,"',$1,'").split(" ").join("');").split("%>").join("p.push('").split("\r").join("\\'")+"');}return p.join('');"):s[t]=s[t];return i?e(i):e}if(t instanceof Function)return t(i);var s={};return e(t,i)}),b=(s.generateLabels=function(t,i,e,s){var o=new Array(i);return labelTemplateString&&n(o,function(i,n){o[n]=C(t,{value:e+s*(n+1)})}),o},s.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),-(s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)))},easeOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:1==(t/=1)?1:(e||(e=.3),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),s*Math.pow(2,-10*t)*Math.sin(2*(1*t-i)*Math.PI/e)+1)},easeInOutElastic:function(t){var i=1.70158,e=0,s=1;return 0===t?0:2==(t/=.5)?1:(e||(e=.3*1.5),s<Math.abs(1)?(s=1,i=e/4):i=e/(2*Math.PI)*Math.asin(1/s),1>t?-.5*s*Math.pow(2,10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e):s*Math.pow(2,-10*(t-=1))*Math.sin(2*(1*t-i)*Math.PI/e)*.5+1)},easeInBack:function(t){var i=1.70158;return 1*(t/=1)*t*((i+1)*t-i)},easeOutBack:function(t){var i=1.70158;return 1*((t=t/1-1)*t*((i+1)*t+i)+1)},easeInOutBack:function(t){var i=1.70158;return(t/=.5)<1?.5*t*t*(((i*=1.525)+1)*t-i):.5*((t-=2)*t*(((i*=1.525)+1)*t+i)+2)},easeInBounce:function(t){return 1-b.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?7.5625*t*t:2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*b.easeInBounce(2*t):.5*b.easeOutBounce(2*t-1)+.5}}),w=s.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),P=(s.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),s.animationLoop=function(t,i,e,s,n,o){var a=0,h=b[e]||b.linear,l=function(){a++;var e=a/i,r=h(e);t.call(o,r,e,a),s.call(o,r,e),i>a?o.animationFrame=w(l):n.apply(o)};w(l)},s.getRelativePosition=function(t){var i,e,s=t.originalEvent||t,n=t.currentTarget||t.srcElement,o=n.getBoundingClientRect();return s.touches?(i=s.touches[0].clientX-o.left,e=s.touches[0].clientY-o.top):(i=s.clientX-o.left,e=s.clientY-o.top),{x:i,y:e}},s.addEvent=function(t,i,e){t.addEventListener?t.addEventListener(i,e):t.attachEvent?t.attachEvent("on"+i,e):t["on"+i]=e}),L=s.removeEvent=function(t,i,e){t.removeEventListener?t.removeEventListener(i,e,!1):t.detachEvent?t.detachEvent("on"+i,e):t["on"+i]=c},k=(s.bindEvents=function(t,i,e){t.events||(t.events={}),n(i,function(i){t.events[i]=function(){e.apply(t,arguments)},P(t.chart.canvas,i,t.events[i])})},s.unbindEvents=function(t,i){n(i,function(i,e){L(t.chart.canvas,e,i)})}),F=s.getMaximumWidth=function(t){var i=t.parentNode;return i.clientWidth},R=s.getMaximumHeight=function(t){var i=t.parentNode;return i.clientHeight},A=(s.getMaximumSize=s.getMaximumWidth,s.retinaScale=function(t){var i=t.ctx,e=t.canvas.width,s=t.canvas.height;window.devicePixelRatio&&(i.canvas.style.width=e+"px",i.canvas.style.height=s+"px",i.canvas.height=s*window.devicePixelRatio,i.canvas.width=e*window.devicePixelRatio,i.scale(window.devicePixelRatio,window.devicePixelRatio))}),T=s.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},M=s.fontString=function(t,i,e){return i+" "+t+"px "+e},W=s.longestText=function(t,i,e){t.font=i;var s=0;return n(e,function(i){var e=t.measureText(i).width;s=e>s?e:s}),s},z=s.drawRoundedRectangle=function(t,i,e,s,n,o){t.beginPath(),t.moveTo(i+o,e),t.lineTo(i+s-o,e),t.quadraticCurveTo(i+s,e,i+s,e+o),t.lineTo(i+s,e+n-o),t.quadraticCurveTo(i+s,e+n,i+s-o,e+n),t.lineTo(i+o,e+n),t.quadraticCurveTo(i,e+n,i,e+n-o),t.lineTo(i,e+o),t.quadraticCurveTo(i,e,i+o,e),t.closePath()};e.instances={},e.Type=function(t,i,s){this.options=i,this.chart=s,this.id=u(),e.instances[this.id]=this,i.responsive&&this.resize(),this.initialize.call(this,t)},a(e.Type.prototype,{initialize:function(){return this},clear:function(){return T(this.chart),this},stop:function(){return s.cancelAnimFrame.call(t,this.animationFrame),this},resize:function(t){this.stop();var i=this.chart.canvas,e=F(this.chart.canvas),s=this.options.maintainAspectRatio?e/this.chart.aspectRatio:R(this.chart.canvas);return i.width=this.chart.width=e,i.height=this.chart.height=s,A(this.chart),"function"==typeof t&&t.apply(this,Array.prototype.slice.call(arguments,1)),this},reflow:c,render:function(t){return t&&this.reflow(),this.options.animation&&!t?s.animationLoop(this.draw,this.options.animationSteps,this.options.animationEasing,this.options.onAnimationProgress,this.options.onAnimationComplete,this):(this.draw(),this.options.onAnimationComplete.call(this)),this},generateLegend:function(){return C(this.options.legendTemplate,this)},destroy:function(){this.clear(),k(this,this.events),delete e.instances[this.id]},showTooltip:function(t,i){"undefined"==typeof this.activeElements&&(this.activeElements=[]);var o=function(t){var i=!1;return t.length!==this.activeElements.length?i=!0:(n(t,function(t,e){t!==this.activeElements[e]&&(i=!0)},this),i)}.call(this,t);if(o||i){if(this.activeElements=t,this.draw(),t.length>0)if(this.datasets&&this.datasets.length>1){for(var a,h,r=this.datasets.length-1;r>=0&&(a=this.datasets[r].points||this.datasets[r].bars||this.datasets[r].segments,h=l(a,t[0]),-1===h);r--);var c=[],u=[],d=function(){var t,i,e,n,o,a=[],l=[],r=[];return s.each(this.datasets,function(i){t=i.points||i.bars||i.segments,t[h]&&t[h].hasValue()&&a.push(t[h])}),s.each(a,function(t){l.push(t.x),r.push(t.y),c.push(s.template(this.options.multiTooltipTemplate,t)),u.push({fill:t._saved.fillColor||t.fillColor,stroke:t._saved.strokeColor||t.strokeColor})},this),o=m(r),e=g(r),n=m(l),i=g(l),{x:n>this.chart.width/2?n:i,y:(o+e)/2}}.call(this,h);new e.MultiTooltip({x:d.x,y:d.y,xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,xOffset:this.options.tooltipXOffset,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,titleTextColor:this.options.tooltipTitleFontColor,titleFontFamily:this.options.tooltipTitleFontFamily,titleFontStyle:this.options.tooltipTitleFontStyle,titleFontSize:this.options.tooltipTitleFontSize,cornerRadius:this.options.tooltipCornerRadius,labels:c,legendColors:u,legendColorBackground:this.options.multiTooltipKeyBackground,title:t[0].label,chart:this.chart,ctx:this.chart.ctx}).draw()}else n(t,function(t){var i=t.tooltipPosition();new e.Tooltip({x:Math.round(i.x),y:Math.round(i.y),xPadding:this.options.tooltipXPadding,yPadding:this.options.tooltipYPadding,fillColor:this.options.tooltipFillColor,textColor:this.options.tooltipFontColor,fontFamily:this.options.tooltipFontFamily,fontStyle:this.options.tooltipFontStyle,fontSize:this.options.tooltipFontSize,caretHeight:this.options.tooltipCaretSize,cornerRadius:this.options.tooltipCornerRadius,text:C(this.options.tooltipTemplate,t),chart:this.chart}).draw()},this);return this}},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)}}),e.Type.extend=function(t){var i=this,s=function(){return i.apply(this,arguments)};if(s.prototype=o(i.prototype),a(s.prototype,t),s.extend=e.Type.extend,t.name||i.prototype.name){var n=t.name||i.prototype.name,l=e.defaults[i.prototype.name]?o(e.defaults[i.prototype.name]):{};e.defaults[n]=a(l,t.defaults),e.types[n]=s,e.prototype[n]=function(t,i){var o=h(e.defaults.global,e.defaults[n],i||{});return new s(t,o,this)}}else d("Name not provided for this chart, so it hasn't been registered");return i},e.Element=function(t){a(this,t),this.initialize.apply(this,arguments),this.save()},a(e.Element.prototype,{initialize:function(){},restore:function(t){return t?n(t,function(t){this[t]=this._saved[t]},this):a(this,this._saved),this},save:function(){return this._saved=o(this),delete this._saved._saved,this},update:function(t){return n(t,function(t,i){this._saved[i]=this[i],this[i]=t},this),this},transition:function(t,i){return n(t,function(t,e){this[e]=(t-this._saved[e])*i+this._saved[e]},this),this},tooltipPosition:function(){return{x:this.x,y:this.y}},hasValue:function(){return f(this.value)}}),e.Element.extend=r,e.Point=e.Element.extend({display:!0,inRange:function(t,i){var e=this.hitDetectionRadius+this.radius;return Math.pow(t-this.x,2)+Math.pow(i-this.y,2)<Math.pow(e,2)},draw:function(){if(this.display){var t=this.ctx;t.beginPath(),t.arc(this.x,this.y,this.radius,0,2*Math.PI),t.closePath(),t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.fillStyle=this.fillColor,t.fill(),t.stroke()}}}),e.Arc=e.Element.extend({inRange:function(t,i){var e=s.getAngleFromPoint(this,{x:t,y:i}),n=e.angle>=this.startAngle&&e.angle<=this.endAngle,o=e.distance>=this.innerRadius&&e.distance<=this.outerRadius;return n&&o},tooltipPosition:function(){var t=this.startAngle+(this.endAngle-this.startAngle)/2,i=(this.outerRadius-this.innerRadius)/2+this.innerRadius;return{x:this.x+Math.cos(t)*i,y:this.y+Math.sin(t)*i}},draw:function(t){var i=this.ctx;i.beginPath(),i.arc(this.x,this.y,this.outerRadius,this.startAngle,this.endAngle),i.arc(this.x,this.y,this.innerRadius,this.endAngle,this.startAngle,!0),i.closePath(),i.strokeStyle=this.strokeColor,i.lineWidth=this.strokeWidth,i.fillStyle=this.fillColor,i.fill(),i.lineJoin="bevel",this.showStroke&&i.stroke()}}),e.Rectangle=e.Element.extend({draw:function(){var t=this.ctx,i=this.width/2,e=this.x-i,s=this.x+i,n=this.base-(this.base-this.y),o=this.strokeWidth/2;this.showStroke&&(e+=o,s-=o,n+=o),t.beginPath(),t.fillStyle=this.fillColor,t.strokeStyle=this.strokeColor,t.lineWidth=this.strokeWidth,t.moveTo(e,this.base),t.lineTo(e,n),t.lineTo(s,n),t.lineTo(s,this.base),t.fill(),this.showStroke&&t.stroke()},height:function(){return this.base-this.y},inRange:function(t,i){return t>=this.x-this.width/2&&t<=this.x+this.width/2&&i>=this.y&&i<=this.base}}),e.Tooltip=e.Element.extend({draw:function(){var t=this.chart.ctx;t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.xAlign="center",this.yAlign="above";var i=2,e=t.measureText(this.text).width+2*this.xPadding,s=this.fontSize+2*this.yPadding,n=s+this.caretHeight+i;this.x+e/2>this.chart.width?this.xAlign="left":this.x-e/2<0&&(this.xAlign="right"),this.y-n<0&&(this.yAlign="below");var o=this.x-e/2,a=this.y-n;switch(t.fillStyle=this.fillColor,this.yAlign){case"above":t.beginPath(),t.moveTo(this.x,this.y-i),t.lineTo(this.x+this.caretHeight,this.y-(i+this.caretHeight)),t.lineTo(this.x-this.caretHeight,this.y-(i+this.caretHeight)),t.closePath(),t.fill();break;case"below":a=this.y+i+this.caretHeight,t.beginPath(),t.moveTo(this.x,this.y+i),t.lineTo(this.x+this.caretHeight,this.y+i+this.caretHeight),t.lineTo(this.x-this.caretHeight,this.y+i+this.caretHeight),t.closePath(),t.fill()}switch(this.xAlign){case"left":o=this.x-e+(this.cornerRadius+this.caretHeight);break;case"right":o=this.x-(this.cornerRadius+this.caretHeight)}z(t,o,a,e,s,this.cornerRadius),t.fill(),t.fillStyle=this.textColor,t.textAlign="center",t.textBaseline="middle",t.fillText(this.text,o+e/2,a+s/2)}}),e.MultiTooltip=e.Element.extend({initialize:function(){this.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.titleFont=M(this.titleFontSize,this.titleFontStyle,this.titleFontFamily),this.height=this.labels.length*this.fontSize+(this.labels.length-1)*(this.fontSize/2)+2*this.yPadding+1.5*this.titleFontSize,this.ctx.font=this.titleFont;var t=this.ctx.measureText(this.title).width,i=W(this.ctx,this.font,this.labels)+this.fontSize+3,e=g([i,t]);this.width=e+2*this.xPadding;var s=this.height/2;this.y-s<0?this.y=s:this.y+s>this.chart.height&&(this.y=this.chart.height-s),this.x>this.chart.width/2?this.x-=this.xOffset+this.width:this.x+=this.xOffset},getLineHeight:function(t){var i=this.y-this.height/2+this.yPadding,e=t-1;return 0===t?i+this.titleFontSize/2:i+(1.5*this.fontSize*e+this.fontSize/2)+1.5*this.titleFontSize},draw:function(){z(this.ctx,this.x,this.y-this.height/2,this.width,this.height,this.cornerRadius);var t=this.ctx;t.fillStyle=this.fillColor,t.fill(),t.closePath(),t.textAlign="left",t.textBaseline="middle",t.fillStyle=this.titleTextColor,t.font=this.titleFont,t.fillText(this.title,this.x+this.xPadding,this.getLineHeight(0)),t.font=this.font,s.each(this.labels,function(i,e){t.fillStyle=this.textColor,t.fillText(i,this.x+this.xPadding+this.fontSize+3,this.getLineHeight(e+1)),t.fillStyle=this.legendColorBackground,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize),t.fillStyle=this.legendColors[e].fill,t.fillRect(this.x+this.xPadding,this.getLineHeight(e+1)-this.fontSize/2,this.fontSize,this.fontSize)},this)}}),e.Scale=e.Element.extend({initialize:function(){this.fit()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}));this.yLabelWidth=this.display&&this.showLabels?W(this.ctx,this.font,this.yLabels):0},addXLabel:function(t){this.xLabels.push(t),this.valuesCount++,this.fit()},removeXLabel:function(){this.xLabels.shift(),this.valuesCount--,this.fit()},fit:function(){this.startPoint=this.display?this.fontSize:0,this.endPoint=this.display?this.height-1.5*this.fontSize-5:this.height,this.startPoint+=this.padding,this.endPoint-=this.padding;var t,i=this.endPoint-this.startPoint;for(this.calculateYRange(i),this.buildYLabels(),this.calculateXLabelRotation();i>this.endPoint-this.startPoint;)i=this.endPoint-this.startPoint,t=this.yLabelWidth,this.calculateYRange(i),this.buildYLabels(),t<this.yLabelWidth&&this.calculateXLabelRotation()},calculateXLabelRotation:function(){this.ctx.font=this.font;var t,i,e=this.ctx.measureText(this.xLabels[0]).width,s=this.ctx.measureText(this.xLabels[this.xLabels.length-1]).width;if(this.xScalePaddingRight=s/2+3,this.xScalePaddingLeft=e/2>this.yLabelWidth+10?e/2:this.yLabelWidth+10,this.xLabelRotation=0,this.display){var n,o=W(this.ctx,this.font,this.xLabels);this.xLabelWidth=o;for(var a=Math.floor(this.calculateX(1)-this.calculateX(0))-6;this.xLabelWidth>a&&0===this.xLabelRotation||this.xLabelWidth>a&&this.xLabelRotation<=90&&this.xLabelRotation>0;)n=Math.cos(x(this.xLabelRotation)),t=n*e,i=n*s,t+this.fontSize/2>this.yLabelWidth+8&&(this.xScalePaddingLeft=t+this.fontSize/2),this.xScalePaddingRight=this.fontSize/2,this.xLabelRotation++,this.xLabelWidth=n*o;this.xLabelRotation>0&&(this.endPoint-=Math.sin(x(this.xLabelRotation))*o+3)}else this.xLabelWidth=0,this.xScalePaddingRight=this.padding,this.xScalePaddingLeft=this.padding},calculateYRange:c,drawingArea:function(){return this.startPoint-this.endPoint},calculateY:function(t){var i=this.drawingArea()/(this.min-this.max);return this.endPoint-i*(t-this.min)},calculateX:function(t){var i=(this.xLabelRotation>0,this.width-(this.xScalePaddingLeft+this.xScalePaddingRight)),e=i/(this.valuesCount-(this.offsetGridLines?0:1)),s=e*t+this.xScalePaddingLeft;return this.offsetGridLines&&(s+=e/2),Math.round(s)},update:function(t){s.extend(this,t),this.fit()},draw:function(){var t=this.ctx,i=(this.endPoint-this.startPoint)/this.steps,e=Math.round(this.xScalePaddingLeft);this.display&&(t.fillStyle=this.textColor,t.font=this.font,n(this.yLabels,function(n,o){var a=this.endPoint-i*o,h=Math.round(a);t.textAlign="right",t.textBaseline="middle",this.showLabels&&t.fillText(n,e-10,a),t.beginPath(),o>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),h+=s.aliasPixel(t.lineWidth),t.moveTo(e,h),t.lineTo(this.width,h),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(e-5,h),t.lineTo(e,h),t.stroke(),t.closePath()},this),n(this.xLabels,function(i,e){var s=this.calculateX(e)+S(this.lineWidth),n=this.calculateX(e-(this.offsetGridLines?.5:0))+S(this.lineWidth),o=this.xLabelRotation>0;t.beginPath(),e>0?(t.lineWidth=this.gridLineWidth,t.strokeStyle=this.gridLineColor):(t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor),t.moveTo(n,this.endPoint),t.lineTo(n,this.startPoint-3),t.stroke(),t.closePath(),t.lineWidth=this.lineWidth,t.strokeStyle=this.lineColor,t.beginPath(),t.moveTo(n,this.endPoint),t.lineTo(n,this.endPoint+5),t.stroke(),t.closePath(),t.save(),t.translate(s,o?this.endPoint+12:this.endPoint+8),t.rotate(-1*x(this.xLabelRotation)),t.font=this.font,t.textAlign=o?"right":"center",t.textBaseline=o?"middle":"top",t.fillText(i,0,0),t.restore()},this))}}),e.RadialScale=e.Element.extend({initialize:function(){this.size=m([this.height,this.width]),this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2},calculateCenterOffset:function(t){var i=this.drawingArea/(this.max-this.min);return(t-this.min)*i},update:function(){this.lineArc?this.drawingArea=this.display?this.size/2-(this.fontSize/2+this.backdropPaddingY):this.size/2:this.setScaleSize(),this.buildYLabels()},buildYLabels:function(){this.yLabels=[];for(var t=v(this.stepValue),i=0;i<=this.steps;i++)this.yLabels.push(C(this.templateString,{value:(this.min+i*this.stepValue).toFixed(t)}))},getCircumference:function(){return 2*Math.PI/this.valuesCount},setScaleSize:function(){var t,i,e,s,n,o,a,h,l,r,c,u,d=m([this.height/2-this.pointLabelFontSize-5,this.width/2]),p=this.width,g=0;for(this.ctx.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),i=0;i<this.valuesCount;i++)t=this.getPointPosition(i,d),e=this.ctx.measureText(C(this.templateString,{value:this.labels[i]})).width+5,0===i||i===this.valuesCount/2?(s=e/2,t.x+s>p&&(p=t.x+s,n=i),t.x-s<g&&(g=t.x-s,a=i)):i<this.valuesCount/2?t.x+e>p&&(p=t.x+e,n=i):i>this.valuesCount/2&&t.x-e<g&&(g=t.x-e,a=i);l=g,r=Math.ceil(p-this.width),o=this.getIndexAngle(n),h=this.getIndexAngle(a),c=r/Math.sin(o+Math.PI/2),u=l/Math.sin(h+Math.PI/2),c=f(c)?c:0,u=f(u)?u:0,this.drawingArea=d-(u+c)/2,this.setCenterPoint(u,c)},setCenterPoint:function(t,i){var e=this.width-i-this.drawingArea,s=t+this.drawingArea;this.xCenter=(s+e)/2,this.yCenter=this.height/2},getIndexAngle:function(t){var i=2*Math.PI/this.valuesCount;return t*i-Math.PI/2},getPointPosition:function(t,i){var e=this.getIndexAngle(t);return{x:Math.cos(e)*i+this.xCenter,y:Math.sin(e)*i+this.yCenter}},draw:function(){if(this.display){var t=this.ctx;if(n(this.yLabels,function(i,e){if(e>0){var s,n=e*(this.drawingArea/this.steps),o=this.yCenter-n;if(this.lineWidth>0)if(t.strokeStyle=this.lineColor,t.lineWidth=this.lineWidth,this.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var a=0;a<this.valuesCount;a++)s=this.getPointPosition(a,this.calculateCenterOffset(this.min+e*this.stepValue)),0===a?t.moveTo(s.x,s.y):t.lineTo(s.x,s.y);t.closePath(),t.stroke()}if(this.showLabels){if(t.font=M(this.fontSize,this.fontStyle,this.fontFamily),this.showLabelBackdrop){var h=t.measureText(i).width;t.fillStyle=this.backdropColor,t.fillRect(this.xCenter-h/2-this.backdropPaddingX,o-this.fontSize/2-this.backdropPaddingY,h+2*this.backdropPaddingX,this.fontSize+2*this.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=this.fontColor,t.fillText(i,this.xCenter,o)}}},this),!this.lineArc){t.lineWidth=this.angleLineWidth,t.strokeStyle=this.angleLineColor;for(var i=this.valuesCount-1;i>=0;i--){if(this.angleLineWidth>0){var e=this.getPointPosition(i,this.calculateCenterOffset(this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(e.x,e.y),t.stroke(),t.closePath()}var s=this.getPointPosition(i,this.calculateCenterOffset(this.max)+5);t.font=M(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily),t.fillStyle=this.pointLabelFontColor;var o=this.labels.length,a=this.labels.length/2,h=a/2,l=h>i||i>o-h,r=i===h||i===o-h;t.textAlign=0===i?"center":i===a?"center":a>i?"left":"right",t.textBaseline=r?"middle":l?"bottom":"top",t.fillText(this.labels[i],s.x,s.y)}}}}}),s.addEvent(window,"resize",function(){var t;return function(){clearTimeout(t),t=setTimeout(function(){n(e.instances,function(t){t.options.responsive&&t.resize(t.render,!0)})},50)}}()),p?define(function(){return e}):"object"==typeof module&&module.exports&&(module.exports=e),t.Chart=e,e.noConflict=function(){return t.Chart=i,e}}).call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleBeginAtZero:!0,scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,barShowStroke:!0,barStrokeWidth:2,barValueSpacing:5,barDatasetSpacing:1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].fillColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Bar",defaults:s,initialize:function(t){var s=this.options;this.ScaleClass=i.Scale.extend({offsetGridLines:!0,calculateBarX:function(t,i,e){var n=this.calculateBaseWidth(),o=this.calculateX(e)-n/2,a=this.calculateBarWidth(t);return o+a*i+i*s.barDatasetSpacing+a/2},calculateBaseWidth:function(){return this.calculateX(1)-this.calculateX(0)-2*s.barValueSpacing},calculateBarWidth:function(t){var i=this.calculateBaseWidth()-(t-1)*s.barDatasetSpacing;return i/t}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getBarsAtEvent(t):[];this.eachBars(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),this.BarClass=i.Rectangle.extend({strokeWidth:this.options.barStrokeWidth,showStroke:this.options.barShowStroke,ctx:this.chart.ctx}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,bars:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.bars.push(new this.BarClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.strokeColor,fillColor:i.fillColor,highlightFill:i.highlightFill||i.fillColor,highlightStroke:i.highlightStroke||i.strokeColor}))},this)},this),this.buildScale(t.labels),this.BarClass.prototype.base=this.scale.endPoint,this.eachBars(function(t,i,s){e.extend(t,{width:this.scale.calculateBarWidth(this.datasets.length),x:this.scale.calculateBarX(this.datasets.length,s,i),y:this.scale.endPoint}),t.save()},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachBars(function(t){t.save()}),this.render()},eachBars:function(t){e.each(this.datasets,function(i,s){e.each(i.bars,t,this,s)},this)},getBarsAtEvent:function(t){for(var i,s=[],n=e.getRelativePosition(t),o=function(t){s.push(t.bars[i])},a=0;a<this.datasets.length;a++)for(i=0;i<this.datasets[a].bars.length;i++)if(this.datasets[a].bars[i].inRange(n.x,n.y))return e.each(this.datasets,o),s;return s},buildScale:function(t){var i=this,s=function(){var t=[];return i.eachBars(function(i){t.push(i.value)}),t},n={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(s(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.barShowStroke?this.options.barStrokeWidth:0,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(n,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new this.ScaleClass(n)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].bars.push(new this.BarClass({value:t,label:i,x:this.scale.calculateBarX(this.datasets.length,e,this.scale.valuesCount+1),y:this.scale.endPoint,width:this.scale.calculateBarWidth(this.datasets.length),base:this.scale.endPoint,strokeColor:this.datasets[e].strokeColor,fillColor:this.datasets[e].fillColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.bars.shift()},this),this.update()},reflow:function(){e.extend(this.BarClass.prototype,{y:this.scale.endPoint,base:this.scale.endPoint});var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();this.chart.ctx;this.scale.draw(i),e.each(this.datasets,function(t,s){e.each(t.bars,function(t,e){t.hasValue()&&(t.base=this.scale.endPoint,t.transition({x:this.scale.calculateBarX(this.datasets.length,s,e),y:this.scale.calculateY(t.value),width:this.scale.calculateBarWidth(this.datasets.length)},i).draw())},this)},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,percentageInnerCutout:50,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};
i.Type.extend({name:"Doughnut",defaults:s,initialize:function(t){this.segments=[],this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,this.SegmentArc=i.Arc.extend({ctx:this.chart.ctx,x:this.chart.width/2,y:this.chart.height/2}),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.calculateTotal(t),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({value:t.value,outerRadius:this.options.animateScale?0:this.outerRadius,innerRadius:this.options.animateScale?0:this.outerRadius/100*this.options.percentageInnerCutout,fillColor:t.color,highlightColor:t.highlight||t.color,showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,startAngle:1.5*Math.PI,circumference:this.options.animateRotate?0:this.calculateCircumference(t.value),label:t.label})),e||(this.reflow(),this.update())},calculateCircumference:function(t){return 2*Math.PI*(t/this.total)},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this)},update:function(){this.calculateTotal(this.segments),e.each(this.activeElements,function(t){t.restore(["fillColor"])}),e.each(this.segments,function(t){t.save()}),this.render()},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.outerRadius=(e.min([this.chart.width,this.chart.height])-this.options.segmentStrokeWidth/2)/2,e.each(this.segments,function(t){t.update({outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout})},this)},draw:function(t){var i=t?t:1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.calculateCircumference(t.value),outerRadius:this.outerRadius,innerRadius:this.outerRadius/100*this.options.percentageInnerCutout},i),t.endAngle=t.startAngle+t.circumference,t.draw(),0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle)},this)}}),i.types.Doughnut.extend({name:"Pie",defaults:e.merge(s,{percentageInnerCutout:0})})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowGridLines:!0,scaleGridLineColor:"rgba(0,0,0,.05)",scaleGridLineWidth:1,bezierCurve:!0,bezierCurveTension:.4,pointDot:!0,pointDotRadius:4,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"Line",defaults:s,initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx,inRange:function(t){return Math.pow(t-this.x,2)<Math.pow(this.radius+this.hitDetectionRadius,2)}}),this.datasets=[],this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this),this.buildScale(t.labels),this.eachPoints(function(t,i){e.extend(t,{x:this.scale.calculateX(i),y:this.scale.endPoint}),t.save()},this)},this),this.render()},update:function(){this.scale.update(),e.each(this.activeElements,function(t){t.restore(["fillColor","strokeColor"])}),this.eachPoints(function(t){t.save()}),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.datasets,function(t){e.each(t.points,function(t){t.inRange(s.x,s.y)&&i.push(t)})},this),i},buildScale:function(t){var s=this,n=function(){var t=[];return s.eachPoints(function(i){t.push(i.value)}),t},o={templateString:this.options.scaleLabel,height:this.chart.height,width:this.chart.width,ctx:this.chart.ctx,textColor:this.options.scaleFontColor,fontSize:this.options.scaleFontSize,fontStyle:this.options.scaleFontStyle,fontFamily:this.options.scaleFontFamily,valuesCount:t.length,beginAtZero:this.options.scaleBeginAtZero,integersOnly:this.options.scaleIntegersOnly,calculateYRange:function(t){var i=e.calculateScaleRange(n(),t,this.fontSize,this.beginAtZero,this.integersOnly);e.extend(this,i)},xLabels:t,font:e.fontString(this.options.scaleFontSize,this.options.scaleFontStyle,this.options.scaleFontFamily),lineWidth:this.options.scaleLineWidth,lineColor:this.options.scaleLineColor,gridLineWidth:this.options.scaleShowGridLines?this.options.scaleGridLineWidth:0,gridLineColor:this.options.scaleShowGridLines?this.options.scaleGridLineColor:"rgba(0,0,0,0)",padding:this.options.showScale?0:this.options.pointDotRadius+this.options.pointDotStrokeWidth,showLabels:this.options.scaleShowLabels,display:this.options.showScale};this.options.scaleOverride&&e.extend(o,{calculateYRange:e.noop,steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}),this.scale=new i.Scale(o)},addData:function(t,i){e.each(t,function(t,e){this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:this.scale.calculateX(this.scale.valuesCount+1),y:this.scale.endPoint,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.addXLabel(i),this.update()},removeData:function(){this.scale.removeXLabel(),e.each(this.datasets,function(t){t.points.shift()},this),this.update()},reflow:function(){var t=e.extend({height:this.chart.height,width:this.chart.width});this.scale.update(t)},draw:function(t){var i=t||1;this.clear();var s=this.chart.ctx,n=function(t){return null!==t.value},o=function(t,i,s){return e.findNextWhere(i,n,s)||t},a=function(t,i,s){return e.findPreviousWhere(i,n,s)||t};this.scale.draw(i),e.each(this.datasets,function(t){var h=e.where(t.points,n);e.each(t.points,function(t,e){t.hasValue()&&t.transition({y:this.scale.calculateY(t.value),x:this.scale.calculateX(e)},i)},this),this.options.bezierCurve&&e.each(h,function(t,i){var s=i>0&&i<h.length-1?this.options.bezierCurveTension:0;t.controlPoints=e.splineCurve(a(t,h,i),t,o(t,h,i),s),t.controlPoints.outer.y>this.scale.endPoint?t.controlPoints.outer.y=this.scale.endPoint:t.controlPoints.outer.y<this.scale.startPoint&&(t.controlPoints.outer.y=this.scale.startPoint),t.controlPoints.inner.y>this.scale.endPoint?t.controlPoints.inner.y=this.scale.endPoint:t.controlPoints.inner.y<this.scale.startPoint&&(t.controlPoints.inner.y=this.scale.startPoint)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(h,function(t,i){if(0===i)s.moveTo(t.x,t.y);else if(this.options.bezierCurve){var e=a(t,h,i);s.bezierCurveTo(e.controlPoints.outer.x,e.controlPoints.outer.y,t.controlPoints.inner.x,t.controlPoints.inner.y,t.x,t.y)}else s.lineTo(t.x,t.y)},this),s.stroke(),this.options.datasetFill&&h.length>0&&(s.lineTo(h[h.length-1].x,this.scale.endPoint),s.lineTo(h[0].x,this.scale.endPoint),s.fillStyle=t.fillColor,s.closePath(),s.fill()),e.each(h,function(t){t.draw()})},this)}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers,s={scaleShowLabelBackdrop:!0,scaleBackdropColor:"rgba(255,255,255,0.75)",scaleBeginAtZero:!0,scaleBackdropPaddingY:2,scaleBackdropPaddingX:2,scaleShowLine:!0,segmentShowStroke:!0,segmentStrokeColor:"#fff",segmentStrokeWidth:2,animationSteps:100,animationEasing:"easeOutBounce",animateRotate:!0,animateScale:!1,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<segments.length; i++){%><li><span style="background-color:<%=segments[i].fillColor%>"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>'};i.Type.extend({name:"PolarArea",defaults:s,initialize:function(t){this.segments=[],this.SegmentArc=i.Arc.extend({showStroke:this.options.segmentShowStroke,strokeWidth:this.options.segmentStrokeWidth,strokeColor:this.options.segmentStrokeColor,ctx:this.chart.ctx,innerRadius:0,x:this.chart.width/2,y:this.chart.height/2}),this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,lineArc:!0,width:this.chart.width,height:this.chart.height,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,valuesCount:t.length}),this.updateScaleRange(t),this.scale.update(),e.each(t,function(t,i){this.addData(t,i,!0)},this),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getSegmentsAtEvent(t):[];e.each(this.segments,function(t){t.restore(["fillColor"])}),e.each(i,function(t){t.fillColor=t.highlightColor}),this.showTooltip(i)}),this.render()},getSegmentsAtEvent:function(t){var i=[],s=e.getRelativePosition(t);return e.each(this.segments,function(t){t.inRange(s.x,s.y)&&i.push(t)},this),i},addData:function(t,i,e){var s=i||this.segments.length;this.segments.splice(s,0,new this.SegmentArc({fillColor:t.color,highlightColor:t.highlight||t.color,label:t.label,value:t.value,outerRadius:this.options.animateScale?0:this.scale.calculateCenterOffset(t.value),circumference:this.options.animateRotate?0:this.scale.getCircumference(),startAngle:1.5*Math.PI})),e||(this.reflow(),this.update())},removeData:function(t){var i=e.isNumber(t)?t:this.segments.length-1;this.segments.splice(i,1),this.reflow(),this.update()},calculateTotal:function(t){this.total=0,e.each(t,function(t){this.total+=t.value},this),this.scale.valuesCount=this.segments.length},updateScaleRange:function(t){var i=[];e.each(t,function(t){i.push(t.value)});var s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s,{size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2})},update:function(){this.calculateTotal(this.segments),e.each(this.segments,function(t){t.save()}),this.render()},reflow:function(){e.extend(this.SegmentArc.prototype,{x:this.chart.width/2,y:this.chart.height/2}),this.updateScaleRange(this.segments),this.scale.update(),e.extend(this.scale,{xCenter:this.chart.width/2,yCenter:this.chart.height/2}),e.each(this.segments,function(t){t.update({outerRadius:this.scale.calculateCenterOffset(t.value)})},this)},draw:function(t){var i=t||1;this.clear(),e.each(this.segments,function(t,e){t.transition({circumference:this.scale.getCircumference(),outerRadius:this.scale.calculateCenterOffset(t.value)},i),t.endAngle=t.startAngle+t.circumference,0===e&&(t.startAngle=1.5*Math.PI),e<this.segments.length-1&&(this.segments[e+1].startAngle=t.endAngle),t.draw()},this),this.scale.draw()}})}.call(this),function(){"use strict";var t=this,i=t.Chart,e=i.helpers;i.Type.extend({name:"Radar",defaults:{scaleShowLine:!0,angleShowLineOut:!0,scaleShowLabels:!1,scaleBeginAtZero:!0,angleLineColor:"rgba(0,0,0,.1)",angleLineWidth:1,pointLabelFontFamily:"'Arial'",pointLabelFontStyle:"normal",pointLabelFontSize:10,pointLabelFontColor:"#666",pointDot:!0,pointDotRadius:3,pointDotStrokeWidth:1,pointHitDetectionRadius:20,datasetStroke:!0,datasetStrokeWidth:2,datasetFill:!0,legendTemplate:'<ul class="<%=name.toLowerCase()%>-legend"><% for (var i=0; i<datasets.length; i++){%><li><span style="background-color:<%=datasets[i].strokeColor%>"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>'},initialize:function(t){this.PointClass=i.Point.extend({strokeWidth:this.options.pointDotStrokeWidth,radius:this.options.pointDotRadius,display:this.options.pointDot,hitDetectionRadius:this.options.pointHitDetectionRadius,ctx:this.chart.ctx}),this.datasets=[],this.buildScale(t),this.options.showTooltips&&e.bindEvents(this,this.options.tooltipEvents,function(t){var i="mouseout"!==t.type?this.getPointsAtEvent(t):[];this.eachPoints(function(t){t.restore(["fillColor","strokeColor"])}),e.each(i,function(t){t.fillColor=t.highlightFill,t.strokeColor=t.highlightStroke}),this.showTooltip(i)}),e.each(t.datasets,function(i){var s={label:i.label||null,fillColor:i.fillColor,strokeColor:i.strokeColor,pointColor:i.pointColor,pointStrokeColor:i.pointStrokeColor,points:[]};this.datasets.push(s),e.each(i.data,function(e,n){var o;this.scale.animation||(o=this.scale.getPointPosition(n,this.scale.calculateCenterOffset(e))),s.points.push(new this.PointClass({value:e,label:t.labels[n],datasetLabel:i.label,x:this.options.animation?this.scale.xCenter:o.x,y:this.options.animation?this.scale.yCenter:o.y,strokeColor:i.pointStrokeColor,fillColor:i.pointColor,highlightFill:i.pointHighlightFill||i.pointColor,highlightStroke:i.pointHighlightStroke||i.pointStrokeColor}))},this)},this),this.render()},eachPoints:function(t){e.each(this.datasets,function(i){e.each(i.points,t,this)},this)},getPointsAtEvent:function(t){var i=e.getRelativePosition(t),s=e.getAngleFromPoint({x:this.scale.xCenter,y:this.scale.yCenter},i),n=2*Math.PI/this.scale.valuesCount,o=Math.round((s.angle-1.5*Math.PI)/n),a=[];return(o>=this.scale.valuesCount||0>o)&&(o=0),s.distance<=this.scale.drawingArea&&e.each(this.datasets,function(t){a.push(t.points[o])}),a},buildScale:function(t){this.scale=new i.RadialScale({display:this.options.showScale,fontStyle:this.options.scaleFontStyle,fontSize:this.options.scaleFontSize,fontFamily:this.options.scaleFontFamily,fontColor:this.options.scaleFontColor,showLabels:this.options.scaleShowLabels,showLabelBackdrop:this.options.scaleShowLabelBackdrop,backdropColor:this.options.scaleBackdropColor,backdropPaddingY:this.options.scaleBackdropPaddingY,backdropPaddingX:this.options.scaleBackdropPaddingX,lineWidth:this.options.scaleShowLine?this.options.scaleLineWidth:0,lineColor:this.options.scaleLineColor,angleLineColor:this.options.angleLineColor,angleLineWidth:this.options.angleShowLineOut?this.options.angleLineWidth:0,pointLabelFontColor:this.options.pointLabelFontColor,pointLabelFontSize:this.options.pointLabelFontSize,pointLabelFontFamily:this.options.pointLabelFontFamily,pointLabelFontStyle:this.options.pointLabelFontStyle,height:this.chart.height,width:this.chart.width,xCenter:this.chart.width/2,yCenter:this.chart.height/2,ctx:this.chart.ctx,templateString:this.options.scaleLabel,labels:t.labels,valuesCount:t.datasets[0].data.length}),this.scale.setScaleSize(),this.updateScaleRange(t.datasets),this.scale.buildYLabels()},updateScaleRange:function(t){var i=function(){var i=[];return e.each(t,function(t){t.data?i=i.concat(t.data):e.each(t.points,function(t){i.push(t.value)})}),i}(),s=this.options.scaleOverride?{steps:this.options.scaleSteps,stepValue:this.options.scaleStepWidth,min:this.options.scaleStartValue,max:this.options.scaleStartValue+this.options.scaleSteps*this.options.scaleStepWidth}:e.calculateScaleRange(i,e.min([this.chart.width,this.chart.height])/2,this.options.scaleFontSize,this.options.scaleBeginAtZero,this.options.scaleIntegersOnly);e.extend(this.scale,s)},addData:function(t,i){this.scale.valuesCount++,e.each(t,function(t,e){var s=this.scale.getPointPosition(this.scale.valuesCount,this.scale.calculateCenterOffset(t));this.datasets[e].points.push(new this.PointClass({value:t,label:i,x:s.x,y:s.y,strokeColor:this.datasets[e].pointStrokeColor,fillColor:this.datasets[e].pointColor}))},this),this.scale.labels.push(i),this.reflow(),this.update()},removeData:function(){this.scale.valuesCount--,this.scale.labels.shift(),e.each(this.datasets,function(t){t.points.shift()},this),this.reflow(),this.update()},update:function(){this.eachPoints(function(t){t.save()}),this.reflow(),this.render()},reflow:function(){e.extend(this.scale,{width:this.chart.width,height:this.chart.height,size:e.min([this.chart.width,this.chart.height]),xCenter:this.chart.width/2,yCenter:this.chart.height/2}),this.updateScaleRange(this.datasets),this.scale.setScaleSize(),this.scale.buildYLabels()},draw:function(t){var i=t||1,s=this.chart.ctx;this.clear(),this.scale.draw(),e.each(this.datasets,function(t){e.each(t.points,function(t,e){t.hasValue()&&t.transition(this.scale.getPointPosition(e,this.scale.calculateCenterOffset(t.value)),i)},this),s.lineWidth=this.options.datasetStrokeWidth,s.strokeStyle=t.strokeColor,s.beginPath(),e.each(t.points,function(t,i){0===i?s.moveTo(t.x,t.y):s.lineTo(t.x,t.y)},this),s.closePath(),s.stroke(),s.fillStyle=t.fillColor,s.fill(),e.each(t.points,function(t){t.hasValue()&&t.draw()})},this)}})}.call(this);
title anchor
Getting started
getting-started

###Include Chart.js

First we need to include the Chart.js library on the page. The library occupies a global variable of Chart.

<script src="Chart.js"></script>

Alternatively, if you're using an AMD loader for JavaScript modules, that is also supported in the Chart.js core. Please note: the library will still occupy a global variable of Chart, even if it detects define and define.amd. If this is a problem, you can call noConflict to restore the global Chart variable to it's previous owner.

// Using requirejs
require(['path/to/Chartjs'], function(Chart){
	// Use Chart.js as normal here.

	// Chart.noConflict restores the Chart global variable to it's previous owner
	// The function returns what was previously Chart, allowing you to reassign.
	var Chartjs = Chart.noConflict();

});

You can also grab Chart.js using bower:

bower install chartjs --save

###Creating a chart

To create a chart, we need to instantiate the Chart class. To do this, we need to pass in the 2d context of where we want to draw the chart. Here's an example.

<canvas id="myChart" width="400" height="400"></canvas>
// Get the context of the canvas element we want to select
var ctx = document.getElementById("myChart").getContext("2d");
var myNewChart = new Chart(ctx).PolarArea(data);

We can also get the context of our canvas with jQuery. To do this, we need to get the DOM node out of the jQuery collection, and call the getContext("2d") method on that.

// Get context with jQuery - using jQuery's .get() method.
var ctx = $("#myChart").get(0).getContext("2d");
// This will get the first returned node in the jQuery collection.
var myNewChart = new Chart(ctx);

After we've instantiated the Chart class on the canvas we want to draw on, Chart.js will handle the scaling for retina displays.

With the Chart class set up, we can go on to create one of the charts Chart.js has available. In the example below, we would be drawing a Polar area chart.

new Chart(ctx).PolarArea(data, options);

We call a method of the name of the chart we want to create. We pass in the data for that chart type, and the options for that chart as parameters. Chart.js will merge the global defaults with chart type specific defaults, then merge any options passed in as a second argument after data.

###Global chart configuration

This concept was introduced in Chart.js 1.0 to keep configuration DRY, and allow for changing options globally across chart types, avoiding the need to specify options for each instance, or the default for a particular chart type.

Chart.defaults.global = {
	// Boolean - Whether to animate the chart
	animation: true,

	// Number - Number of animation steps
	animationSteps: 60,

	// String - Animation easing effect
	animationEasing: "easeOutQuart",

	// Boolean - If we should show the scale at all
	showScale: true,

	// Boolean - If we want to override with a hard coded scale
	scaleOverride: false,

	// ** Required if scaleOverride is true **
	// Number - The number of steps in a hard coded scale
	scaleSteps: null,
	// Number - The value jump in the hard coded scale
	scaleStepWidth: null,
	// Number - The scale starting value
	scaleStartValue: null,

	// String - Colour of the scale line
	scaleLineColor: "rgba(0,0,0,.1)",

	// Number - Pixel width of the scale line
	scaleLineWidth: 1,

	// Boolean - Whether to show labels on the scale
	scaleShowLabels: true,

	// Interpolated JS string - can access value
	scaleLabel: "<%=value%>",

	// Boolean - Whether the scale should stick to integers, not floats even if drawing space is there
	scaleIntegersOnly: true,

	// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
	scaleBeginAtZero: false,

	// String - Scale label font declaration for the scale label
	scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",

	// Number - Scale label font size in pixels
	scaleFontSize: 12,

	// String - Scale label font weight style
	scaleFontStyle: "normal",

	// String - Scale label font colour
	scaleFontColor: "#666",

	// Boolean - whether or not the chart should be responsive and resize when the browser does.
	responsive: false,

	// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
	maintainAspectRatio: true,

	// Boolean - Determines whether to draw tooltips on the canvas or not
	showTooltips: true,

	// Array - Array of string names to attach tooltip events
	tooltipEvents: ["mousemove", "touchstart", "touchmove"],

	// String - Tooltip background colour
	tooltipFillColor: "rgba(0,0,0,0.8)",

	// String - Tooltip label font declaration for the scale label
	tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",

	// Number - Tooltip label font size in pixels
	tooltipFontSize: 14,

	// String - Tooltip font weight style
	tooltipFontStyle: "normal",

	// String - Tooltip label font colour
	tooltipFontColor: "#fff",

	// String - Tooltip title font declaration for the scale label
	tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",

	// Number - Tooltip title font size in pixels
	tooltipTitleFontSize: 14,

	// String - Tooltip title font weight style
	tooltipTitleFontStyle: "bold",

	// String - Tooltip title font colour
	tooltipTitleFontColor: "#fff",

	// Number - pixel width of padding around tooltip text
	tooltipYPadding: 6,

	// Number - pixel width of padding around tooltip text
	tooltipXPadding: 6,

	// Number - Size of the caret on the tooltip
	tooltipCaretSize: 8,

	// Number - Pixel radius of the tooltip border
	tooltipCornerRadius: 6,

	// Number - Pixel offset from point x to tooltip edge
	tooltipXOffset: 10,
	{% raw %}
	// String - Template string for single tooltips
	tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
	{% endraw %}
	// String - Template string for single tooltips
	multiTooltipTemplate: "<%= value %>",

	// Function - Will fire on animation progression.
	onAnimationProgress: function(){},

	// Function - Will fire on animation completion.
	onAnimationComplete: function(){}
}

If for example, you wanted all charts created to be responsive, and resize when the browser window does, the following setting can be changed:

Chart.defaults.global.responsive = true;

Now, every time we create a chart, options.responsive will be true.

title anchor
Line Chart
line-chart

###Introduction A line chart is a way of plotting data points on a line.

Often, it is used to show trend data, and the comparison of two data sets.

###Example usage

var myLineChart = new Chart(ctx).Line(data, options);

###Data structure

var data = {
	labels: ["January", "February", "March", "April", "May", "June", "July"],
	datasets: [
		{
			label: "My First dataset",
			fillColor: "rgba(220,220,220,0.2)",
			strokeColor: "rgba(220,220,220,1)",
			pointColor: "rgba(220,220,220,1)",
			pointStrokeColor: "#fff",
			pointHighlightFill: "#fff",
			pointHighlightStroke: "rgba(220,220,220,1)",
			data: [65, 59, 80, 81, 56, 55, 40]
		},
		{
			label: "My Second dataset",
			fillColor: "rgba(151,187,205,0.2)",
			strokeColor: "rgba(151,187,205,1)",
			pointColor: "rgba(151,187,205,1)",
			pointStrokeColor: "#fff",
			pointHighlightFill: "#fff",
			pointHighlightStroke: "rgba(151,187,205,1)",
			data: [28, 48, 40, 19, 86, 27, 90]
		}
	]
};

The line chart requires an array of labels for each of the data points. This is shown on the X axis. The data for line charts is broken up into an array of datasets. Each dataset has a colour for the fill, a colour for the line and colours for the points and strokes of the points. These colours are strings just like CSS. You can use RGBA, RGB, HEX or HSL notation.

The label key on each dataset is optional, and can be used when generating a scale for the chart.

Chart options

These are the customisation options specific to Line charts. These options are merged with the global chart configuration options, and form the options of the chart.

{

	///Boolean - Whether grid lines are shown across the chart
	scaleShowGridLines : true,

	//String - Colour of the grid lines
	scaleGridLineColor : "rgba(0,0,0,.05)",

	//Number - Width of the grid lines
	scaleGridLineWidth : 1,

	//Boolean - Whether the line is curved between points
	bezierCurve : true,

	//Number - Tension of the bezier curve between points
	bezierCurveTension : 0.4,

	//Boolean - Whether to show a dot for each point
	pointDot : true,

	//Number - Radius of each point dot in pixels
	pointDotRadius : 4,

	//Number - Pixel width of point dot stroke
	pointDotStrokeWidth : 1,

	//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
	pointHitDetectionRadius : 20,

	//Boolean - Whether to show a stroke for datasets
	datasetStroke : true,

	//Number - Pixel width of dataset stroke
	datasetStrokeWidth : 2,

	//Boolean - Whether to fill the dataset with a colour
	datasetFill : true,
	{% raw %}
	//String - A legend template
	legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
	{% endraw %}
};

You can override these for your Chart instance by passing a second argument into the Line method as an object with the keys you want to override.

For example, we could have a line chart without bezier curves between points by doing the following:

new Chart(ctx).Line(data, {
	bezierCurve: false
});
// This will create a chart with all of the default options, merged from the global config,
// and the Line chart defaults, but this particular instance will have `bezierCurve` set to false.

We can also change these defaults values for each Line type that is created, this object is available at Chart.defaults.Line.

Prototype methods

.getPointsAtEvent( event )

Calling getPointsAtEvent(event) on your Chart instance passing an argument of an event, or jQuery event, will return the point elements that are at that the same position of that event.

canvas.onclick = function(evt){
	var activePoints = myLineChart.getPointsAtEvent(evt);
	// => activePoints is an array of points on the canvas that are at the same position as the click event.
};

This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.

.update( )

Calling update() on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.

myLineChart.datasets[0].points[2].value = 50;
// Would update the first dataset's value of 'March' to be 50
myLineChart.update();
// Calling update now animates the position of March from 90 to 50.

.addData( valuesArray, label )

Calling addData(valuesArray, label) on your Chart instance passing an array of values for each dataset, along with a label for those points.

// The values array passed into addData should be one for each dataset in the chart
myLineChart.addData([40, 60], "August");
// This new data will now animate at the end of the chart.

.removeData( )

Calling removeData() on your Chart instance will remove the first value for all datasets on the chart.

myLineChart.removeData();
// The chart will remove the first point and animate other points into place
title anchor
Bar Chart
bar-chart

Introduction

A bar chart is a way of showing data as bars.

It is sometimes used to show trend data, and the comparison of multiple data sets side by side.

Example usage

var myBarChart = new Chart(ctx).Bar(data, options);

Data structure

var data = {
	labels: ["January", "February", "March", "April", "May", "June", "July"],
	datasets: [
		{
			label: "My First dataset",
			fillColor: "rgba(220,220,220,0.5)",
			strokeColor: "rgba(220,220,220,0.8)",
			highlightFill: "rgba(220,220,220,0.75)",
			highlightStroke: "rgba(220,220,220,1)",
			data: [65, 59, 80, 81, 56, 55, 40]
		},
		{
			label: "My Second dataset",
			fillColor: "rgba(151,187,205,0.5)",
			strokeColor: "rgba(151,187,205,0.8)",
			highlightFill: "rgba(151,187,205,0.75)",
			highlightStroke: "rgba(151,187,205,1)",
			data: [28, 48, 40, 19, 86, 27, 90]
		}
	]
};

The bar chart has the a very similar data structure to the line chart, and has an array of datasets, each with colours and an array of data. Again, colours are in CSS format. We have an array of labels too for display. In the example, we are showing the same data as the previous line chart example.

The label key on each dataset is optional, and can be used when generating a scale for the chart.

Chart Options

These are the customisation options specific to Bar charts. These options are merged with the global chart configuration options, and form the options of the chart.

{
	//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
	scaleBeginAtZero : true,

	//Boolean - Whether grid lines are shown across the chart
	scaleShowGridLines : true,

	//String - Colour of the grid lines
	scaleGridLineColor : "rgba(0,0,0,.05)",

	//Number - Width of the grid lines
	scaleGridLineWidth : 1,

	//Boolean - If there is a stroke on each bar
	barShowStroke : true,

	//Number - Pixel width of the bar stroke
	barStrokeWidth : 2,

	//Number - Spacing between each of the X value sets
	barValueSpacing : 5,

	//Number - Spacing between data sets within X values
	barDatasetSpacing : 1,
	{% raw %}
	//String - A legend template
	legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
	{% endraw %}
}

You can override these for your Chart instance by passing a second argument into the Bar method as an object with the keys you want to override.

For example, we could have a bar chart without a stroke on each bar by doing the following:

new Chart(ctx).Bar(data, {
	barShowStroke: false
});
// This will create a chart with all of the default options, merged from the global config,
//  and the Bar chart defaults but this particular instance will have `barShowStroke` set to false.

We can also change these defaults values for each Bar type that is created, this object is available at Chart.defaults.Bar.

Prototype methods

.getBarsAtEvent( event )

Calling getBarsAtEvent(event) on your Chart instance passing an argument of an event, or jQuery event, will return the bar elements that are at that the same position of that event.

canvas.onclick = function(evt){
	var activeBars = myBarChart.getBarsAtEvent(evt);
	// => activeBars is an array of bars on the canvas that are at the same position as the click event.
};

This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.

.update( )

Calling update() on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.

myBarChart.datasets[0].bars[2].value = 50;
// Would update the first dataset's value of 'March' to be 50
myBarChart.update();
// Calling update now animates the position of March from 90 to 50.

.addData( valuesArray, label )

Calling addData(valuesArray, label) on your Chart instance passing an array of values for each dataset, along with a label for those bars.

// The values array passed into addData should be one for each dataset in the chart
myBarChart.addData([40, 60], "August");
// The new data will now animate at the end of the chart.

.removeData( )

Calling removeData() on your Chart instance will remove the first value for all datasets on the chart.

myBarChart.removeData();
// The chart will now animate and remove the first bar
title anchor
Radar Chart
radar-chart

###Introduction A radar chart is a way of showing multiple data points and the variation between them.

They are often useful for comparing the points of two or more different data sets.

###Example usage

var myRadarChart = new Chart(ctx).Radar(data, options);

###Data structure

var data = {
	labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
	datasets: [
		{
			label: "My First dataset",
			fillColor: "rgba(220,220,220,0.2)",
			strokeColor: "rgba(220,220,220,1)",
			pointColor: "rgba(220,220,220,1)",
			pointStrokeColor: "#fff",
			pointHighlightFill: "#fff",
			pointHighlightStroke: "rgba(220,220,220,1)",
			data: [65, 59, 90, 81, 56, 55, 40]
		},
		{
			label: "My Second dataset",
			fillColor: "rgba(151,187,205,0.2)",
			strokeColor: "rgba(151,187,205,1)",
			pointColor: "rgba(151,187,205,1)",
			pointStrokeColor: "#fff",
			pointHighlightFill: "#fff",
			pointHighlightStroke: "rgba(151,187,205,1)",
			data: [28, 48, 40, 19, 96, 27, 100]
		}
	]
};

For a radar chart, to provide context of what each point means, we include an array of strings that show around each point in the chart. For the radar chart data, we have an array of datasets. Each of these is an object, with a fill colour, a stroke colour, a colour for the fill of each point, and a colour for the stroke of each point. We also have an array of data values.

The label key on each dataset is optional, and can be used when generating a scale for the chart.

Chart options

These are the customisation options specific to Radar charts. These options are merged with the global chart configuration options, and form the options of the chart.

{
	//Boolean - Whether to show lines for each scale point
	scaleShowLine : true,

	//Boolean - Whether we show the angle lines out of the radar
	angleShowLineOut : true,

	//Boolean - Whether to show labels on the scale
	scaleShowLabels : false,

	// Boolean - Whether the scale should begin at zero
	scaleBeginAtZero : true,

	//String - Colour of the angle line
	angleLineColor : "rgba(0,0,0,.1)",

	//Number - Pixel width of the angle line
	angleLineWidth : 1,

	//String - Point label font declaration
	pointLabelFontFamily : "'Arial'",

	//String - Point label font weight
	pointLabelFontStyle : "normal",

	//Number - Point label font size in pixels
	pointLabelFontSize : 10,

	//String - Point label font colour
	pointLabelFontColor : "#666",

	//Boolean - Whether to show a dot for each point
	pointDot : true,

	//Number - Radius of each point dot in pixels
	pointDotRadius : 3,

	//Number - Pixel width of point dot stroke
	pointDotStrokeWidth : 1,

	//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
	pointHitDetectionRadius : 20,

	//Boolean - Whether to show a stroke for datasets
	datasetStroke : true,

	//Number - Pixel width of dataset stroke
	datasetStrokeWidth : 2,

	//Boolean - Whether to fill the dataset with a colour
	datasetFill : true,
	{% raw %}
	//String - A legend template
	legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].lineColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
	{% endraw %}
}

You can override these for your Chart instance by passing a second argument into the Radar method as an object with the keys you want to override.

For example, we could have a radar chart without a point for each on piece of data by doing the following:

new Chart(ctx).Radar(data, {
	pointDot: false
});
// This will create a chart with all of the default options, merged from the global config,
//  and the Bar chart defaults but this particular instance will have `pointDot` set to false.

We can also change these defaults values for each Radar type that is created, this object is available at Chart.defaults.Radar.

Prototype methods

.getPointsAtEvent( event )

Calling getPointsAtEvent(event) on your Chart instance passing an argument of an event, or jQuery event, will return the point elements that are at that the same position of that event.

canvas.onclick = function(evt){
	var activePoints = myRadarChart.getPointsAtEvent(evt);
	// => activePoints is an array of points on the canvas that are at the same position as the click event.
};

This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.

.update( )

Calling update() on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.

myRadarChart.datasets[0].points[2].value = 50;
// Would update the first dataset's value of 'Sleeping' to be 50
myRadarChart.update();
// Calling update now animates the position of Sleeping from 90 to 50.

.addData( valuesArray, label )

Calling addData(valuesArray, label) on your Chart instance passing an array of values for each dataset, along with a label for those points.

// The values array passed into addData should be one for each dataset in the chart
myRadarChart.addData([40, 60], "Dancing");
// The new data will now animate at the end of the chart.

.removeData( )

Calling removeData() on your Chart instance will remove the first value for all datasets on the chart.

myRadarChart.removeData();
// Other points will now animate to their correct positions.
title anchor
Polar Area Chart
polar-area-chart

Introduction

Polar area charts are similar to pie charts, but each segment has the same angle - the radius of the segment differs depending on the value.

This type of chart is often useful when we want to show a comparison data similar to a pie chart, but also show a scale of values for context.

Example usage

new Chart(ctx).PolarArea(data, options);

Data structure

var data = [
	{
		value: 300,
		color:"#F7464A",
		highlight: "#FF5A5E",
		label: "Red"
	},
	{
		value: 50,
		color: "#46BFBD",
		highlight: "#5AD3D1",
		label: "Green"
	},
	{
		value: 100,
		color: "#FDB45C",
		highlight: "#FFC870",
		label: "Yellow"
	},
	{
		value: 40,
		color: "#949FB1",
		highlight: "#A8B3C5",
		label: "Grey"
	},
	{
		value: 120,
		color: "#4D5360",
		highlight: "#616774",
		label: "Dark Grey"
	}

];

As you can see, for the chart data you pass in an array of objects, with a value and a colour. The value attribute should be a number, while the color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.

Chart options

These are the customisation options specific to Polar Area charts. These options are merged with the global chart configuration options, and form the options of the chart.

{
	//Boolean - Show a backdrop to the scale label
	scaleShowLabelBackdrop : true,

	//String - The colour of the label backdrop
	scaleBackdropColor : "rgba(255,255,255,0.75)",

	// Boolean - Whether the scale should begin at zero
	scaleBeginAtZero : true,

	//Number - The backdrop padding above & below the label in pixels
	scaleBackdropPaddingY : 2,

	//Number - The backdrop padding to the side of the label in pixels
	scaleBackdropPaddingX : 2,

	//Boolean - Show line for each value in the scale
	scaleShowLine : true,

	//Boolean - Stroke a line around each segment in the chart
	segmentShowStroke : true,

	//String - The colour of the stroke on each segement.
	segmentStrokeColor : "#fff",

	//Number - The width of the stroke value in pixels
	segmentStrokeWidth : 2,

	//Number - Amount of animation steps
	animationSteps : 100,

	//String - Animation easing effect.
	animationEasing : "easeOutBounce",

	//Boolean - Whether to animate the rotation of the chart
	animateRotate : true,

	//Boolean - Whether to animate scaling the chart from the centre
	animateScale : false,
	{% raw %}
	//String - A legend template
	legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
	{% endraw %}
}

You can override these for your Chart instance by passing a second argument into the PolarArea method as an object with the keys you want to override.

For example, we could have a polar area chart with a black stroke on each segment like so:

new Chart(ctx).PolarArea(data, {
	segmentStrokeColor: "#000000"
});
// This will create a chart with all of the default options, merged from the global config,
// and the PolarArea chart defaults but this particular instance will have `segmentStrokeColor` set to `"#000000"`.

We can also change these defaults values for each PolarArea type that is created, this object is available at Chart.defaults.PolarArea.

Prototype methods

.getSegmentsAtEvent( event )

Calling getSegmentsAtEvent(event) on your Chart instance passing an argument of an event, or jQuery event, will return the segment elements that are at that the same position of that event.

canvas.onclick = function(evt){
	var activePoints = myPolarAreaChart.getSegmentsAtEvent(evt);
	// => activePoints is an array of segments on the canvas that are at the same position as the click event.
};

This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.

.update( )

Calling update() on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.

myPolarAreaChart.segments[1].value = 10;
// Would update the first dataset's value of 'Green' to be 10
myPolarAreaChart.update();
// Calling update now animates the position of Green from 50 to 10.

.addData( segmentData, index )

Calling addData(segmentData, index) on your Chart instance passing an object in the same format as in the constructor. There is an option second argument of 'index', this determines at what index the new segment should be inserted into the chart.

// An object in the same format as the original data source
myPolarAreaChart.addData({
	value: 130,
	color: "#B48EAD",
	highlight: "#C69CBE",
	label: "Purple"
});
// The new segment will now animate in.

.removeData( index )

Calling removeData(index) on your Chart instance will remove segment at that particular index. If none is provided, it will default to the last segment.

myPolarAreaChart.removeData();
// Other segments will update to fill the empty space left.
title anchor
Pie & Doughnut Charts
doughnut-pie-chart

###Introduction Pie and doughnut charts are probably the most commonly used chart there are. They are divided into segments, the arc of each segment shows a the proportional value of each piece of data.

They are excellent at showing the relational proportions between data.

Pie and doughnut charts in are effectively the same class in Chart.js, but have one different default value - their percentageInnerCutout. This equates what percentage of the inner should be cut out. This defaults to 0 for pie charts, and 50 for doughnuts.

They are also registered under two aliases in the Chart core. Other than their different default value, and different alias, they are exactly the same.

Example usage

// For a pie chart
var myPieChart = new Chart(ctx[0]).Pie(data,options);

// And for a doughnut chart
var myDoughnutChart = new Chart(ctx[1]).Doughnut(data,options);

Data structure

var data = [
	{
		value: 300,
		color:"#F7464A",
		highlight: "#FF5A5E",
		label: "Red"
	},
	{
		value: 50,
		color: "#46BFBD",
		highlight: "#5AD3D1",
		label: "Green"
	},
	{
		value: 100,
		color: "#FDB45C",
		highlight: "#FFC870",
		label: "Yellow"
	}
]

For a pie chart, you must pass in an array of objects with a value and a color property. The value attribute should be a number, Chart.js will total all of the numbers and calculate the relative proportion of each. The color attribute should be a string. Similar to CSS, for this string you can use HEX notation, RGB, RGBA or HSL.

Chart options

These are the customisation options specific to Pie & Doughnut charts. These options are merged with the global chart configuration options, and form the options of the chart.

{
	//Boolean - Whether we should show a stroke on each segment
	segmentShowStroke : true,

	//String - The colour of each segment stroke
	segmentStrokeColor : "#fff",

	//Number - The width of each segment stroke
	segmentStrokeWidth : 2,

	//Number - The percentage of the chart that we cut out of the middle
	percentageInnerCutout : 50, // This is 0 for Pie charts

	//Number - Amount of animation steps
	animationSteps : 100,

	//String - Animation easing effect
	animationEasing : "easeOutBounce",

	//Boolean - Whether we animate the rotation of the Doughnut
	animateRotate : true,

	//Boolean - Whether we animate scaling the Doughnut from the centre
	animateScale : false,
	{% raw %}
	//String - A legend template
	legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
	{% endraw %}
}

You can override these for your Chart instance by passing a second argument into the Doughnut method as an object with the keys you want to override.

For example, we could have a doughnut chart that animates by scaling out from the centre like so:

new Chart(ctx).Doughnut(data, {
	animateScale: true
});
// This will create a chart with all of the default options, merged from the global config,
// and the Doughnut chart defaults but this particular instance will have `animateScale` set to `true`.

We can also change these defaults values for each Doughnut type that is created, this object is available at Chart.defaults.Doughnut. Pie charts also have a clone of these defaults available to change at Chart.defaults.Pie, with the only difference being percentageInnerCutout being set to 0.

Prototype methods

.getSegmentsAtEvent( event )

Calling getSegmentsAtEvent(event) on your Chart instance passing an argument of an event, or jQuery event, will return the segment elements that are at that the same position of that event.

canvas.onclick = function(evt){
	var activePoints = myDoughnutChart.getSegmentsAtEvent(evt);
	// => activePoints is an array of segments on the canvas that are at the same position as the click event.
};

This functionality may be useful for implementing DOM based tooltips, or triggering custom behaviour in your application.

.update( )

Calling update() on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.

myDoughnutChart.segments[1].value = 10;
// Would update the first dataset's value of 'Green' to be 10
myDoughnutChart.update();
// Calling update now animates the circumference of the segment 'Green' from 50 to 10.
// and transitions other segment widths

.addData( segmentData, index )

Calling addData(segmentData, index) on your Chart instance passing an object in the same format as in the constructor. There is an option second argument of 'index', this determines at what index the new segment should be inserted into the chart.

// An object in the same format as the original data source
myDoughnutChart.addData({
	value: 130,
	color: "#B48EAD",
	highlight: "#C69CBE",
	label: "Purple"
});
// The new segment will now animate in.

.removeData( index )

Calling removeData(index) on your Chart instance will remove segment at that particular index. If none is provided, it will default to the last segment.

myDoughnutChart.removeData();
// Other segments will update to fill the empty space left.
title anchor
Advanced usage
advanced-usage

Prototype methods

For each chart, there are a set of global prototype methods on the shared ChartType which you may find useful. These are available on all charts created with Chart.js, but for the examples, let's use a line chart we've made.

// For example:
var myLineChart = new Chart(ctx).Line(data);

.clear()

Will clear the chart canvas. Used extensively internally between animation frames, but you might find it useful.

// Will clear the canvas that myLineChart is drawn on
myLineChart.clear();
// => returns 'this' for chainability

.stop()

Use this to stop any current animation loop. This will pause the chart during any current animation frame. Call .render() to re-animate.

// Stops the charts animation loop at its current frame
myLineChart.stop();
// => returns 'this' for chainability

.resize()

Use this to manually resize the canvas element. This is run each time the browser is resized, but you can call this method manually if you change the size of the canvas nodes container element.

// Resizes & redraws to fill its container element
myLineChart.resize();
// => returns 'this' for chainability

.destroy()

Use this to destroy any chart instances that are created. This will clean up any references stored to the chart object within Chart.js, along with any associated event listeners attached by Chart.js.

// Destroys a specific chart instance
myLineChart.destroy();

.toBase64Image()

This returns a base 64 encoded string of the chart in it's current state.

myLineChart.toBase64Image();
// => returns png data url of the image on the canvas

.generateLegend()

Returns an HTML string of a legend for that chart. The template for this legend is at legendTemplate in the chart options.

myLineChart.generateLegend();
// => returns HTML string of a legend for this chart

Writing new chart types

Chart.js 1.0 has been rewritten to provide a platform for developers to create their own custom chart types, and be able to share and utilise them through the Chart.js API.

The format is relatively simple, there are a set of utility helper methods under Chart.helpers, including things such as looping over collections, requesting animation frames, and easing equations.

On top of this, there are also some simple base classes of Chart elements, these all extend from Chart.Element, and include things such as points, bars and scales.

Chart.Type.extend({
	// Passing in a name registers this chart in the Chart namespace
	name: "Scatter",
	// Providing a defaults will also register the deafults in the chart namespace
	defaults : {
		options: "Here",
		available: "at this.options"
	},
	// Initialize is fired when the chart is initialized - Data is passed in as a parameter
	// Config is automatically merged by the core of Chart.js, and is available at this.options
	initialize:  function(data){
		this.chart.ctx // The drawing context for this chart
		this.chart.canvas // the canvas node for this chart
	},
	// Used to draw something on the canvas
	draw: function() {
	}
});

// Now we can create a new instance of our chart, using the Chart.js API
new Chart(ctx).Scatter(data);
// initialize is now run

Extending existing chart types

We can also extend existing chart types, and expose them to the API in the same way. Let's say for example, we might want to run some more code when we initialize every Line chart.

// Notice now we're extending the particular Line chart type, rather than the base class.
Chart.types.Line.extend({
	// Passing in a name registers this chart in the Chart namespace in the same way
	name: "LineAlt",
	initialize: function(data){
		console.log('My Line chart extension');
		Chart.types.Line.prototype.initialize.apply(this, arguments);
	}
});

// Creates a line chart in the same way
new Chart(ctx).LineAlt(data);
// but this logs 'My Line chart extension' in the console.

Community extensions

Creating custom builds

Chart.js uses gulp to build the library into a single JavaScript file. We can use this same build script with custom parameters in order to build a custom version.

Firstly, we need to ensure development dependencies are installed. With node and npm installed, after cloning the Chart.js repo to a local directory, and navigating to that directory in the command line, we can run the following:

npm install
npm install -g gulp

This will install the local development dependencies for Chart.js, along with a CLI for the JavaScript task runner gulp.

Now, we can run the gulp build task, and pass in a comma seperated list of types as an argument to build a custom version of Chart.js with only specified chart types.

Here we will create a version of Chart.js with only Line, Radar and Bar charts included:

gulp build --types=Line,Radar,Bar

This will output to the /custom directory, and write two files, Chart.js, and Chart.min.js with only those chart types included.

title anchor
Notes
notes

Browser support

Browser support for the canvas element is available in all modern & major mobile browsers (caniuse.com/canvas).

For IE8 & below, I would recommend using the polyfill ExplorerCanvas - available at https://code.google.com/p/explorercanvas/. It falls back to Internet explorer's format VML when canvas support is not available. Example use:

<head>
	<!--[if lte IE 8]>
		<script src="excanvas.js"></script>
	<![endif]-->
</head>

Usually I would recommend feature detection to choose whether or not to load a polyfill, rather than IE conditional comments, however in this case, VML is a Microsoft proprietary format, so it will only work in IE.

Some important points to note in my experience using ExplorerCanvas as a fallback.

  • Initialise charts on load rather than DOMContentReady when using the library, as sometimes a race condition will occur, and it will result in an error when trying to get the 2d context of a canvas.
  • New VML DOM elements are being created for each animation frame and there is no hardware acceleration. As a result animation is usually slow and jerky, with flashing text. It is a good idea to dynamically turn off animation based on canvas support. I recommend using the excellent Modernizr to do this.
  • When declaring fonts, the library explorercanvas requires the font name to be in single quotes inside the string. For example, instead of your scaleFontFamily property being simply "Arial", explorercanvas support, use "'Arial'" instead. Chart.js does this for default values.

Bugs & issues

Please report these on the GitHub page - at github.com/nnnick/Chart.js. If you could include a link to a simple jsbin or similar to demonstrate the issue, that'd be really helpful.

Contributing

New contributions to the library are welcome, just a couple of guidelines:

  • Tabs for indentation, not spaces please.
  • Please ensure you're changing the individual files in /src, not the concatenated output in the Chart.js file in the root of the repo.
  • Please check that your code will pass jshint code standards, gulp jshint will run this for you.
  • Please keep pull requests concise, and document new functionality in the relevant .md file.
  • Consider whether your changes are useful for all users, or if creating a Chart.js extension would be more appropriate.

License

Chart.js is open source and available under the MIT license.

var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
util = require('gulp-util'),
jshint = require('gulp-jshint'),
size = require('gulp-size'),
connect = require('gulp-connect'),
replace = require('gulp-replace'),
inquirer = require('inquirer'),
semver = require('semver'),
exec = require('child_process').exec,
fs = require('fs'),
package = require('./package.json'),
bower = require('./bower.json');
var srcDir = './src/';
/*
* Usage : gulp build --types=Bar,Line,Doughnut
* Output: - A built Chart.js file with Core and types Bar, Line and Doughnut concatenated together
* - A minified version of this code, in Chart.min.js
*/
gulp.task('build', function(){
// Default to all of the chart types, with Chart.Core first
var srcFiles = [FileName('Core')],
isCustom = !!(util.env.types),
outputDir = (isCustom) ? 'custom' : '.';
if (isCustom){
util.env.types.split(',').forEach(function(type){ return srcFiles.push(FileName(type))});
}
else{
// Seems gulp-concat remove duplicates - nice!
// So we can use this to sort out dependency order - aka include Core first!
srcFiles.push(srcDir+'*');
}
return gulp.src(srcFiles)
.pipe(concat('Chart.js'))
.pipe(replace('{{ version }}', package.version))
.pipe(gulp.dest(outputDir))
.pipe(uglify({preserveComments:'some'}))
.pipe(concat('Chart.min.js'))
.pipe(gulp.dest(outputDir));
function FileName(moduleName){
return srcDir+'Chart.'+moduleName+'.js';
};
});
/*
* Usage : gulp bump
* Prompts: Version increment to bump
* Output: - New version number written into package.json & bower.json
*/
gulp.task('bump', function(complete){
util.log('Current version:', util.colors.cyan(package.version));
var choices = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease'].map(function(versionType){
return versionType + ' (v' + semver.inc(package.version, versionType) + ')';
});
inquirer.prompt({
type: 'list',
name: 'version',
message: 'What version update would you like?',
choices: choices
}, function(res){
var increment = res.version.split(' ')[0],
newVersion = semver.inc(package.version, increment);
// Set the new versions into the bower/package object
package.version = newVersion;
bower.version = newVersion;
// Write these to their own files, then build the output
fs.writeFileSync('package.json', JSON.stringify(package, null, 2));
fs.writeFileSync('bower.json', JSON.stringify(bower, null, 2));
complete();
});
});
gulp.task('release', ['build'], function(){
exec('git tag -a v' + package.version);
});
gulp.task('jshint', function(){
return gulp.src(srcDir + '*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
gulp.task('library-size', function(){
return gulp.src('Chart.min.js')
.pipe(size({
gzip: true
}));
});
gulp.task('module-sizes', function(){
return gulp.src(srcDir + '*.js')
.pipe(uglify({preserveComments:'some'}))
.pipe(size({
showFiles: true,
gzip: true
}))
});
gulp.task('watch', function(){
gulp.watch('./src/*', ['build']);
});
gulp.task('test', ['jshint']);
gulp.task('size', ['library-size', 'module-sizes']);
gulp.task('default', ['build', 'watch']);
gulp.task('server', function(){
connect.server({
port: 8000,
});
});
// Convenience task for opening the project straight from the command line
gulp.task('_open', function(){
exec('open http://localhost:8000');
exec('subl .');
});
gulp.task('dev', ['server', 'default']);

Copyright (c) 2013-2014 Nick Downie

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

{
"name": "chart.js",
"homepage": "http://www.chartjs.org",
"description": "Simple HTML5 charts using the canvas element.",
"version": "1.0.1-beta.4",
"main": "Chart.js",
"repository": {
"type": "git",
"url": "https://github.com/nnnick/Chart.js.git"
},
"dependences": {},
"devDependencies": {
"gulp": "3.5.x",
"gulp-concat": "~2.1.x",
"gulp-connect": "~2.0.5",
"gulp-jshint": "~1.5.1",
"gulp-replace": "^0.4.0",
"gulp-size": "~0.4.0",
"gulp-uglify": "~0.2.x",
"gulp-util": "~2.2.x",
"inquirer": "^0.5.1",
"semver": "^3.0.1"
}
}

Chart.js

Simple HTML5 Charts using the canvas element chartjs.org

Documentation

You can find documentation at chartjs.org/docs. The markdown files that build the site are available under /docs. Please note - in some of the json examples of configuration you might notice some liquid tags - this is just for the generating the site html, please disregard.

License

Chart.js is available under the MIT license.

Bugs & issues

When reporting bugs or issues, if you could include a link to a simple jsbin or similar demonstrating the issue, that'd be really helpful.

Contributing

New contributions to the library are welcome, just a couple of guidelines:

  • Tabs for indentation, not spaces please.
  • Please ensure you're changing the individual files in /src, not the concatenated output in the Chart.js file in the root of the repo.
  • Please check that your code will pass jshint code standards, gulp jshint will run this for you.
  • Please keep pull requests concise, and document new functionality in the relevant .md file.
  • Consider whether your changes are useful for all users, or if creating a Chart.js extension would be more appropriate.
  • Please avoid committing in the build Chart.js & Chart.min.js file, as it causes conflicts when merging.
<!doctype html>
<html>
<head>
<title>Bar Chart</title>
<script src="../Chart.js"></script>
</head>
<body>
<div style="width: 50%">
<canvas id="canvas" height="450" width="600"></canvas>
</div>
<script>
var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
var barChartData = {
labels : ["January","February","March","April","May","June","July"],
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
strokeColor : "rgba(220,220,220,0.8)",
highlightFill: "rgba(220,220,220,0.75)",
highlightStroke: "rgba(220,220,220,1)",
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
},
{
fillColor : "rgba(151,187,205,0.5)",
strokeColor : "rgba(151,187,205,0.8)",
highlightFill : "rgba(151,187,205,0.75)",
highlightStroke : "rgba(151,187,205,1)",
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
}
]
}
window.onload = function(){
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx).Bar(barChartData, {
responsive : true
});
}
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Doughnut Chart</title>
<script src="../Chart.js"></script>
<style>
body{
padding: 0;
margin: 0;
}
#canvas-holder{
width:30%;
}
</style>
</head>
<body>
<div id="canvas-holder">
<canvas id="chart-area" width="500" height="500"/>
</div>
<script>
var doughnutData = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
},
{
value: 40,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 120,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey"
}
];
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {responsive : true});
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Line Chart</title>
<script src="../Chart.js"></script>
</head>
<body>
<div style="width:30%">
<div>
<canvas id="canvas" height="450" width="600"></canvas>
</div>
</div>
<script>
var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
var lineChartData = {
labels : ["January","February","March","April","May","June","July"],
datasets : [
{
label: "My First dataset",
fillColor : "rgba(220,220,220,0.2)",
strokeColor : "rgba(220,220,220,1)",
pointColor : "rgba(220,220,220,1)",
pointStrokeColor : "#fff",
pointHighlightFill : "#fff",
pointHighlightStroke : "rgba(220,220,220,1)",
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
},
{
label: "My Second dataset",
fillColor : "rgba(151,187,205,0.2)",
strokeColor : "rgba(151,187,205,1)",
pointColor : "rgba(151,187,205,1)",
pointStrokeColor : "#fff",
pointHighlightFill : "#fff",
pointHighlightStroke : "rgba(151,187,205,1)",
data : [randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor(),randomScalingFactor()]
}
]
}
window.onload = function(){
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx).Line(lineChartData, {
responsive: true
});
}
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Pie Chart</title>
<script src="../Chart.js"></script>
</head>
<body>
<div id="canvas-holder">
<canvas id="chart-area" width="300" height="300"/>
</div>
<script>
var pieData = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
},
{
value: 40,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 120,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey"
}
];
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
window.myPie = new Chart(ctx).Pie(pieData);
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Polar Area Chart</title>
<script src="../Chart.js"></script>
</head>
<body>
<div id="canvas-holder" style="width:30%">
<canvas id="chart-area" width="300" height="300"/>
</div>
<script>
var polarData = [
{
value: 300,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#46BFBD",
highlight: "#5AD3D1",
label: "Green"
},
{
value: 100,
color: "#FDB45C",
highlight: "#FFC870",
label: "Yellow"
},
{
value: 40,
color: "#949FB1",
highlight: "#A8B3C5",
label: "Grey"
},
{
value: 120,
color: "#4D5360",
highlight: "#616774",
label: "Dark Grey"
}
];
window.onload = function(){
var ctx = document.getElementById("chart-area").getContext("2d");
window.myPolarArea = new Chart(ctx).PolarArea(polarData, {
responsive:true
});
};
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Radar Chart</title>
<script src="../Chart.js"></script>
<meta name = "viewport" content = "initial-scale = 1, user-scalable = no">
<style>
canvas{
}
</style>
</head>
<body>
<div style="width:30%">
<canvas id="canvas" height="450" width="450"></canvas>
</div>
<script>
var radarChartData = {
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
datasets: [
{
label: "My First dataset",
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [65,59,90,81,56,55,40]
},
{
label: "My Second dataset",
fillColor: "rgba(151,187,205,0.2)",
strokeColor: "rgba(151,187,205,1)",
pointColor: "rgba(151,187,205,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(151,187,205,1)",
data: [28,48,40,19,96,27,100]
}
]
};
window.onload = function(){
window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(radarChartData, {
responsive: true
});
}
</script>
</body>
</html>
(function(){
"use strict";
var root = this,
Chart = root.Chart,
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
scaleBeginAtZero : true,
//Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,
//String - Colour of the grid lines
scaleGridLineColor : "rgba(0,0,0,.05)",
//Number - Width of the grid lines
scaleGridLineWidth : 1,
//Boolean - If there is a stroke on each bar
barShowStroke : true,
//Number - Pixel width of the bar stroke
barStrokeWidth : 2,
//Number - Spacing between each of the X value sets
barValueSpacing : 5,
//Number - Spacing between data sets within X values
barDatasetSpacing : 1,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
name: "Bar",
defaults : defaultConfig,
initialize: function(data){
//Expose options as a scope variable here so we can access it in the ScaleClass
var options = this.options;
this.ScaleClass = Chart.Scale.extend({
offsetGridLines : true,
calculateBarX : function(datasetCount, datasetIndex, barIndex){
//Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
var xWidth = this.calculateBaseWidth(),
xAbsolute = this.calculateX(barIndex) - (xWidth/2),
barWidth = this.calculateBarWidth(datasetCount);
return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
},
calculateBaseWidth : function(){
return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
},
calculateBarWidth : function(datasetCount){
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing);
return (baseWidth / datasetCount);
}
});
this.datasets = [];
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
this.eachBars(function(bar){
bar.restore(['fillColor', 'strokeColor']);
});
helpers.each(activeBars, function(activeBar){
activeBar.fillColor = activeBar.highlightFill;
activeBar.strokeColor = activeBar.highlightStroke;
});
this.showTooltip(activeBars);
});
}
//Declare the extension of the default point, to cater for the options passed in to the constructor
this.BarClass = Chart.Rectangle.extend({
strokeWidth : this.options.barStrokeWidth,
showStroke : this.options.barShowStroke,
ctx : this.chart.ctx
});
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets,function(dataset,datasetIndex){
var datasetObject = {
label : dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
bars : []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data,function(dataPoint,index){
//Add a new point for each piece of data, passing any required data to draw.
datasetObject.bars.push(new this.BarClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
strokeColor : dataset.strokeColor,
fillColor : dataset.fillColor,
highlightFill : dataset.highlightFill || dataset.fillColor,
highlightStroke : dataset.highlightStroke || dataset.strokeColor
}));
},this);
},this);
this.buildScale(data.labels);
this.BarClass.prototype.base = this.scale.endPoint;
this.eachBars(function(bar, index, datasetIndex){
helpers.extend(bar, {
width : this.scale.calculateBarWidth(this.datasets.length),
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y: this.scale.endPoint
});
bar.save();
}, this);
this.render();
},
update : function(){
this.scale.update();
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor', 'strokeColor']);
});
this.eachBars(function(bar){
bar.save();
});
this.render();
},
eachBars : function(callback){
helpers.each(this.datasets,function(dataset, datasetIndex){
helpers.each(dataset.bars, callback, this, datasetIndex);
},this);
},
getBarsAtEvent : function(e){
var barsArray = [],
eventPosition = helpers.getRelativePosition(e),
datasetIterator = function(dataset){
barsArray.push(dataset.bars[barIndex]);
},
barIndex;
for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
helpers.each(this.datasets, datasetIterator);
return barsArray;
}
}
}
return barsArray;
},
buildScale : function(labels){
var self = this;
var dataTotal = function(){
var values = [];
self.eachBars(function(bar){
values.push(bar.value);
});
return values;
};
var scaleOptions = {
templateString : this.options.scaleLabel,
height : this.chart.height,
width : this.chart.width,
ctx : this.chart.ctx,
textColor : this.options.scaleFontColor,
fontSize : this.options.scaleFontSize,
fontStyle : this.options.scaleFontStyle,
fontFamily : this.options.scaleFontFamily,
valuesCount : labels.length,
beginAtZero : this.options.scaleBeginAtZero,
integersOnly : this.options.scaleIntegersOnly,
calculateYRange: function(currentHeight){
var updatedRanges = helpers.calculateScaleRange(
dataTotal(),
currentHeight,
this.fontSize,
this.beginAtZero,
this.integersOnly
);
helpers.extend(this, updatedRanges);
},
xLabels : labels,
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth : this.options.scaleLineWidth,
lineColor : this.options.scaleLineColor,
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
showLabels : this.options.scaleShowLabels,
display : this.options.showScale
};
if (this.options.scaleOverride){
helpers.extend(scaleOptions, {
calculateYRange: helpers.noop,
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
});
}
this.scale = new this.ScaleClass(scaleOptions);
},
addData : function(valuesArray,label){
//Map the values array for each of the datasets
helpers.each(valuesArray,function(value,datasetIndex){
//Add a new point for each piece of data, passing any required data to draw.
this.datasets[datasetIndex].bars.push(new this.BarClass({
value : value,
label : label,
x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1),
y: this.scale.endPoint,
width : this.scale.calculateBarWidth(this.datasets.length),
base : this.scale.endPoint,
strokeColor : this.datasets[datasetIndex].strokeColor,
fillColor : this.datasets[datasetIndex].fillColor
}));
},this);
this.scale.addXLabel(label);
//Then re-render the chart.
this.update();
},
removeData : function(){
this.scale.removeXLabel();
//Then re-render the chart.
helpers.each(this.datasets,function(dataset){
dataset.bars.shift();
},this);
this.update();
},
reflow : function(){
helpers.extend(this.BarClass.prototype,{
y: this.scale.endPoint,
base : this.scale.endPoint
});
var newScaleProps = helpers.extend({
height : this.chart.height,
width : this.chart.width
});
this.scale.update(newScaleProps);
},
draw : function(ease){
var easingDecimal = ease || 1;
this.clear();
var ctx = this.chart.ctx;
this.scale.draw(easingDecimal);
//Draw all the bars for each dataset
helpers.each(this.datasets,function(dataset,datasetIndex){
helpers.each(dataset.bars,function(bar,index){
if (bar.hasValue()){
bar.base = this.scale.endPoint;
//Transition then draw
bar.transition({
x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index),
y : this.scale.calculateY(bar.value),
width : this.scale.calculateBarWidth(this.datasets.length)
}, easingDecimal).draw();
}
},this);
},this);
}
});
}).call(this);
/*!
* Chart.js
* http://chartjs.org/
* Version: {{ version }}
*
* Copyright 2014 Nick Downie
* Released under the MIT license
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
*/
(function(){
"use strict";
//Declare root variable - window in the browser, global on the server
var root = this,
previous = root.Chart;
//Occupy the global variable of Chart, and create a simple base class
var Chart = function(context){
var chart = this;
this.canvas = context.canvas;
this.ctx = context;
//Variables global to the chart
var width = this.width = context.canvas.width;
var height = this.height = context.canvas.height;
this.aspectRatio = this.width / this.height;
//High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
helpers.retinaScale(this);
return this;
};
//Globally expose the defaults to allow for user updating/changing
Chart.defaults = {
global: {
// Boolean - Whether to animate the chart
animation: true,
// Number - Number of animation steps
animationSteps: 60,
// String - Animation easing effect
animationEasing: "easeOutQuart",
// Boolean - If we should show the scale at all
showScale: true,
// Boolean - If we want to override with a hard coded scale
scaleOverride: false,
// ** Required if scaleOverride is true **
// Number - The number of steps in a hard coded scale
scaleSteps: null,
// Number - The value jump in the hard coded scale
scaleStepWidth: null,
// Number - The scale starting value
scaleStartValue: null,
// String - Colour of the scale line
scaleLineColor: "rgba(0,0,0,.1)",
// Number - Pixel width of the scale line
scaleLineWidth: 1,
// Boolean - Whether to show labels on the scale
scaleShowLabels: true,
// Interpolated JS string - can access value
scaleLabel: "<%=value%>",
// Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there
scaleIntegersOnly: true,
// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
scaleBeginAtZero: false,
// String - Scale label font declaration for the scale label
scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Scale label font size in pixels
scaleFontSize: 12,
// String - Scale label font weight style
scaleFontStyle: "normal",
// String - Scale label font colour
scaleFontColor: "#666",
// Boolean - whether or not the chart should be responsive and resize when the browser does.
responsive: false,
// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
maintainAspectRatio: true,
// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
showTooltips: true,
// Array - Array of string names to attach tooltip events
tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
// String - Tooltip background colour
tooltipFillColor: "rgba(0,0,0,0.8)",
// String - Tooltip label font declaration for the scale label
tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Tooltip label font size in pixels
tooltipFontSize: 14,
// String - Tooltip font weight style
tooltipFontStyle: "normal",
// String - Tooltip label font colour
tooltipFontColor: "#fff",
// String - Tooltip title font declaration for the scale label
tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Tooltip title font size in pixels
tooltipTitleFontSize: 14,
// String - Tooltip title font weight style
tooltipTitleFontStyle: "bold",
// String - Tooltip title font colour
tooltipTitleFontColor: "#fff",
// Number - pixel width of padding around tooltip text
tooltipYPadding: 6,
// Number - pixel width of padding around tooltip text
tooltipXPadding: 6,
// Number - Size of the caret on the tooltip
tooltipCaretSize: 8,
// Number - Pixel radius of the tooltip border
tooltipCornerRadius: 6,
// Number - Pixel offset from point x to tooltip edge
tooltipXOffset: 10,
// String - Template string for single tooltips
tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
// String - Template string for single tooltips
multiTooltipTemplate: "<%= value %>",
// String - Colour behind the legend colour block
multiTooltipKeyBackground: '#fff',
// Function - Will fire on animation progression.
onAnimationProgress: function(){},
// Function - Will fire on animation completion.
onAnimationComplete: function(){}
}
};
//Create a dictionary of chart types, to allow for extension of existing types
Chart.types = {};
//Global Chart helpers object for utility methods and classes
var helpers = Chart.helpers = {};
//-- Basic js utility methods
var each = helpers.each = function(loopable,callback,self){
var additionalArgs = Array.prototype.slice.call(arguments, 3);
// Check to see if null or undefined firstly.
if (loopable){
if (loopable.length === +loopable.length){
var i;
for (i=0; i<loopable.length; i++){
callback.apply(self,[loopable[i], i].concat(additionalArgs));
}
}
else{
for (var item in loopable){
callback.apply(self,[loopable[item],item].concat(additionalArgs));
}
}
}
},
clone = helpers.clone = function(obj){
var objClone = {};
each(obj,function(value,key){
if (obj.hasOwnProperty(key)) objClone[key] = value;
});
return objClone;
},
extend = helpers.extend = function(base){
each(Array.prototype.slice.call(arguments,1), function(extensionObject) {
each(extensionObject,function(value,key){
if (extensionObject.hasOwnProperty(key)) base[key] = value;
});
});
return base;
},
merge = helpers.merge = function(base,master){
//Merge properties in left object over to a shallow clone of object right.
var args = Array.prototype.slice.call(arguments,0);
args.unshift({});
return extend.apply(null, args);
},
indexOf = helpers.indexOf = function(arrayToSearch, item){
if (Array.prototype.indexOf) {
return arrayToSearch.indexOf(item);
}
else{
for (var i = 0; i < arrayToSearch.length; i++) {
if (arrayToSearch[i] === item) return i;
}
return -1;
}
},
where = helpers.where = function(collection, filterCallback){
var filtered = [];
helpers.each(collection, function(item){
if (filterCallback(item)){
filtered.push(item);
}
});
return filtered;
},
findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){
// Default to start of the array
if (!startIndex){
startIndex = -1;
}
for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
var currentItem = arrayToSearch[i];
if (filterCallback(currentItem)){
return currentItem;
}
};
},
findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){
// Default to end of the array
if (!startIndex){
startIndex = arrayToSearch.length;
}
for (var i = startIndex - 1; i >= 0; i--) {
var currentItem = arrayToSearch[i];
if (filterCallback(currentItem)){
return currentItem;
}
};
},
inherits = helpers.inherits = function(extensions){
//Basic javascript inheritance based on the model created in Backbone.js
var parent = this;
var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); };
var Surrogate = function(){ this.constructor = ChartElement;};
Surrogate.prototype = parent.prototype;
ChartElement.prototype = new Surrogate();
ChartElement.extend = inherits;
if (extensions) extend(ChartElement.prototype, extensions);
ChartElement.__super__ = parent.prototype;
return ChartElement;
},
noop = helpers.noop = function(){},
uid = helpers.uid = (function(){
var id=0;
return function(){
return "chart-" + id++;
};
})(),
warn = helpers.warn = function(str){
//Method for warning of errors
if (window.console && typeof window.console.warn == "function") console.warn(str);
},
amd = helpers.amd = (typeof root.define == 'function' && root.define.amd),
//-- Math methods
isNumber = helpers.isNumber = function(n){
return !isNaN(parseFloat(n)) && isFinite(n);
},
max = helpers.max = function(array){
return Math.max.apply( Math, array );
},
min = helpers.min = function(array){
return Math.min.apply( Math, array );
},
cap = helpers.cap = function(valueToCap,maxValue,minValue){
if(isNumber(maxValue)) {
if( valueToCap > maxValue ) {
return maxValue;
}
}
else if(isNumber(minValue)){
if ( valueToCap < minValue ){
return minValue;
}
}
return valueToCap;
},
getDecimalPlaces = helpers.getDecimalPlaces = function(num){
if (num%1!==0 && isNumber(num)){
return num.toString().split(".")[1].length;
}
else {
return 0;
}
},
toRadians = helpers.radians = function(degrees){
return degrees * (Math.PI/180);
},
// Gets the angle from vertical upright to the point about a centre.
getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){
var distanceFromXCenter = anglePoint.x - centrePoint.x,
distanceFromYCenter = anglePoint.y - centrePoint.y,
radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter);
//If the segment is in the top left quadrant, we need to add another rotation to the angle
if (distanceFromXCenter < 0 && distanceFromYCenter < 0){
angle += Math.PI*2;
}
return {
angle: angle,
distance: radialDistanceFromCenter
};
},
aliasPixel = helpers.aliasPixel = function(pixelWidth){
return (pixelWidth % 2 === 0) ? 0 : 0.5;
},
splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){
//Props to Rob Spencer at scaled innovation for his post on splining between points
//http://scaledinnovation.com/analytics/splines/aboutSplines.html
var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)),
d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)),
fa=t*d01/(d01+d12),// scaling factor for triangle Ta
fb=t*d12/(d01+d12);
return {
inner : {
x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x),
y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y)
},
outer : {
x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x),
y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y)
}
};
},
calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){
return Math.floor(Math.log(val) / Math.LN10);
},
calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){
//Set a minimum step of two - a point at the top of the graph, and a point at the base
var minSteps = 2,
maxSteps = Math.floor(drawingSize/(textSize * 1.5)),
skipFitting = (minSteps >= maxSteps);
var maxValue = max(valuesArray),
minValue = min(valuesArray);
// We need some degree of seperation here to calculate the scales if all the values are the same
// Adding/minusing 0.5 will give us a range of 1.
if (maxValue === minValue){
maxValue += 0.5;
// So we don't end up with a graph with a negative start value if we've said always start from zero
if (minValue >= 0.5 && !startFromZero){
minValue -= 0.5;
}
else{
// Make up a whole number above the values
maxValue += 0.5;
}
}
var valueRange = Math.abs(maxValue - minValue),
rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange),
graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude),
graphRange = graphMax - graphMin,
stepValue = Math.pow(10, rangeOrderOfMagnitude),
numberOfSteps = Math.round(graphRange / stepValue);
//If we have more space on the graph we'll use it to give more definition to the data
while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) {
if(numberOfSteps > maxSteps){
stepValue *=2;
numberOfSteps = Math.round(graphRange/stepValue);
// Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps.
if (numberOfSteps % 1 !== 0){
skipFitting = true;
}
}
//We can fit in double the amount of scale points on the scale
else{
//If user has declared ints only, and the step value isn't a decimal
if (integersOnly && rangeOrderOfMagnitude >= 0){
//If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float
if(stepValue/2 % 1 === 0){
stepValue /=2;
numberOfSteps = Math.round(graphRange/stepValue);
}
//If it would make it a float break out of the loop
else{
break;
}
}
//If the scale doesn't have to be an int, make the scale more granular anyway.
else{
stepValue /=2;
numberOfSteps = Math.round(graphRange/stepValue);
}
}
}
if (skipFitting){
numberOfSteps = minSteps;
stepValue = graphRange / numberOfSteps;
}
return {
steps : numberOfSteps,
stepValue : stepValue,
min : graphMin,
max : graphMin + (numberOfSteps * stepValue)
};
},
/* jshint ignore:start */
// Blows up jshint errors based on the new Function constructor
//Templating methods
//Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/
template = helpers.template = function(templateString, valuesObject){
// If templateString is function rather than string-template - call the function for valuesObject
if(templateString instanceof Function){
return templateString(valuesObject);
}
var cache = {};
function tmpl(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] = cache[str] :
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'") +
"');}return p.join('');"
);
// Provide some basic currying to the user
return data ? fn( data ) : fn;
}
return tmpl(templateString,valuesObject);
},
/* jshint ignore:end */
generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){
var labelsArray = new Array(numberOfSteps);
if (labelTemplateString){
each(labelsArray,function(val,index){
labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))});
});
}
return labelsArray;
},
//--Animation methods
//Easing functions adapted from Robert Penner's easing equations
//http://www.robertpenner.com/easing/
easingEffects = helpers.easingEffects = {
linear: function (t) {
return t;
},
easeInQuad: function (t) {
return t * t;
},
easeOutQuad: function (t) {
return -1 * t * (t - 2);
},
easeInOutQuad: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t;
return -1 / 2 * ((--t) * (t - 2) - 1);
},
easeInCubic: function (t) {
return t * t * t;
},
easeOutCubic: function (t) {
return 1 * ((t = t / 1 - 1) * t * t + 1);
},
easeInOutCubic: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t;
return 1 / 2 * ((t -= 2) * t * t + 2);
},
easeInQuart: function (t) {
return t * t * t * t;
},
easeOutQuart: function (t) {
return -1 * ((t = t / 1 - 1) * t * t * t - 1);
},
easeInOutQuart: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t;
return -1 / 2 * ((t -= 2) * t * t * t - 2);
},
easeInQuint: function (t) {
return 1 * (t /= 1) * t * t * t * t;
},
easeOutQuint: function (t) {
return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
},
easeInOutQuint: function (t) {
if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t;
return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
},
easeInSine: function (t) {
return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
},
easeOutSine: function (t) {
return 1 * Math.sin(t / 1 * (Math.PI / 2));
},
easeInOutSine: function (t) {
return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
},
easeInExpo: function (t) {
return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
},
easeOutExpo: function (t) {
return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
},
easeInOutExpo: function (t) {
if (t === 0) return 0;
if (t === 1) return 1;
if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1));
return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
},
easeInCirc: function (t) {
if (t >= 1) return t;
return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
},
easeOutCirc: function (t) {
return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
},
easeInOutCirc: function (t) {
if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
},
easeInElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0) return 0;
if ((t /= 1) == 1) return 1;
if (!p) p = 1 * 0.3;
if (a < Math.abs(1)) {
a = 1;
s = p / 4;
} else s = p / (2 * Math.PI) * Math.asin(1 / a);
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
},
easeOutElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0) return 0;
if ((t /= 1) == 1) return 1;
if (!p) p = 1 * 0.3;
if (a < Math.abs(1)) {
a = 1;
s = p / 4;
} else s = p / (2 * Math.PI) * Math.asin(1 / a);
return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
},
easeInOutElastic: function (t) {
var s = 1.70158;
var p = 0;
var a = 1;
if (t === 0) return 0;
if ((t /= 1 / 2) == 2) return 1;
if (!p) p = 1 * (0.3 * 1.5);
if (a < Math.abs(1)) {
a = 1;
s = p / 4;
} else s = p / (2 * Math.PI) * Math.asin(1 / a);
if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
},
easeInBack: function (t) {
var s = 1.70158;
return 1 * (t /= 1) * t * ((s + 1) * t - s);
},
easeOutBack: function (t) {
var s = 1.70158;
return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
},
easeInOutBack: function (t) {
var s = 1.70158;
if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
},
easeInBounce: function (t) {
return 1 - easingEffects.easeOutBounce(1 - t);
},
easeOutBounce: function (t) {
if ((t /= 1) < (1 / 2.75)) {
return 1 * (7.5625 * t * t);
} else if (t < (2 / 2.75)) {
return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
} else if (t < (2.5 / 2.75)) {
return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
} else {
return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
}
},
easeInOutBounce: function (t) {
if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5;
return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
}
},
//Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
requestAnimFrame = helpers.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
return window.setTimeout(callback, 1000 / 60);
};
})(),
cancelAnimFrame = helpers.cancelAnimFrame = (function(){
return window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.oCancelAnimationFrame ||
window.msCancelAnimationFrame ||
function(callback) {
return window.clearTimeout(callback, 1000 / 60);
};
})(),
animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){
var currentStep = 0,
easingFunction = easingEffects[easingString] || easingEffects.linear;
var animationFrame = function(){
currentStep++;
var stepDecimal = currentStep/totalSteps;
var easeDecimal = easingFunction(stepDecimal);
callback.call(chartInstance,easeDecimal,stepDecimal, currentStep);
onProgress.call(chartInstance,easeDecimal,stepDecimal);
if (currentStep < totalSteps){
chartInstance.animationFrame = requestAnimFrame(animationFrame);
} else{
onComplete.apply(chartInstance);
}
};
requestAnimFrame(animationFrame);
},
//-- DOM methods
getRelativePosition = helpers.getRelativePosition = function(evt){
var mouseX, mouseY;
var e = evt.originalEvent || evt,
canvas = evt.currentTarget || evt.srcElement,
boundingRect = canvas.getBoundingClientRect();
if (e.touches){
mouseX = e.touches[0].clientX - boundingRect.left;
mouseY = e.touches[0].clientY - boundingRect.top;
}
else{
mouseX = e.clientX - boundingRect.left;
mouseY = e.clientY - boundingRect.top;
}
return {
x : mouseX,
y : mouseY
};
},
addEvent = helpers.addEvent = function(node,eventType,method){
if (node.addEventListener){
node.addEventListener(eventType,method);
} else if (node.attachEvent){
node.attachEvent("on"+eventType, method);
} else {
node["on"+eventType] = method;
}
},
removeEvent = helpers.removeEvent = function(node, eventType, handler){
if (node.removeEventListener){
node.removeEventListener(eventType, handler, false);
} else if (node.detachEvent){
node.detachEvent("on"+eventType,handler);
} else{
node["on" + eventType] = noop;
}
},
bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){
// Create the events object if it's not already present
if (!chartInstance.events) chartInstance.events = {};
each(arrayOfEvents,function(eventName){
chartInstance.events[eventName] = function(){
handler.apply(chartInstance, arguments);
};
addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]);
});
},
unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) {
each(arrayOfEvents, function(handler,eventName){
removeEvent(chartInstance.chart.canvas, eventName, handler);
});
},
getMaximumWidth = helpers.getMaximumWidth = function(domNode){
var container = domNode.parentNode;
// TODO = check cross browser stuff with this.
return container.clientWidth;
},
getMaximumHeight = helpers.getMaximumHeight = function(domNode){
var container = domNode.parentNode;
// TODO = check cross browser stuff with this.
return container.clientHeight;
},
getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
retinaScale = helpers.retinaScale = function(chart){
var ctx = chart.ctx,
width = chart.canvas.width,
height = chart.canvas.height;
if (window.devicePixelRatio) {
ctx.canvas.style.width = width + "px";
ctx.canvas.style.height = height + "px";
ctx.canvas.height = height * window.devicePixelRatio;
ctx.canvas.width = width * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
}
},
//-- Canvas methods
clear = helpers.clear = function(chart){
chart.ctx.clearRect(0,0,chart.width,chart.height);
},
fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){
return fontStyle + " " + pixelSize+"px " + fontFamily;
},
longestText = helpers.longestText = function(ctx,font,arrayOfStrings){
ctx.font = font;
var longest = 0;
each(arrayOfStrings,function(string){
var textWidth = ctx.measureText(string).width;
longest = (textWidth > longest) ? textWidth : longest;
});
return longest;
},
drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.closePath();
};
//Store a reference to each instance - allowing us to globally resize chart instances on window resize.
//Destroy method on the chart will remove the instance of the chart from this reference.
Chart.instances = {};
Chart.Type = function(data,options,chart){
this.options = options;
this.chart = chart;
this.id = uid();
//Add the chart instance to the global namespace
Chart.instances[this.id] = this;
// Initialize is always called when a chart type is created
// By default it is a no op, but it should be extended
if (options.responsive){
this.resize();
}
this.initialize.call(this,data);
};
//Core methods that'll be a part of every chart type
extend(Chart.Type.prototype,{
initialize : function(){return this;},
clear : function(){
clear(this.chart);
return this;
},
stop : function(){
// Stops any current animation loop occuring
helpers.cancelAnimFrame.call(root, this.animationFrame);
return this;
},
resize : function(callback){
this.stop();
var canvas = this.chart.canvas,
newWidth = getMaximumWidth(this.chart.canvas),
newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
canvas.width = this.chart.width = newWidth;
canvas.height = this.chart.height = newHeight;
retinaScale(this.chart);
if (typeof callback === "function"){
callback.apply(this, Array.prototype.slice.call(arguments, 1));
}
return this;
},
reflow : noop,
render : function(reflow){
if (reflow){
this.reflow();
}
if (this.options.animation && !reflow){
helpers.animationLoop(
this.draw,
this.options.animationSteps,
this.options.animationEasing,
this.options.onAnimationProgress,
this.options.onAnimationComplete,
this
);
}
else{
this.draw();
this.options.onAnimationComplete.call(this);
}
return this;
},
generateLegend : function(){
return template(this.options.legendTemplate,this);
},
destroy : function(){
this.clear();
unbindEvents(this, this.events);
delete Chart.instances[this.id];
},
showTooltip : function(ChartElements, forceRedraw){
// Only redraw the chart if we've actually changed what we're hovering on.
if (typeof this.activeElements === 'undefined') this.activeElements = [];
var isChanged = (function(Elements){
var changed = false;
if (Elements.length !== this.activeElements.length){
changed = true;
return changed;
}
each(Elements, function(element, index){
if (element !== this.activeElements[index]){
changed = true;
}
}, this);
return changed;
}).call(this, ChartElements);
if (!isChanged && !forceRedraw){
return;
}
else{
this.activeElements = ChartElements;
}
this.draw();
if (ChartElements.length > 0){
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
if (this.datasets && this.datasets.length > 1) {
var dataArray,
dataIndex;
for (var i = this.datasets.length - 1; i >= 0; i--) {
dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
dataIndex = indexOf(dataArray, ChartElements[0]);
if (dataIndex !== -1){
break;
}
}
var tooltipLabels = [],
tooltipColors = [],
medianPosition = (function(index) {
// Get all the points at that particular index
var Elements = [],
dataCollection,
xPositions = [],
yPositions = [],
xMax,
yMax,
xMin,
yMin;
helpers.each(this.datasets, function(dataset){
dataCollection = dataset.points || dataset.bars || dataset.segments;
if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
Elements.push(dataCollection[dataIndex]);
}
});
helpers.each(Elements, function(element) {
xPositions.push(element.x);
yPositions.push(element.y);
//Include any colour information about the element
tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
tooltipColors.push({
fill: element._saved.fillColor || element.fillColor,
stroke: element._saved.strokeColor || element.strokeColor
});
}, this);
yMin = min(yPositions);
yMax = max(yPositions);
xMin = min(xPositions);
xMax = max(xPositions);
return {
x: (xMin > this.chart.width/2) ? xMin : xMax,
y: (yMin + yMax)/2
};
}).call(this, dataIndex);
new Chart.MultiTooltip({
x: medianPosition.x,
y: medianPosition.y,
xPadding: this.options.tooltipXPadding,
yPadding: this.options.tooltipYPadding,
xOffset: this.options.tooltipXOffset,
fillColor: this.options.tooltipFillColor,
textColor: this.options.tooltipFontColor,
fontFamily: this.options.tooltipFontFamily,
fontStyle: this.options.tooltipFontStyle,
fontSize: this.options.tooltipFontSize,
titleTextColor: this.options.tooltipTitleFontColor,
titleFontFamily: this.options.tooltipTitleFontFamily,
titleFontStyle: this.options.tooltipTitleFontStyle,
titleFontSize: this.options.tooltipTitleFontSize,
cornerRadius: this.options.tooltipCornerRadius,
labels: tooltipLabels,
legendColors: tooltipColors,
legendColorBackground : this.options.multiTooltipKeyBackground,
title: ChartElements[0].label,
chart: this.chart,
ctx: this.chart.ctx
}).draw();
} else {
each(ChartElements, function(Element) {
var tooltipPosition = Element.tooltipPosition();
new Chart.Tooltip({
x: Math.round(tooltipPosition.x),
y: Math.round(tooltipPosition.y),
xPadding: this.options.tooltipXPadding,
yPadding: this.options.tooltipYPadding,
fillColor: this.options.tooltipFillColor,
textColor: this.options.tooltipFontColor,
fontFamily: this.options.tooltipFontFamily,
fontStyle: this.options.tooltipFontStyle,
fontSize: this.options.tooltipFontSize,
caretHeight: this.options.tooltipCaretSize,
cornerRadius: this.options.tooltipCornerRadius,
text: template(this.options.tooltipTemplate, Element),
chart: this.chart
}).draw();
}, this);
}
}
return this;
},
toBase64Image : function(){
return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
}
});
Chart.Type.extend = function(extensions){
var parent = this;
var ChartType = function(){
return parent.apply(this,arguments);
};
//Copy the prototype object of the this class
ChartType.prototype = clone(parent.prototype);
//Now overwrite some of the properties in the base class with the new extensions
extend(ChartType.prototype, extensions);
ChartType.extend = Chart.Type.extend;
if (extensions.name || parent.prototype.name){
var chartName = extensions.name || parent.prototype.name;
//Assign any potential default values of the new chart type
//If none are defined, we'll use a clone of the chart type this is being extended from.
//I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
//doesn't define some defaults of their own.
var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults);
Chart.types[chartName] = ChartType;
//Register this new chart type in the Chart prototype
Chart.prototype[chartName] = function(data,options){
var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});
return new ChartType(data,config,this);
};
} else{
warn("Name not provided for this chart, so it hasn't been registered");
}
return parent;
};
Chart.Element = function(configuration){
extend(this,configuration);
this.initialize.apply(this,arguments);
this.save();
};
extend(Chart.Element.prototype,{
initialize : function(){},
restore : function(props){
if (!props){
extend(this,this._saved);
} else {
each(props,function(key){
this[key] = this._saved[key];
},this);
}
return this;
},
save : function(){
this._saved = clone(this);
delete this._saved._saved;
return this;
},
update : function(newProps){
each(newProps,function(value,key){
this._saved[key] = this[key];
this[key] = value;
},this);
return this;
},
transition : function(props,ease){
each(props,function(value,key){
this[key] = ((value - this._saved[key]) * ease) + this._saved[key];
},this);
return this;
},
tooltipPosition : function(){
return {
x : this.x,
y : this.y
};
},
hasValue: function(){
return isNumber(this.value);
}
});
Chart.Element.extend = inherits;
Chart.Point = Chart.Element.extend({
display: true,
inRange: function(chartX,chartY){
var hitDetectionRange = this.hitDetectionRadius + this.radius;
return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2));
},
draw : function(){
if (this.display){
var ctx = this.ctx;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.closePath();
ctx.strokeStyle = this.strokeColor;
ctx.lineWidth = this.strokeWidth;
ctx.fillStyle = this.fillColor;
ctx.fill();
ctx.stroke();
}
//Quick debug for bezier curve splining
//Highlights control points and the line between them.
//Handy for dev - stripped in the min version.
// ctx.save();
// ctx.fillStyle = "black";
// ctx.strokeStyle = "black"
// ctx.beginPath();
// ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2);
// ctx.fill();
// ctx.beginPath();
// ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2);
// ctx.fill();
// ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y);
// ctx.lineTo(this.x, this.y);
// ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y);
// ctx.stroke();
// ctx.restore();
}
});
Chart.Arc = Chart.Element.extend({
inRange : function(chartX,chartY){
var pointRelativePosition = helpers.getAngleFromPoint(this, {
x: chartX,
y: chartY
});
//Check if within the range of the open/close angle
var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle),
withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius);
return (betweenAngles && withinRadius);
//Ensure within the outside of the arc centre, but inside arc outer
},
tooltipPosition : function(){
var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2),
rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius;
return {
x : this.x + (Math.cos(centreAngle) * rangeFromCentre),
y : this.y + (Math.sin(centreAngle) * rangeFromCentre)
};
},
draw : function(animationPercent){
var easingDecimal = animationPercent || 1;
var ctx = this.ctx;
ctx.beginPath();
ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle);
ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true);
ctx.closePath();
ctx.strokeStyle = this.strokeColor;
ctx.lineWidth = this.strokeWidth;
ctx.fillStyle = this.fillColor;
ctx.fill();
ctx.lineJoin = 'bevel';
if (this.showStroke){
ctx.stroke();
}
}
});
Chart.Rectangle = Chart.Element.extend({
draw : function(){
var ctx = this.ctx,
halfWidth = this.width/2,
leftX = this.x - halfWidth,
rightX = this.x + halfWidth,
top = this.base - (this.base - this.y),
halfStroke = this.strokeWidth / 2;
// Canvas doesn't allow us to stroke inside the width so we can
// adjust the sizes to fit if we're setting a stroke on the line
if (this.showStroke){
leftX += halfStroke;
rightX -= halfStroke;
top += halfStroke;
}
ctx.beginPath();
ctx.fillStyle = this.fillColor;
ctx.strokeStyle = this.strokeColor;
ctx.lineWidth = this.strokeWidth;
// It'd be nice to keep this class totally generic to any rectangle
// and simply specify which border to miss out.
ctx.moveTo(leftX, this.base);
ctx.lineTo(leftX, top);
ctx.lineTo(rightX, top);
ctx.lineTo(rightX, this.base);
ctx.fill();
if (this.showStroke){
ctx.stroke();
}
},
height : function(){
return this.base - this.y;
},
inRange : function(chartX,chartY){
return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base);
}
});
Chart.Tooltip = Chart.Element.extend({
draw : function(){
var ctx = this.chart.ctx;
ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
this.xAlign = "center";
this.yAlign = "above";
//Distance between the actual element.y position and the start of the tooltip caret
var caretPadding = 2;
var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding,
tooltipRectHeight = this.fontSize + 2*this.yPadding,
tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding;
if (this.x + tooltipWidth/2 >this.chart.width){
this.xAlign = "left";
} else if (this.x - tooltipWidth/2 < 0){
this.xAlign = "right";
}
if (this.y - tooltipHeight < 0){
this.yAlign = "below";
}
var tooltipX = this.x - tooltipWidth/2,
tooltipY = this.y - tooltipHeight;
ctx.fillStyle = this.fillColor;
switch(this.yAlign)
{
case "above":
//Draw a caret above the x/y
ctx.beginPath();
ctx.moveTo(this.x,this.y - caretPadding);
ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight));
ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight));
ctx.closePath();
ctx.fill();
break;
case "below":
tooltipY = this.y + caretPadding + this.caretHeight;
//Draw a caret below the x/y
ctx.beginPath();
ctx.moveTo(this.x, this.y + caretPadding);
ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight);
ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight);
ctx.closePath();
ctx.fill();
break;
}
switch(this.xAlign)
{
case "left":
tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight);
break;
case "right":
tooltipX = this.x - (this.cornerRadius + this.caretHeight);
break;
}
drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius);
ctx.fill();
ctx.fillStyle = this.textColor;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2);
}
});
Chart.MultiTooltip = Chart.Element.extend({
initialize : function(){
this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily);
this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5;
this.ctx.font = this.titleFont;
var titleWidth = this.ctx.measureText(this.title).width,
//Label has a legend square as well so account for this.
labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3,
longestTextWidth = max([labelWidth,titleWidth]);
this.width = longestTextWidth + (this.xPadding*2);
var halfHeight = this.height/2;
//Check to ensure the height will fit on the canvas
//The three is to buffer form the very
if (this.y - halfHeight < 0 ){
this.y = halfHeight;
} else if (this.y + halfHeight > this.chart.height){
this.y = this.chart.height - halfHeight;
}
//Decide whether to align left or right based on position on canvas
if (this.x > this.chart.width/2){
this.x -= this.xOffset + this.width;
} else {
this.x += this.xOffset;
}
},
getLineHeight : function(index){
var baseLineHeight = this.y - (this.height/2) + this.yPadding,
afterTitleIndex = index-1;
//If the index is zero, we're getting the title
if (index === 0){
return baseLineHeight + this.titleFontSize/2;
} else{
return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5;
}
},
draw : function(){
drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius);
var ctx = this.ctx;
ctx.fillStyle = this.fillColor;
ctx.fill();
ctx.closePath();
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillStyle = this.titleTextColor;
ctx.font = this.titleFont;
ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0));
ctx.font = this.font;
helpers.each(this.labels,function(label,index){
ctx.fillStyle = this.textColor;
ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1));
//A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas)
//ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
//Instead we'll make a white filled block to put the legendColour palette over.
ctx.fillStyle = this.legendColorBackground;
ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
ctx.fillStyle = this.legendColors[index].fill;
ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize);
},this);
}
});
Chart.Scale = Chart.Element.extend({
initialize : function(){
this.fit();
},
buildYLabels : function(){
this.yLabels = [];
var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
for (var i=0; i<=this.steps; i++){
this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
}
this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0;
},
addXLabel : function(label){
this.xLabels.push(label);
this.valuesCount++;
this.fit();
},
removeXLabel : function(){
this.xLabels.shift();
this.valuesCount--;
this.fit();
},
// Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use
fit: function(){
// First we need the width of the yLabels, assuming the xLabels aren't rotated
// To do that we need the base line at the top and base of the chart, assuming there is no x label rotation
this.startPoint = (this.display) ? this.fontSize : 0;
this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels
// Apply padding settings to the start and end point.
this.startPoint += this.padding;
this.endPoint -= this.padding;
// Cache the starting height, so can determine if we need to recalculate the scale yAxis
var cachedHeight = this.endPoint - this.startPoint,
cachedYLabelWidth;
// Build the current yLabels so we have an idea of what size they'll be to start
/*
* This sets what is returned from calculateScaleRange as static properties of this class:
*
this.steps;
this.stepValue;
this.min;
this.max;
*
*/
this.calculateYRange(cachedHeight);
// With these properties set we can now build the array of yLabels
// and also the width of the largest yLabel
this.buildYLabels();
this.calculateXLabelRotation();
while((cachedHeight > this.endPoint - this.startPoint)){
cachedHeight = this.endPoint - this.startPoint;
cachedYLabelWidth = this.yLabelWidth;
this.calculateYRange(cachedHeight);
this.buildYLabels();
// Only go through the xLabel loop again if the yLabel width has changed
if (cachedYLabelWidth < this.yLabelWidth){
this.calculateXLabelRotation();
}
}
},
calculateXLabelRotation : function(){
//Get the width of each grid by calculating the difference
//between x offsets between 0 and 1.
this.ctx.font = this.font;
var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
firstRotated,
lastRotated;
this.xScalePaddingRight = lastWidth/2 + 3;
this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10;
this.xLabelRotation = 0;
if (this.display){
var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels),
cosRotation,
firstRotatedWidth;
this.xLabelWidth = originalLabelWidth;
//Allow 3 pixels x2 padding either side for label readability
var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
//Max label rotate should be 90 - also act as a loop counter
while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){
cosRotation = Math.cos(toRadians(this.xLabelRotation));
firstRotated = cosRotation * firstWidth;
lastRotated = cosRotation * lastWidth;
// We're right aligning the text now.
if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){
this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
}
this.xScalePaddingRight = this.fontSize/2;
this.xLabelRotation++;
this.xLabelWidth = cosRotation * originalLabelWidth;
}
if (this.xLabelRotation > 0){
this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3;
}
}
else{
this.xLabelWidth = 0;
this.xScalePaddingRight = this.padding;
this.xScalePaddingLeft = this.padding;
}
},
// Needs to be overidden in each Chart type
// Otherwise we need to pass all the data into the scale class
calculateYRange: noop,
drawingArea: function(){
return this.startPoint - this.endPoint;
},
calculateY : function(value){
var scalingFactor = this.drawingArea() / (this.min - this.max);
return this.endPoint - (scalingFactor * (value - this.min));
},
calculateX : function(index){
var isRotated = (this.xLabelRotation > 0),
// innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding,
innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight),
valueWidth = innerWidth/(this.valuesCount - ((this.offsetGridLines) ? 0 : 1)),
valueOffset = (valueWidth * index) + this.xScalePaddingLeft;
if (this.offsetGridLines){
valueOffset += (valueWidth/2);
}
return Math.round(valueOffset);
},
update : function(newProps){
helpers.extend(this, newProps);
this.fit();
},
draw : function(){
var ctx = this.ctx,
yLabelGap = (this.endPoint - this.startPoint) / this.steps,
xStart = Math.round(this.xScalePaddingLeft);
if (this.display){
ctx.fillStyle = this.textColor;
ctx.font = this.font;
each(this.yLabels,function(labelString,index){
var yLabelCenter = this.endPoint - (yLabelGap * index),
linePositionY = Math.round(yLabelCenter);
ctx.textAlign = "right";
ctx.textBaseline = "middle";
if (this.showLabels){
ctx.fillText(labelString,xStart - 10,yLabelCenter);
}
ctx.beginPath();
if (index > 0){
// This is a grid line in the centre, so drop that
ctx.lineWidth = this.gridLineWidth;
ctx.strokeStyle = this.gridLineColor;
} else {
// This is the first line on the scale
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
}
linePositionY += helpers.aliasPixel(ctx.lineWidth);
ctx.moveTo(xStart, linePositionY);
ctx.lineTo(this.width, linePositionY);
ctx.stroke();
ctx.closePath();
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
ctx.beginPath();
ctx.moveTo(xStart - 5, linePositionY);
ctx.lineTo(xStart, linePositionY);
ctx.stroke();
ctx.closePath();
},this);
each(this.xLabels,function(label,index){
var xPos = this.calculateX(index) + aliasPixel(this.lineWidth),
// Check to see if line/bar here and decide where to place the line
linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth),
isRotated = (this.xLabelRotation > 0);
ctx.beginPath();
if (index > 0){
// This is a grid line in the centre, so drop that
ctx.lineWidth = this.gridLineWidth;
ctx.strokeStyle = this.gridLineColor;
} else {
// This is the first line on the scale
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
}
ctx.moveTo(linePos,this.endPoint);
ctx.lineTo(linePos,this.startPoint - 3);
ctx.stroke();
ctx.closePath();
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.lineColor;
// Small lines at the bottom of the base grid line
ctx.beginPath();
ctx.moveTo(linePos,this.endPoint);
ctx.lineTo(linePos,this.endPoint + 5);
ctx.stroke();
ctx.closePath();
ctx.save();
ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8);
ctx.rotate(toRadians(this.xLabelRotation)*-1);
ctx.font = this.font;
ctx.textAlign = (isRotated) ? "right" : "center";
ctx.textBaseline = (isRotated) ? "middle" : "top";
ctx.fillText(label, 0, 0);
ctx.restore();
},this);
}
}
});
Chart.RadialScale = Chart.Element.extend({
initialize: function(){
this.size = min([this.height, this.width]);
this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
},
calculateCenterOffset: function(value){
// Take into account half font size + the yPadding of the top value
var scalingFactor = this.drawingArea / (this.max - this.min);
return (value - this.min) * scalingFactor;
},
update : function(){
if (!this.lineArc){
this.setScaleSize();
} else {
this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2);
}
this.buildYLabels();
},
buildYLabels: function(){
this.yLabels = [];
var stepDecimalPlaces = getDecimalPlaces(this.stepValue);
for (var i=0; i<=this.steps; i++){
this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)}));
}
},
getCircumference : function(){
return ((Math.PI*2) / this.valuesCount);
},
setScaleSize: function(){
/*
* Right, this is really confusing and there is a lot of maths going on here
* The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
*
* Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
*
* Solution:
*
* We assume the radius of the polygon is half the size of the canvas at first
* at each index we check if the text overlaps.
*
* Where it does, we store that angle and that index.
*
* After finding the largest index and angle we calculate how much we need to remove
* from the shape radius to move the point inwards by that x.
*
* We average the left and right distances to get the maximum shape radius that can fit in the box
* along with labels.
*
* Once we have that, we can find the centre point for the chart, by taking the x text protrusion
* on each side, removing that from the size, halving it and adding the left x protrusion width.
*
* This will mean we have a shape fitted to the canvas, as large as it can be with the labels
* and position it in the most space efficient manner
*
* https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
*/
// Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
// Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]),
pointPosition,
i,
textWidth,
halfTextWidth,
furthestRight = this.width,
furthestRightIndex,
furthestRightAngle,
furthestLeft = 0,
furthestLeftIndex,
furthestLeftAngle,
xProtrusionLeft,
xProtrusionRight,
radiusReductionRight,
radiusReductionLeft,
maxWidthRadius;
this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
for (i=0;i<this.valuesCount;i++){
// 5px to space the text slightly out - similar to what we do in the draw function.
pointPosition = this.getPointPosition(i, largestPossibleRadius);
textWidth = this.ctx.measureText(template(this.templateString, { value: this.labels[i] })).width + 5;
if (i === 0 || i === this.valuesCount/2){
// If we're at index zero, or exactly the middle, we're at exactly the top/bottom
// of the radar chart, so text will be aligned centrally, so we'll half it and compare
// w/left and right text sizes
halfTextWidth = textWidth/2;
if (pointPosition.x + halfTextWidth > furthestRight) {
furthestRight = pointPosition.x + halfTextWidth;
furthestRightIndex = i;
}
if (pointPosition.x - halfTextWidth < furthestLeft) {
furthestLeft = pointPosition.x - halfTextWidth;
furthestLeftIndex = i;
}
}
else if (i < this.valuesCount/2) {
// Less than half the values means we'll left align the text
if (pointPosition.x + textWidth > furthestRight) {
furthestRight = pointPosition.x + textWidth;
furthestRightIndex = i;
}
}
else if (i > this.valuesCount/2){
// More than half the values means we'll right align the text
if (pointPosition.x - textWidth < furthestLeft) {
furthestLeft = pointPosition.x - textWidth;
furthestLeftIndex = i;
}
}
}
xProtrusionLeft = furthestLeft;
xProtrusionRight = Math.ceil(furthestRight - this.width);
furthestRightAngle = this.getIndexAngle(furthestRightIndex);
furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2);
radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2);
// Ensure we actually need to reduce the size of the chart
radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2;
//this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2])
this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
},
setCenterPoint: function(leftMovement, rightMovement){
var maxRight = this.width - rightMovement - this.drawingArea,
maxLeft = leftMovement + this.drawingArea;
this.xCenter = (maxLeft + maxRight)/2;
// Always vertically in the centre as the text height doesn't change
this.yCenter = (this.height/2);
},
getIndexAngle : function(index){
var angleMultiplier = (Math.PI * 2) / this.valuesCount;
// Start from the top instead of right, so remove a quarter of the circle
return index * angleMultiplier - (Math.PI/2);
},
getPointPosition : function(index, distanceFromCenter){
var thisAngle = this.getIndexAngle(index);
return {
x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,
y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter
};
},
draw: function(){
if (this.display){
var ctx = this.ctx;
each(this.yLabels, function(label, index){
// Don't draw a centre value
if (index > 0){
var yCenterOffset = index * (this.drawingArea/this.steps),
yHeight = this.yCenter - yCenterOffset,
pointPosition;
// Draw circular lines around the scale
if (this.lineWidth > 0){
ctx.strokeStyle = this.lineColor;
ctx.lineWidth = this.lineWidth;
if(this.lineArc){
ctx.beginPath();
ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2);
ctx.closePath();
ctx.stroke();
} else{
ctx.beginPath();
for (var i=0;i<this.valuesCount;i++)
{
pointPosition = this.getPointPosition(i, this.calculateCenterOffset(this.min + (index * this.stepValue)));
if (i === 0){
ctx.moveTo(pointPosition.x, pointPosition.y);
} else {
ctx.lineTo(pointPosition.x, pointPosition.y);
}
}
ctx.closePath();
ctx.stroke();
}
}
if(this.showLabels){
ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily);
if (this.showLabelBackdrop){
var labelWidth = ctx.measureText(label).width;
ctx.fillStyle = this.backdropColor;
ctx.fillRect(
this.xCenter - labelWidth/2 - this.backdropPaddingX,
yHeight - this.fontSize/2 - this.backdropPaddingY,
labelWidth + this.backdropPaddingX*2,
this.fontSize + this.backdropPaddingY*2
);
}
ctx.textAlign = 'center';
ctx.textBaseline = "middle";
ctx.fillStyle = this.fontColor;
ctx.fillText(label, this.xCenter, yHeight);
}
}
}, this);
if (!this.lineArc){
ctx.lineWidth = this.angleLineWidth;
ctx.strokeStyle = this.angleLineColor;
for (var i = this.valuesCount - 1; i >= 0; i--) {
if (this.angleLineWidth > 0){
var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max));
ctx.beginPath();
ctx.moveTo(this.xCenter, this.yCenter);
ctx.lineTo(outerPosition.x, outerPosition.y);
ctx.stroke();
ctx.closePath();
}
// Extra 3px out for some label spacing
var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5);
ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily);
ctx.fillStyle = this.pointLabelFontColor;
var labelsCount = this.labels.length,
halfLabelsCount = this.labels.length/2,
quarterLabelsCount = halfLabelsCount/2,
upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
if (i === 0){
ctx.textAlign = 'center';
} else if(i === halfLabelsCount){
ctx.textAlign = 'center';
} else if (i < halfLabelsCount){
ctx.textAlign = 'left';
} else {
ctx.textAlign = 'right';
}
// Set the correct text baseline based on outer positioning
if (exactQuarter){
ctx.textBaseline = 'middle';
} else if (upperHalf){
ctx.textBaseline = 'bottom';
} else {
ctx.textBaseline = 'top';
}
ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y);
}
}
}
}
});
// Attach global event to resize each chart instance when the browser resizes
helpers.addEvent(window, "resize", (function(){
// Basic debounce of resize function so it doesn't hurt performance when resizing browser.
var timeout;
return function(){
clearTimeout(timeout);
timeout = setTimeout(function(){
each(Chart.instances,function(instance){
// If the responsive flag is set in the chart instance config
// Cascade the resize event down to the chart.
if (instance.options.responsive){
instance.resize(instance.render, true);
}
});
}, 50);
};
})());
if (amd) {
define(function(){
return Chart;
});
} else if (typeof module === 'object' && module.exports) {
module.exports = Chart;
}
root.Chart = Chart;
Chart.noConflict = function(){
root.Chart = previous;
return Chart;
};
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
//Cache a local reference to Chart.helpers
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Whether we should show a stroke on each segment
segmentShowStroke : true,
//String - The colour of each segment stroke
segmentStrokeColor : "#fff",
//Number - The width of each segment stroke
segmentStrokeWidth : 2,
//The percentage of the chart that we cut out of the middle.
percentageInnerCutout : 50,
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect
animationEasing : "easeOutBounce",
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true,
//Boolean - Whether we animate scaling the Doughnut from the centre
animateScale : false,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
//Passing in a name registers this chart in the Chart namespace
name: "Doughnut",
//Providing a defaults will also register the deafults in the chart namespace
defaults : defaultConfig,
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
//Config is automatically merged by the core of Chart.js, and is available at this.options
initialize: function(data){
//Declare segments as a static property to prevent inheriting across the Chart type prototype
this.segments = [];
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
this.SegmentArc = Chart.Arc.extend({
ctx : this.chart.ctx,
x : this.chart.width/2,
y : this.chart.height/2
});
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
helpers.each(this.segments,function(segment){
segment.restore(["fillColor"]);
});
helpers.each(activeSegments,function(activeSegment){
activeSegment.fillColor = activeSegment.highlightColor;
});
this.showTooltip(activeSegments);
});
}
this.calculateTotal(data);
helpers.each(data,function(datapoint, index){
this.addData(datapoint, index, true);
},this);
this.render();
},
getSegmentsAtEvent : function(e){
var segmentsArray = [];
var location = helpers.getRelativePosition(e);
helpers.each(this.segments,function(segment){
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
},this);
return segmentsArray;
},
addData : function(segment, atIndex, silent){
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
value : segment.value,
outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
fillColor : segment.color,
highlightColor : segment.highlight || segment.color,
showStroke : this.options.segmentShowStroke,
strokeWidth : this.options.segmentStrokeWidth,
strokeColor : this.options.segmentStrokeColor,
startAngle : Math.PI * 1.5,
circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
label : segment.label
}));
if (!silent){
this.reflow();
this.update();
}
},
calculateCircumference : function(value){
return (Math.PI*2)*(value / this.total);
},
calculateTotal : function(data){
this.total = 0;
helpers.each(data,function(segment){
this.total += segment.value;
},this);
},
update : function(){
this.calculateTotal(this.segments);
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor']);
});
helpers.each(this.segments,function(segment){
segment.save();
});
this.render();
},
removeData: function(atIndex){
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
this.segments.splice(indexToDelete, 1);
this.reflow();
this.update();
},
reflow : function(){
helpers.extend(this.SegmentArc.prototype,{
x : this.chart.width/2,
y : this.chart.height/2
});
this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
helpers.each(this.segments, function(segment){
segment.update({
outerRadius : this.outerRadius,
innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
});
}, this);
},
draw : function(easeDecimal){
var animDecimal = (easeDecimal) ? easeDecimal : 1;
this.clear();
helpers.each(this.segments,function(segment,index){
segment.transition({
circumference : this.calculateCircumference(segment.value),
outerRadius : this.outerRadius,
innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
},animDecimal);
segment.endAngle = segment.startAngle + segment.circumference;
segment.draw();
if (index === 0){
segment.startAngle = Math.PI * 1.5;
}
//Check to see if it's the last segment, if not get the next and update the start angle
if (index < this.segments.length-1){
this.segments[index+1].startAngle = segment.endAngle;
}
},this);
}
});
Chart.types.Doughnut.extend({
name : "Pie",
defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
});
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
helpers = Chart.helpers;
var defaultConfig = {
///Boolean - Whether grid lines are shown across the chart
scaleShowGridLines : true,
//String - Colour of the grid lines
scaleGridLineColor : "rgba(0,0,0,.05)",
//Number - Width of the grid lines
scaleGridLineWidth : 1,
//Boolean - Whether the line is curved between points
bezierCurve : true,
//Number - Tension of the bezier curve between points
bezierCurveTension : 0.4,
//Boolean - Whether to show a dot for each point
pointDot : true,
//Number - Radius of each point dot in pixels
pointDotRadius : 4,
//Number - Pixel width of point dot stroke
pointDotStrokeWidth : 1,
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
pointHitDetectionRadius : 20,
//Boolean - Whether to show a stroke for datasets
datasetStroke : true,
//Number - Pixel width of dataset stroke
datasetStrokeWidth : 2,
//Boolean - Whether to fill the dataset with a colour
datasetFill : true,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
name: "Line",
defaults : defaultConfig,
initialize: function(data){
//Declare the extension of the default point, to cater for the options passed in to the constructor
this.PointClass = Chart.Point.extend({
strokeWidth : this.options.pointDotStrokeWidth,
radius : this.options.pointDotRadius,
display: this.options.pointDot,
hitDetectionRadius : this.options.pointHitDetectionRadius,
ctx : this.chart.ctx,
inRange : function(mouseX){
return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2));
}
});
this.datasets = [];
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
this.eachPoints(function(point){
point.restore(['fillColor', 'strokeColor']);
});
helpers.each(activePoints, function(activePoint){
activePoint.fillColor = activePoint.highlightFill;
activePoint.strokeColor = activePoint.highlightStroke;
});
this.showTooltip(activePoints);
});
}
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets,function(dataset){
var datasetObject = {
label : dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
pointColor : dataset.pointColor,
pointStrokeColor : dataset.pointStrokeColor,
points : []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data,function(dataPoint,index){
//Add a new point for each piece of data, passing any required data to draw.
datasetObject.points.push(new this.PointClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
strokeColor : dataset.pointStrokeColor,
fillColor : dataset.pointColor,
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
}));
},this);
this.buildScale(data.labels);
this.eachPoints(function(point, index){
helpers.extend(point, {
x: this.scale.calculateX(index),
y: this.scale.endPoint
});
point.save();
}, this);
},this);
this.render();
},
update : function(){
this.scale.update();
// Reset any highlight colours before updating.
helpers.each(this.activeElements, function(activeElement){
activeElement.restore(['fillColor', 'strokeColor']);
});
this.eachPoints(function(point){
point.save();
});
this.render();
},
eachPoints : function(callback){
helpers.each(this.datasets,function(dataset){
helpers.each(dataset.points,callback,this);
},this);
},
getPointsAtEvent : function(e){
var pointsArray = [],
eventPosition = helpers.getRelativePosition(e);
helpers.each(this.datasets,function(dataset){
helpers.each(dataset.points,function(point){
if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point);
});
},this);
return pointsArray;
},
buildScale : function(labels){
var self = this;
var dataTotal = function(){
var values = [];
self.eachPoints(function(point){
values.push(point.value);
});
return values;
};
var scaleOptions = {
templateString : this.options.scaleLabel,
height : this.chart.height,
width : this.chart.width,
ctx : this.chart.ctx,
textColor : this.options.scaleFontColor,
fontSize : this.options.scaleFontSize,
fontStyle : this.options.scaleFontStyle,
fontFamily : this.options.scaleFontFamily,
valuesCount : labels.length,
beginAtZero : this.options.scaleBeginAtZero,
integersOnly : this.options.scaleIntegersOnly,
calculateYRange : function(currentHeight){
var updatedRanges = helpers.calculateScaleRange(
dataTotal(),
currentHeight,
this.fontSize,
this.beginAtZero,
this.integersOnly
);
helpers.extend(this, updatedRanges);
},
xLabels : labels,
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth : this.options.scaleLineWidth,
lineColor : this.options.scaleLineColor,
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
showLabels : this.options.scaleShowLabels,
display : this.options.showScale
};
if (this.options.scaleOverride){
helpers.extend(scaleOptions, {
calculateYRange: helpers.noop,
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
});
}
this.scale = new Chart.Scale(scaleOptions);
},
addData : function(valuesArray,label){
//Map the values array for each of the datasets
helpers.each(valuesArray,function(value,datasetIndex){
//Add a new point for each piece of data, passing any required data to draw.
this.datasets[datasetIndex].points.push(new this.PointClass({
value : value,
label : label,
x: this.scale.calculateX(this.scale.valuesCount+1),
y: this.scale.endPoint,
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
fillColor : this.datasets[datasetIndex].pointColor
}));
},this);
this.scale.addXLabel(label);
//Then re-render the chart.
this.update();
},
removeData : function(){
this.scale.removeXLabel();
//Then re-render the chart.
helpers.each(this.datasets,function(dataset){
dataset.points.shift();
},this);
this.update();
},
reflow : function(){
var newScaleProps = helpers.extend({
height : this.chart.height,
width : this.chart.width
});
this.scale.update(newScaleProps);
},
draw : function(ease){
var easingDecimal = ease || 1;
this.clear();
var ctx = this.chart.ctx;
// Some helper methods for getting the next/prev points
var hasValue = function(item){
return item.value !== null;
},
nextPoint = function(point, collection, index){
return helpers.findNextWhere(collection, hasValue, index) || point;
},
previousPoint = function(point, collection, index){
return helpers.findPreviousWhere(collection, hasValue, index) || point;
};
this.scale.draw(easingDecimal);
helpers.each(this.datasets,function(dataset){
var pointsWithValues = helpers.where(dataset.points, hasValue);
//Transition each point first so that the line and point drawing isn't out of sync
//We can use this extra loop to calculate the control points of this dataset also in this loop
helpers.each(dataset.points, function(point, index){
if (point.hasValue()){
point.transition({
y : this.scale.calculateY(point.value),
x : this.scale.calculateX(index)
}, easingDecimal);
}
},this);
// Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point
// This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed
if (this.options.bezierCurve){
helpers.each(pointsWithValues, function(point, index){
var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0;
point.controlPoints = helpers.splineCurve(
previousPoint(point, pointsWithValues, index),
point,
nextPoint(point, pointsWithValues, index),
tension
);
// Prevent the bezier going outside of the bounds of the graph
// Cap puter bezier handles to the upper/lower scale bounds
if (point.controlPoints.outer.y > this.scale.endPoint){
point.controlPoints.outer.y = this.scale.endPoint;
}
else if (point.controlPoints.outer.y < this.scale.startPoint){
point.controlPoints.outer.y = this.scale.startPoint;
}
// Cap inner bezier handles to the upper/lower scale bounds
if (point.controlPoints.inner.y > this.scale.endPoint){
point.controlPoints.inner.y = this.scale.endPoint;
}
else if (point.controlPoints.inner.y < this.scale.startPoint){
point.controlPoints.inner.y = this.scale.startPoint;
}
},this);
}
//Draw the line between all the points
ctx.lineWidth = this.options.datasetStrokeWidth;
ctx.strokeStyle = dataset.strokeColor;
ctx.beginPath();
helpers.each(pointsWithValues, function(point, index){
if (index === 0){
ctx.moveTo(point.x, point.y);
}
else{
if(this.options.bezierCurve){
var previous = previousPoint(point, pointsWithValues, index);
ctx.bezierCurveTo(
previous.controlPoints.outer.x,
previous.controlPoints.outer.y,
point.controlPoints.inner.x,
point.controlPoints.inner.y,
point.x,
point.y
);
}
else{
ctx.lineTo(point.x,point.y);
}
}
}, this);
ctx.stroke();
if (this.options.datasetFill && pointsWithValues.length > 0){
//Round off the line by going to the base of the chart, back to the start, then fill.
ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint);
ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint);
ctx.fillStyle = dataset.fillColor;
ctx.closePath();
ctx.fill();
}
//Now draw the points over the line
//A little inefficient double looping, but better than the line
//lagging behind the point positions
helpers.each(pointsWithValues,function(point){
point.draw();
});
},this);
}
});
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
//Cache a local reference to Chart.helpers
helpers = Chart.helpers;
var defaultConfig = {
//Boolean - Show a backdrop to the scale label
scaleShowLabelBackdrop : true,
//String - The colour of the label backdrop
scaleBackdropColor : "rgba(255,255,255,0.75)",
// Boolean - Whether the scale should begin at zero
scaleBeginAtZero : true,
//Number - The backdrop padding above & below the label in pixels
scaleBackdropPaddingY : 2,
//Number - The backdrop padding to the side of the label in pixels
scaleBackdropPaddingX : 2,
//Boolean - Show line for each value in the scale
scaleShowLine : true,
//Boolean - Stroke a line around each segment in the chart
segmentShowStroke : true,
//String - The colour of the stroke on each segement.
segmentStrokeColor : "#fff",
//Number - The width of the stroke value in pixels
segmentStrokeWidth : 2,
//Number - Amount of animation steps
animationSteps : 100,
//String - Animation easing effect.
animationEasing : "easeOutBounce",
//Boolean - Whether to animate the rotation of the chart
animateRotate : true,
//Boolean - Whether to animate scaling the chart from the centre
animateScale : false,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"></span><%if(segments[i].label){%><%=segments[i].label%><%}%></li><%}%></ul>"
};
Chart.Type.extend({
//Passing in a name registers this chart in the Chart namespace
name: "PolarArea",
//Providing a defaults will also register the deafults in the chart namespace
defaults : defaultConfig,
//Initialize is fired when the chart is initialized - Data is passed in as a parameter
//Config is automatically merged by the core of Chart.js, and is available at this.options
initialize: function(data){
this.segments = [];
//Declare segment class as a chart instance specific class, so it can share props for this instance
this.SegmentArc = Chart.Arc.extend({
showStroke : this.options.segmentShowStroke,
strokeWidth : this.options.segmentStrokeWidth,
strokeColor : this.options.segmentStrokeColor,
ctx : this.chart.ctx,
innerRadius : 0,
x : this.chart.width/2,
y : this.chart.height/2
});
this.scale = new Chart.RadialScale({
display: this.options.showScale,
fontStyle: this.options.scaleFontStyle,
fontSize: this.options.scaleFontSize,
fontFamily: this.options.scaleFontFamily,
fontColor: this.options.scaleFontColor,
showLabels: this.options.scaleShowLabels,
showLabelBackdrop: this.options.scaleShowLabelBackdrop,
backdropColor: this.options.scaleBackdropColor,
backdropPaddingY : this.options.scaleBackdropPaddingY,
backdropPaddingX: this.options.scaleBackdropPaddingX,
lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
lineColor: this.options.scaleLineColor,
lineArc: true,
width: this.chart.width,
height: this.chart.height,
xCenter: this.chart.width/2,
yCenter: this.chart.height/2,
ctx : this.chart.ctx,
templateString: this.options.scaleLabel,
valuesCount: data.length
});
this.updateScaleRange(data);
this.scale.update();
helpers.each(data,function(segment,index){
this.addData(segment,index,true);
},this);
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
helpers.each(this.segments,function(segment){
segment.restore(["fillColor"]);
});
helpers.each(activeSegments,function(activeSegment){
activeSegment.fillColor = activeSegment.highlightColor;
});
this.showTooltip(activeSegments);
});
}
this.render();
},
getSegmentsAtEvent : function(e){
var segmentsArray = [];
var location = helpers.getRelativePosition(e);
helpers.each(this.segments,function(segment){
if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
},this);
return segmentsArray;
},
addData : function(segment, atIndex, silent){
var index = atIndex || this.segments.length;
this.segments.splice(index, 0, new this.SegmentArc({
fillColor: segment.color,
highlightColor: segment.highlight || segment.color,
label: segment.label,
value: segment.value,
outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
startAngle: Math.PI * 1.5
}));
if (!silent){
this.reflow();
this.update();
}
},
removeData: function(atIndex){
var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
this.segments.splice(indexToDelete, 1);
this.reflow();
this.update();
},
calculateTotal: function(data){
this.total = 0;
helpers.each(data,function(segment){
this.total += segment.value;
},this);
this.scale.valuesCount = this.segments.length;
},
updateScaleRange: function(datapoints){
var valuesArray = [];
helpers.each(datapoints,function(segment){
valuesArray.push(segment.value);
});
var scaleSizes = (this.options.scaleOverride) ?
{
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
} :
helpers.calculateScaleRange(
valuesArray,
helpers.min([this.chart.width, this.chart.height])/2,
this.options.scaleFontSize,
this.options.scaleBeginAtZero,
this.options.scaleIntegersOnly
);
helpers.extend(
this.scale,
scaleSizes,
{
size: helpers.min([this.chart.width, this.chart.height]),
xCenter: this.chart.width/2,
yCenter: this.chart.height/2
}
);
},
update : function(){
this.calculateTotal(this.segments);
helpers.each(this.segments,function(segment){
segment.save();
});
this.render();
},
reflow : function(){
helpers.extend(this.SegmentArc.prototype,{
x : this.chart.width/2,
y : this.chart.height/2
});
this.updateScaleRange(this.segments);
this.scale.update();
helpers.extend(this.scale,{
xCenter: this.chart.width/2,
yCenter: this.chart.height/2
});
helpers.each(this.segments, function(segment){
segment.update({
outerRadius : this.scale.calculateCenterOffset(segment.value)
});
}, this);
},
draw : function(ease){
var easingDecimal = ease || 1;
//Clear & draw the canvas
this.clear();
helpers.each(this.segments,function(segment, index){
segment.transition({
circumference : this.scale.getCircumference(),
outerRadius : this.scale.calculateCenterOffset(segment.value)
},easingDecimal);
segment.endAngle = segment.startAngle + segment.circumference;
// If we've removed the first segment we need to set the first one to
// start at the top.
if (index === 0){
segment.startAngle = Math.PI * 1.5;
}
//Check to see if it's the last segment, if not get the next and update the start angle
if (index < this.segments.length - 1){
this.segments[index+1].startAngle = segment.endAngle;
}
segment.draw();
}, this);
this.scale.draw();
}
});
}).call(this);
(function(){
"use strict";
var root = this,
Chart = root.Chart,
helpers = Chart.helpers;
Chart.Type.extend({
name: "Radar",
defaults:{
//Boolean - Whether to show lines for each scale point
scaleShowLine : true,
//Boolean - Whether we show the angle lines out of the radar
angleShowLineOut : true,
//Boolean - Whether to show labels on the scale
scaleShowLabels : false,
// Boolean - Whether the scale should begin at zero
scaleBeginAtZero : true,
//String - Colour of the angle line
angleLineColor : "rgba(0,0,0,.1)",
//Number - Pixel width of the angle line
angleLineWidth : 1,
//String - Point label font declaration
pointLabelFontFamily : "'Arial'",
//String - Point label font weight
pointLabelFontStyle : "normal",
//Number - Point label font size in pixels
pointLabelFontSize : 10,
//String - Point label font colour
pointLabelFontColor : "#666",
//Boolean - Whether to show a dot for each point
pointDot : true,
//Number - Radius of each point dot in pixels
pointDotRadius : 3,
//Number - Pixel width of point dot stroke
pointDotStrokeWidth : 1,
//Number - amount extra to add to the radius to cater for hit detection outside the drawn point
pointHitDetectionRadius : 20,
//Boolean - Whether to show a stroke for datasets
datasetStroke : true,
//Number - Pixel width of dataset stroke
datasetStrokeWidth : 2,
//Boolean - Whether to fill the dataset with a colour
datasetFill : true,
//String - A legend template
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
},
initialize: function(data){
this.PointClass = Chart.Point.extend({
strokeWidth : this.options.pointDotStrokeWidth,
radius : this.options.pointDotRadius,
display: this.options.pointDot,
hitDetectionRadius : this.options.pointHitDetectionRadius,
ctx : this.chart.ctx
});
this.datasets = [];
this.buildScale(data);
//Set up tooltip events on the chart
if (this.options.showTooltips){
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
this.eachPoints(function(point){
point.restore(['fillColor', 'strokeColor']);
});
helpers.each(activePointsCollection, function(activePoint){
activePoint.fillColor = activePoint.highlightFill;
activePoint.strokeColor = activePoint.highlightStroke;
});
this.showTooltip(activePointsCollection);
});
}
//Iterate through each of the datasets, and build this into a property of the chart
helpers.each(data.datasets,function(dataset){
var datasetObject = {
label: dataset.label || null,
fillColor : dataset.fillColor,
strokeColor : dataset.strokeColor,
pointColor : dataset.pointColor,
pointStrokeColor : dataset.pointStrokeColor,
points : []
};
this.datasets.push(datasetObject);
helpers.each(dataset.data,function(dataPoint,index){
//Add a new point for each piece of data, passing any required data to draw.
var pointPosition;
if (!this.scale.animation){
pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
}
datasetObject.points.push(new this.PointClass({
value : dataPoint,
label : data.labels[index],
datasetLabel: dataset.label,
x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
strokeColor : dataset.pointStrokeColor,
fillColor : dataset.pointColor,
highlightFill : dataset.pointHighlightFill || dataset.pointColor,
highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
}));
},this);
},this);
this.render();
},
eachPoints : function(callback){
helpers.each(this.datasets,function(dataset){
helpers.each(dataset.points,callback,this);
},this);
},
getPointsAtEvent : function(evt){
var mousePosition = helpers.getRelativePosition(evt),
fromCenter = helpers.getAngleFromPoint({
x: this.scale.xCenter,
y: this.scale.yCenter
}, mousePosition);
var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
activePointsCollection = [];
// If we're at the top, make the pointIndex 0 to get the first of the array.
if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
pointIndex = 0;
}
if (fromCenter.distance <= this.scale.drawingArea){
helpers.each(this.datasets, function(dataset){
activePointsCollection.push(dataset.points[pointIndex]);
});
}
return activePointsCollection;
},
buildScale : function(data){
this.scale = new Chart.RadialScale({
display: this.options.showScale,
fontStyle: this.options.scaleFontStyle,
fontSize: this.options.scaleFontSize,
fontFamily: this.options.scaleFontFamily,
fontColor: this.options.scaleFontColor,
showLabels: this.options.scaleShowLabels,
showLabelBackdrop: this.options.scaleShowLabelBackdrop,
backdropColor: this.options.scaleBackdropColor,
backdropPaddingY : this.options.scaleBackdropPaddingY,
backdropPaddingX: this.options.scaleBackdropPaddingX,
lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
lineColor: this.options.scaleLineColor,
angleLineColor : this.options.angleLineColor,
angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
// Point labels at the edge of each line
pointLabelFontColor : this.options.pointLabelFontColor,
pointLabelFontSize : this.options.pointLabelFontSize,
pointLabelFontFamily : this.options.pointLabelFontFamily,
pointLabelFontStyle : this.options.pointLabelFontStyle,
height : this.chart.height,
width: this.chart.width,
xCenter: this.chart.width/2,
yCenter: this.chart.height/2,
ctx : this.chart.ctx,
templateString: this.options.scaleLabel,
labels: data.labels,
valuesCount: data.datasets[0].data.length
});
this.scale.setScaleSize();
this.updateScaleRange(data.datasets);
this.scale.buildYLabels();
},
updateScaleRange: function(datasets){
var valuesArray = (function(){
var totalDataArray = [];
helpers.each(datasets,function(dataset){
if (dataset.data){
totalDataArray = totalDataArray.concat(dataset.data);
}
else {
helpers.each(dataset.points, function(point){
totalDataArray.push(point.value);
});
}
});
return totalDataArray;
})();
var scaleSizes = (this.options.scaleOverride) ?
{
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
} :
helpers.calculateScaleRange(
valuesArray,
helpers.min([this.chart.width, this.chart.height])/2,
this.options.scaleFontSize,
this.options.scaleBeginAtZero,
this.options.scaleIntegersOnly
);
helpers.extend(
this.scale,
scaleSizes
);
},
addData : function(valuesArray,label){
//Map the values array for each of the datasets
this.scale.valuesCount++;
helpers.each(valuesArray,function(value,datasetIndex){
var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
this.datasets[datasetIndex].points.push(new this.PointClass({
value : value,
label : label,
x: pointPosition.x,
y: pointPosition.y,
strokeColor : this.datasets[datasetIndex].pointStrokeColor,
fillColor : this.datasets[datasetIndex].pointColor
}));
},this);
this.scale.labels.push(label);
this.reflow();
this.update();
},
removeData : function(){
this.scale.valuesCount--;
this.scale.labels.shift();
helpers.each(this.datasets,function(dataset){
dataset.points.shift();
},this);
this.reflow();
this.update();
},
update : function(){
this.eachPoints(function(point){
point.save();
});
this.reflow();
this.render();
},
reflow: function(){
helpers.extend(this.scale, {
width : this.chart.width,
height: this.chart.height,
size : helpers.min([this.chart.width, this.chart.height]),
xCenter: this.chart.width/2,
yCenter: this.chart.height/2
});
this.updateScaleRange(this.datasets);
this.scale.setScaleSize();
this.scale.buildYLabels();
},
draw : function(ease){
var easeDecimal = ease || 1,
ctx = this.chart.ctx;
this.clear();
this.scale.draw();
helpers.each(this.datasets,function(dataset){
//Transition each point first so that the line and point drawing isn't out of sync
helpers.each(dataset.points,function(point,index){
if (point.hasValue()){
point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
}
},this);
//Draw the line between all the points
ctx.lineWidth = this.options.datasetStrokeWidth;
ctx.strokeStyle = dataset.strokeColor;
ctx.beginPath();
helpers.each(dataset.points,function(point,index){
if (index === 0){
ctx.moveTo(point.x,point.y);
}
else{
ctx.lineTo(point.x,point.y);
}
},this);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = dataset.fillColor;
ctx.fill();
//Now draw the points over the line
//A little inefficient double looping, but better than the line
//lagging behind the point positions
helpers.each(dataset.points,function(point){
if (point.hasValue()){
point.draw();
}
});
},this);
}
});
}).call(this);
{
"name": "context-free-parser",
"private": true,
"dependencies": {},
"homepage": "https://github.com/Polymer/context-free-parser",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "6b4ff5a210dc8bd3d24e73f87a6513e32f1e41b6"
},
"_source": "git://github.com/Polymer/context-free-parser.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/context-free-parser"
}
{
"name": "context-free-parser",
"private": true,
"dependencies": {}
}
<!--
@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
-->
<script src="context-free-parser.js"></script>
<link rel="import" href="../core-ajax/core-ajax.html">
<!--
Scrapes source documentation data from input text or url.
@class context-free-parser
-->
<polymer-element name="context-free-parser" attributes="url text data">
<template>
<core-ajax url="{{url}}" response="{{text}}" auto></core-ajax>
</template>
<script>
Polymer('context-free-parser', {
text: null,
textChanged: function() {
if (this.text) {
var entities = ContextFreeParser.parse(this.text);
if (!entities || entities.length === 0) {
entities = [
{name: this.url.split('/').pop(), description: '**Undocumented**'}
];
}
this.data = { classes: entities };
}
},
dataChanged: function() {
this.fire('data-ready');
}
});
</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
*/
(function(scope) {
var ContextFreeParser = {
parse: function(text) {
var top = {};
var entities = [];
var current = top;
var subCurrent = {};
var scriptDocCommentClause = '\\/\\*\\*([\\s\\S]*?)\\*\\/';
var htmlDocCommentClause = '<!--([\\s\\S]*?)-->';
// matches text between /** and */ inclusive and <!-- and --> inclusive
var docCommentRegex = new RegExp(scriptDocCommentClause + '|' + htmlDocCommentClause, 'g');
// acquire all script doc comments
var docComments = text.match(docCommentRegex) || [];
// each match represents a single block of doc comments
docComments.forEach(function(m) {
// unify line ends, remove all comment characters, split into individual lines
var lines = m.replace(/\r\n/g, '\n').replace(/^\s*\/\*\*|^\s*\*\/|^\s*\* ?|^\s*\<\!-\-|^s*\-\-\>/gm, '').split('\n');
// pragmas (@-rules) must occur on a line by themselves
var pragmas = [];
// filter lines whose first non-whitespace character is @ into the pragma list
// (and out of the `lines` array)
lines = lines.filter(function(l) {
var m = l.match(/\s*@([\w-]*) (.*)/);
if (!m) {
return true;
}
pragmas.push(m);
});
// collect all other text into a single block
var code = lines.join('\n');
// process pragmas
pragmas.forEach(function(m) {
var pragma = m[1], content = m[2];
switch (pragma) {
// currently all entities are either @class or @element
case 'class':
case 'element':
current = {
name: content,
description: code
};
entities.push(current);
break;
// an entity may have these describable sub-features
case 'attribute':
case 'property':
case 'method':
case 'event':
subCurrent = {
name: content,
description: code
};
var label = pragma == 'property' ? 'properties' : pragma + 's';
makePragma(current, label, subCurrent);
break;
// sub-feature pragmas
case 'default':
case 'type':
subCurrent[pragma] = content;
break;
case 'param':
var eventParmsRe = /\{(.+)\}\s+(\w+[.\w+]+)\s+(.*)$/;
var params = content.match(eventParmsRe);
if (params) {
var subEventObj = {
type: params[1],
name: params[2],
description: params[3]
};
makePragma(subCurrent, pragma + 's', subEventObj);
}
break;
// everything else
default:
current[pragma] = content;
break;
}
});
// utility function, yay hoisting
function makePragma(object, pragma, content) {
var p$ = object;
var p = p$[pragma];
if (!p) {
p$[pragma] = p = [];
}
p.push(content);
}
});
if (entities.length === 0) {
entities.push({name: 'Entity', description: '**Undocumented**'});
}
return entities;
}
};
if (typeof module !== 'undefined' && module.exports) {
module.exports = ContextFreeParser;
} else {
scope.ContextFreeParser = ContextFreeParser;
}
})(this);
<!--
@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>context-free-parser</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="context-free-parser.html">
</head>
<body unresolved>
<context-free-parser url="../core-ajax/core-ajax.html"></context-free-parser>
<script>
addEventListener('data-ready', function(event) {
console.dir(event.target.data);
});
</script>
</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-a11y-keys",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"homepage": "https://github.com/Polymer/core-a11y-keys",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "54e2dd7067df4bc2dea3546c4507fbb148b5ee0e"
},
"_source": "git://github.com/Polymer/core-a11y-keys.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-a11y-keys"
}
{
"name": "core-a11y-keys",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
<!--
@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
-->
<!--
`core-a11y-keys` provides a normalized interface for processing keyboard commands that pertain to [WAI-ARIA best
practices](http://www.w3.org/TR/wai-aria-practices/#kbd_general_binding). The element takes care of browser differences
with respect to Keyboard events and uses an expressive syntax to filter key presses.
Use the `keys` attribute to express what combination of keys will trigger the event to fire.
Use the `target` attribute to set up event handlers on a specific node.
The `keys-pressed` event will fire when one of the key combinations set with the `keys` attribute is pressed.
Example:
This element will call `arrowHandler` on all arrow keys:
<core-a11y-keys target="{{}}" keys="up down left right" on-keys-pressed="{{arrowHandler}}"></core-a11y-keys>
Keys Syntax:
The `keys` attribute can accepts a space seprated, `+` concatenated set of modifier keys and some common keyboard keys.
The common keys are `a-z`, `0-9` (top row and number pad), `*` (shift 8 and number pad), `F1-F12`, `Page Up`, `Page
Down`, `Left Arrow`, `Right Arrow`, `Down Arrow`, `Up Arrow`, `Home`, `End`, `Escape`, `Space`, `Tab`, and `Enter` keys.
The modifier keys are `Shift`, `Control`, and `Alt`.
All keys are expected to be lowercase and shortened:
`Left Arrow` is `left`, `Page Down` is `pagedown`, `Control` is `ctrl`, `F1` is `f1`, `Escape` is `esc` etc.
Keys Syntax Example:
Given the `keys` attribute value "ctrl+shift+f7 up pagedown esc space alt+m", the `<core-a11y-keys>` element will send
the `keys-pressed` event if any of the follow key combos are pressed: Control and Shift and F7 keys, Up Arrow key, Page
Down key, Escape key, Space key, Alt and M key.
Slider Example:
The following is an example of the set of keys that fulfil the WAI-ARIA "slider" role [best
practices](http://www.w3.org/TR/wai-aria-practices/#slider):
<core-a11y-keys target="{{}}" keys="left pagedown down" on-keys-pressed="{{decrement}}"></core-a11y-keys>
<core-a11y-keys target="{{}}" keys="right pageup up" on-keys-pressed="{{increment}}"></core-a11y-keys>
<core-a11y-keys target="{{}}" keys="home" on-keys-pressed="{{setMin}}"></core-a11y-keys>
<core-a11y-keys target="{{}}" keys="end" on-keys-pressed="{{setMax}}"></core-a11y-keys>
The `increment` function will move the slider a set amount toward the maximum value.
The `decrement` function will move the slider a set amount toward the minimum value.
The `setMin` function will move the slider to the minimum value.
The `setMax` function will move the slider to the maximum value.
Keys Syntax Grammar:
[EBNF](http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form) Grammar of the `keys` attribute.
modifier = "shift" | "ctrl" | "alt";
ascii = ? /[a-z0-9]/ ? ;
fnkey = ? f1 through f12 ? ;
arrow = "up" | "down" | "left" | "right" ;
key = "tab" | "esc" | "space" | "*" | "pageup" | "pagedown" | "home" | "end" | arrow | ascii | fnkey ;
keycombo = { modifier, "+" }, key ;
keys = keycombo, { " ", keycombo } ;
@group Core Elements
@element core-a11y-keys
@homepage github.io
-->
<link rel="import" href="../polymer/polymer.html">
<style shim-shadowdom>
html /deep/ core-a11y-keys {
display: none;
}
</style>
<polymer-element name="core-a11y-keys">
<script>
(function() {
/*
* Chrome uses an older version of DOM Level 3 Keyboard Events
*
* Most keys are labeled as text, but some are Unicode codepoints.
* Values taken from: http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/keyset.html#KeySet-Set
*/
var KEY_IDENTIFIER = {
'U+0009': 'tab',
'U+001B': 'esc',
'U+0020': 'space',
'U+002A': '*',
'U+0030': '0',
'U+0031': '1',
'U+0032': '2',
'U+0033': '3',
'U+0034': '4',
'U+0035': '5',
'U+0036': '6',
'U+0037': '7',
'U+0038': '8',
'U+0039': '9',
'U+0041': 'a',
'U+0042': 'b',
'U+0043': 'c',
'U+0044': 'd',
'U+0045': 'e',
'U+0046': 'f',
'U+0047': 'g',
'U+0048': 'h',
'U+0049': 'i',
'U+004A': 'j',
'U+004B': 'k',
'U+004C': 'l',
'U+004D': 'm',
'U+004E': 'n',
'U+004F': 'o',
'U+0050': 'p',
'U+0051': 'q',
'U+0052': 'r',
'U+0053': 's',
'U+0054': 't',
'U+0055': 'u',
'U+0056': 'v',
'U+0057': 'w',
'U+0058': 'x',
'U+0059': 'y',
'U+005A': 'z',
'U+007F': 'del'
};
/*
* Special table for KeyboardEvent.keyCode.
* KeyboardEvent.keyIdentifier is better, and KeyBoardEvent.key is even better than that
*
* Values from: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.keyCode#Value_of_keyCode
*/
var KEY_CODE = {
13: 'enter',
27: 'esc',
33: 'pageup',
34: 'pagedown',
35: 'end',
36: 'home',
32: 'space',
37: 'left',
38: 'up',
39: 'right',
40: 'down',
46: 'del',
106: '*'
};
/*
* KeyboardEvent.key is mostly represented by printable character made by the keyboard, with unprintable keys labeled
* nicely.
*
* However, on OS X, Alt+char can make a Unicode character that follows an Apple-specific mapping. In this case, we
* fall back to .keyCode.
*/
var KEY_CHAR = /[a-z0-9*]/;
function transformKey(key) {
var validKey = '';
if (key) {
var lKey = key.toLowerCase();
if (lKey.length == 1) {
if (KEY_CHAR.test(lKey)) {
validKey = lKey;
}
} else if (lKey == 'multiply') {
// numpad '*' can map to Multiply on IE/Windows
validKey = '*';
} else {
validKey = lKey;
}
}
return validKey;
}
var IDENT_CHAR = /U\+/;
function transformKeyIdentifier(keyIdent) {
var validKey = '';
if (keyIdent) {
if (IDENT_CHAR.test(keyIdent)) {
validKey = KEY_IDENTIFIER[keyIdent];
} else {
validKey = keyIdent.toLowerCase();
}
}
return validKey;
}
function transformKeyCode(keyCode) {
var validKey = '';
if (Number(keyCode)) {
if (keyCode >= 65 && keyCode <= 90) {
// ascii a-z
// lowercase is 32 offset from uppercase
validKey = String.fromCharCode(32 + keyCode);
} else if (keyCode >= 112 && keyCode <= 123) {
// function keys f1-f12
validKey = 'f' + (keyCode - 112);
} else if (keyCode >= 48 && keyCode <= 57) {
// top 0-9 keys
validKey = String(48 - keyCode);
} else if (keyCode >= 96 && keyCode <= 105) {
// num pad 0-9
validKey = String(96 - keyCode);
} else {
validKey = KEY_CODE[keyCode];
}
}
return validKey;
}
function keyboardEventToKey(ev) {
// fall back from .key, to .keyIdentifier, and then to .keyCode
var normalizedKey = transformKey(ev.key) || transformKeyIdentifier(ev.keyIdentifier) || transformKeyCode(ev.keyCode) || '';
return {
shift: ev.shiftKey,
ctrl: ev.ctrlKey,
meta: ev.metaKey,
alt: ev.altKey,
key: normalizedKey
};
}
/*
* Input: ctrl+shift+f7 => {ctrl: true, shift: true, key: 'f7'}
* ctrl/space => {ctrl: true} || {key: space}
*/
function stringToKey(keyCombo) {
var keys = keyCombo.split('+');
var keyObj = Object.create(null);
keys.forEach(function(key) {
if (key == 'shift') {
keyObj.shift = true;
} else if (key == 'ctrl') {
keyObj.ctrl = true;
} else if (key == 'alt') {
keyObj.alt = true;
} else {
keyObj.key = key;
}
});
return keyObj;
}
function keyMatches(a, b) {
return Boolean(a.alt) == Boolean(b.alt) && Boolean(a.ctrl) == Boolean(b.ctrl) && Boolean(a.shift) == Boolean(b.shift) && a.key === b.key;
}
/**
* Fired when a keycombo in `keys` is pressed.
*
* @event keys-pressed
*/
function processKeys(ev) {
var current = keyboardEventToKey(ev);
for (var i = 0, dk; i < this._desiredKeys.length; i++) {
dk = this._desiredKeys[i];
if (keyMatches(dk, current)) {
ev.preventDefault();
ev.stopPropagation();
this.fire('keys-pressed', current, this, false);
break;
}
}
}
function listen(node, handler) {
if (node && node.addEventListener) {
node.addEventListener('keydown', handler);
}
}
function unlisten(node, handler) {
if (node && node.removeEventListener) {
node.removeEventListener('keydown', handler);
}
}
Polymer('core-a11y-keys', {
created: function() {
this._keyHandler = processKeys.bind(this);
},
attached: function() {
listen(this.target, this._keyHandler);
},
detached: function() {
unlisten(this.target, this._keyHandler);
},
publish: {
/**
* The set of key combinations to listen for.
*
* @attribute keys
* @type string (keys syntax)
* @default ''
*/
keys: '',
/**
* The node that will fire keyboard events.
*
* @attribute target
* @type Node
* @default null
*/
target: null
},
keysChanged: function() {
// * can have multiple mappings: shift+8, * on numpad or Multiply on numpad
var normalized = this.keys.replace('*', '* shift+*');
this._desiredKeys = normalized.toLowerCase().split(' ').map(stringToKey);
},
targetChanged: function(oldTarget) {
unlisten(oldTarget, this._keyHandler);
listen(this.target, this._keyHandler);
}
});
})();
</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
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Core A11y Keys demo</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-a11y-keys.html">
</head>
<body>
<template is="auto-binding">
<style>
div {
height: 100px;
width: 100px;
background: gray;
}
</style>
<core-a11y-keys id="a11y" keys="* pageup pagedown left right down up shift+a alt+a home end" target="{{$.target}}" on-keys-pressed="{{print}}"></core-a11y-keys>
<div id="target" tabindex="0">focus this</div>
<pre id="output"></pre>
</template>
<script>
addEventListener('template-bound', function(ev) {
ev.target.print = function(ev) {
console.log(ev.detail);
this.$.output.textContent += ev.detail.key + ' pressed!\n';
}
});
</script>
</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-ajax",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
},
"homepage": "https://github.com/Polymer/core-ajax",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "e3e62c060b105bedd975f440ddec1f933bd8bec5"
},
"_source": "git://github.com/Polymer/core-ajax.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-ajax"
}
{
"name": "core-ajax",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
}
}
<!--
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-ajax` element exposes `XMLHttpRequest` functionality.
<core-ajax
auto
url="http://gdata.youtube.com/feeds/api/videos/"
params='{"alt":"json", "q":"chrome"}'
handleAs="json"
on-core-response="{{handleResponse}}"></core-ajax>
With `auto` set to `true`, the element performs a request whenever
its `url` or `params` properties are changed.
Note: The `params` attribute must be double quoted JSON.
You can trigger a request explicitly by calling `go` on the
element.
@element core-ajax
@status beta
@homepage github.io
-->
<link rel="import" href="core-xhr.html">
<polymer-element name="core-ajax" hidden attributes="url handleAs auto params response error method headers body contentType withCredentials">
<script>
Polymer('core-ajax', {
/**
* Fired when a response is received.
*
* @event core-response
*/
/**
* Fired when an error is received.
*
* @event core-error
*/
/**
* Fired whenever a response or an error is received.
*
* @event core-complete
*/
/**
* The URL target of the request.
*
* @attribute url
* @type string
* @default ''
*/
url: '',
/**
* Specifies what data to store in the `response` property, and
* to deliver as `event.response` in `response` events.
*
* One of:
*
* `text`: uses `XHR.responseText`.
*
* `xml`: uses `XHR.responseXML`.
*
* `json`: uses `XHR.responseText` parsed as JSON.
*
* `arraybuffer`: uses `XHR.response`.
*
* `blob`: uses `XHR.response`.
*
* `document`: uses `XHR.response`.
*
* @attribute handleAs
* @type string
* @default 'text'
*/
handleAs: '',
/**
* If true, automatically performs an Ajax request when either `url` or `params` changes.
*
* @attribute auto
* @type boolean
* @default false
*/
auto: false,
/**
* Parameters to send to the specified URL, as JSON.
*
* @attribute params
* @type string (JSON)
* @default ''
*/
params: '',
/**
* The response for the most recently made request, or null if it hasn't
* completed yet or the request resulted in error.
*
* @attribute response
* @type Object
* @default null
*/
response: null,
/**
* The error for the most recently made request, or null if it hasn't
* completed yet or the request resulted in success.
*
* @attribute error
* @type Object
* @default null
*/
error: null,
/**
* The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'.
* Default is 'GET'.
*
* @attribute method
* @type string
* @default ''
*/
method: '',
/**
* HTTP request headers to send.
*
* Example:
*
* <core-ajax
* auto
* url="http://somesite.com"
* headers='{"X-Requested-With": "XMLHttpRequest"}'
* handleAs="json"
* on-core-response="{{handleResponse}}"></core-ajax>
*
* @attribute headers
* @type Object
* @default null
*/
headers: null,
/**
* Optional raw body content to send when method === "POST".
*
* Example:
*
* <core-ajax method="POST" auto url="http://somesite.com"
* body='{"foo":1, "bar":2}'>
* </core-ajax>
*
* @attribute body
* @type Object
* @default null
*/
body: null,
/**
* Content type to use when sending data.
*
* @attribute contentType
* @type string
* @default 'application/x-www-form-urlencoded'
*/
contentType: 'application/x-www-form-urlencoded',
/**
* Set the withCredentials flag on the request.
*
* @attribute withCredentials
* @type boolean
* @default false
*/
withCredentials: false,
/**
* Additional properties to send to core-xhr.
*
* Can be set to an object containing default properties
* to send as arguments to the `core-xhr.request()` method
* which implements the low-level communication.
*
* @property xhrArgs
* @type Object
* @default null
*/
xhrArgs: null,
ready: function() {
this.xhr = document.createElement('core-xhr');
},
receive: function(response, xhr) {
if (this.isSuccess(xhr)) {
this.processResponse(xhr);
} else {
this.processError(xhr);
}
this.complete(xhr);
},
isSuccess: function(xhr) {
var status = xhr.status || 0;
return !status || (status >= 200 && status < 300);
},
processResponse: function(xhr) {
var response = this.evalResponse(xhr);
if (xhr === this.activeRequest) {
this.response = response;
}
this.fire('core-response', {response: response, xhr: xhr});
},
processError: function(xhr) {
var response = xhr.status + ': ' + xhr.responseText;
if (xhr === this.activeRequest) {
this.error = response;
}
this.fire('core-error', {response: response, xhr: xhr});
},
complete: function(xhr) {
this.fire('core-complete', {response: xhr.status, xhr: xhr});
},
evalResponse: function(xhr) {
return this[(this.handleAs || 'text') + 'Handler'](xhr);
},
xmlHandler: function(xhr) {
return xhr.responseXML;
},
textHandler: function(xhr) {
return xhr.responseText;
},
jsonHandler: function(xhr) {
var r = xhr.responseText;
try {
return JSON.parse(r);
} catch (x) {
console.warn('core-ajax caught an exception trying to parse response as JSON:');
console.warn('url:', this.url);
console.warn(x);
return r;
}
},
documentHandler: function(xhr) {
return xhr.response;
},
blobHandler: function(xhr) {
return xhr.response;
},
arraybufferHandler: function(xhr) {
return xhr.response;
},
urlChanged: function() {
if (!this.handleAs) {
var ext = String(this.url).split('.').pop();
switch (ext) {
case 'json':
this.handleAs = 'json';
break;
}
}
this.autoGo();
},
paramsChanged: function() {
this.autoGo();
},
autoChanged: function() {
this.autoGo();
},
// TODO(sorvell): multiple side-effects could call autoGo
// during one micro-task, use a job to have only one action
// occur
autoGo: function() {
if (this.auto) {
this.goJob = this.job(this.goJob, this.go, 0);
}
},
/**
* Performs an Ajax request to the specified URL.
*
* @method go
*/
go: function() {
var args = this.xhrArgs || {};
// TODO(sjmiles): we may want XHR to default to POST if body is set
args.body = this.body || args.body;
args.params = this.params || args.params;
if (args.params && typeof(args.params) == 'string') {
args.params = JSON.parse(args.params);
}
args.headers = this.headers || args.headers || {};
if (args.headers && typeof(args.headers) == 'string') {
args.headers = JSON.parse(args.headers);
}
var hasContentType = Object.keys(args.headers).some(function (header) {
return header.toLowerCase() === 'content-type';
});
if (!hasContentType && this.contentType) {
args.headers['Content-Type'] = this.contentType;
}
if (this.handleAs === 'arraybuffer' || this.handleAs === 'blob' ||
this.handleAs === 'document') {
args.responseType = this.handleAs;
}
args.withCredentials = this.withCredentials;
args.callback = this.receive.bind(this);
args.url = this.url;
args.method = this.method;
this.response = this.error = null;
this.activeRequest = args.url && this.xhr.request(args);
return this.activeRequest;
}
});
</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
-->
<!--
/**
* @group Polymer Core Elements
*
* core-xhr can be used to perform XMLHttpRequests.
*
* <core-xhr id="xhr"></core-xhr>
* ...
* this.$.xhr.request({url: url, params: params, callback: callback});
*
* @element core-xhr
*/
-->
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="core-xhr" hidden>
<script>
Polymer('core-xhr', {
/**
* Sends a HTTP request to the server and returns the XHR object.
*
* @method request
* @param {Object} inOptions
* @param {String} inOptions.url The url to which the request is sent.
* @param {String} inOptions.method The HTTP method to use, default is GET.
* @param {boolean} inOptions.sync By default, all requests are sent asynchronously. To send synchronous requests, set to true.
* @param {Object} inOptions.params Data to be sent to the server.
* @param {Object} inOptions.body The content for the request body for POST method.
* @param {Object} inOptions.headers HTTP request headers.
* @param {String} inOptions.responseType The response type. Default is 'text'.
* @param {boolean} inOptions.withCredentials Whether or not to send credentials on the request. Default is false.
* @param {Object} inOptions.callback Called when request is completed.
* @returns {Object} XHR object.
*/
request: function(options) {
var xhr = new XMLHttpRequest();
var url = options.url;
var method = options.method || 'GET';
var async = !options.sync;
//
var params = this.toQueryString(options.params);
if (params && method == 'GET') {
url += (url.indexOf('?') > 0 ? '&' : '?') + params;
}
var xhrParams = this.isBodyMethod(method) ? (options.body || params) : null;
//
xhr.open(method, url, async);
if (options.responseType) {
xhr.responseType = options.responseType;
}
if (options.withCredentials) {
xhr.withCredentials = true;
}
this.makeReadyStateHandler(xhr, options.callback);
this.setRequestHeaders(xhr, options.headers);
xhr.send(xhrParams);
if (!async) {
xhr.onreadystatechange(xhr);
}
return xhr;
},
toQueryString: function(params) {
var r = [];
for (var n in params) {
var v = params[n];
n = encodeURIComponent(n);
r.push(v == null ? n : (n + '=' + encodeURIComponent(v)));
}
return r.join('&');
},
isBodyMethod: function(method) {
return this.bodyMethods[(method || '').toUpperCase()];
},
bodyMethods: {
POST: 1,
PUT: 1,
DELETE: 1
},
makeReadyStateHandler: function(xhr, callback) {
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback && callback.call(null, xhr.response, xhr);
}
};
},
setRequestHeaders: function(xhr, headers) {
if (headers) {
for (var name in headers) {
xhr.setRequestHeader(name, headers[name]);
}
}
}
});
</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>core-ajax</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-ajax.html">
</head>
<body>
<core-ajax auto url="http://gdata.youtube.com/feeds/api/videos/"
params='{"alt":"json", "q":"chrome"}'
handleAs="json"></core-ajax>
<template repeat="{{response.feed.entry}}">
<div>{{title.$t}}</div>
</template>
<script>
document.addEventListener('polymer-ready', function() {
var ajax = document.querySelector("core-ajax");
ajax.addEventListener("core-response",
function(e) {
document.querySelector('template').model = {
response: e.detail.response
};
}
);
});
</script>
</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-ajax" label="Ajax" group="Core">
<property name="handleAs" kind="select" options="json,text,xml,arraybuffer,blob,document"></property>
<property name="method" kind="select" options="GET,POST,PUT,DELETE"></property>
<template>
<core-ajax handleAs="json" method="GET"></core-ajax>
</template>
<template id="imports">
<link rel="import" href="core-ajax.html">
</template>
</x-meta>
<!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>core-ajax-response-and-error</title>
<script src="../../../platform/platform.js"></script>
<script src="../../../polymer-test-tools/chai/chai.js"></script>
<script src="../../../polymer-test-tools/htmltest.js"></script>
<link rel="import" href="../../core-ajax.html">
</head>
<body>
<polymer-element name="race-condition">
<template>
<style>section {margin-top: 20px;}</style>
<core-ajax
id='ajax'
url="http://httpbin.org/delay/{{delay}}"
handleas="json" auto
response="{{response}}"
on-core-response="{{handleResponse}}"></core-ajax>
<div>Response url: {{response.url}}</div>
<div>Result: {{testResult}}</div>
<section>
<div>Requests</div>
<ul>
<template repeat='{{request in requests}}'>
<li>
{{request.delay}} second delay, Status: {{request.statusText}}
</li>
</template>
</ul>
</section>
</template>
<script>
Polymer({
delay: 1,
response: null,
testResult: 'pending...',
passed: false,
requests: [],
observe: {
'$.ajax.activeRequest': 'requestChanged'
},
domReady: function() {
setTimeout(function() {
if (this.response != null) {
console.error('HTTP request returned too quick!')
chai.assert.fail(
'', '', 'Indeterminate, initial request returned too quick');
this.testResult = 'indeterminate';
return;
}
this.delay = 2;
}.bind(this), 100);
// This will fail the test if it neither passes nor fails in time.
this.finalTimeout = setTimeout(function() {
chai.assert.fail('', '', 'Test timed out.');
}, 7000);
},
responseChanged: function() {
if (this.response.url != this.$.ajax.url) {
this.testResult = 'FAIL';
chai.assert.fail(this.$.ajax.url, this.response.url,
'Race condition in response attribute');
return;
}
this.passed = true;
},
passedChanged: function() {
if (this.passed && this.testResult == 'pending...') {
this.testResult = 'PASS';
clearTimeout(this.finalTimeout);
done();
}
},
requestChanged: function(o, n) {
this.requests.push({
'statusText': 'pending',
xhr: n,
delay: this.delay
});
},
handleResponse: function(resp) {
var xhr = resp.detail.xhr;
for (var i = 0; i < this.requests.length; i++) {
if (this.requests[i].xhr === xhr) {
this.requests[i].statusText = xhr.statusText;
}
}
},
});
</script>
</polymer-element>
<race-condition></race-condition>
</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.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>core-ajax</title>
<script src="../../../platform/platform.js"></script>
<script src="../../../polymer-test-tools/chai/chai.js"></script>
<script src="../../../polymer-test-tools/htmltest.js"></script>
<link rel="import" href="../../core-ajax.html">
</head>
<body>
<core-ajax
url="http://gdata.youtube.com/feeds/api/videos/"
params='{"alt":"json", "q":"chrome"}'
handleAs="json"
auto></core-ajax>
<script>
document.addEventListener('polymer-ready', function() {
var assert = chai.assert;
var ajax = document.querySelector('core-ajax');
ajax.addEventListener("core-response", function(event) {
assert.isTrue(event.detail.response.feed.entry.length > 0);
done();
});
});
</script>
</body>
</html>
htmlSuite('core-ajax', function() {
htmlTest('html/core-ajax.html');
htmlTest('html/core-ajax-response-and-error.html');
});
<!doctype htmlz>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>Web Component Test Runner</title>
<script src="../../polymer-test-tools/ci-support.js"></script>
</head>
<body>
<script>
runTests('tests.json');
</script>
</body>
</html>
{
"tools": ["chai", "mocha-tdd"],
"tests": [
"js/htmltests.js"
]
}
{
"name": "core-animated-pages",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-selector": "Polymer/core-selector#^0.4.0",
"core-style": "Polymer/core-style#^0.4.0",
"core-transition": "Polymer/core-transition#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-animated-pages",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "224eb03b59d249ee6829946233546c1dd9d264b0"
},
"_source": "git://github.com/Polymer/core-animated-pages.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-animated-pages"
}
{
"name": "core-animated-pages",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-selector": "Polymer/core-selector#^0.4.0",
"core-style": "Polymer/core-style#^0.4.0",
"core-transition": "Polymer/core-transition#^0.4.0"
}
}
/*
* @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
*/
:host {
display: block;
position: relative;
}
polyfill-next-selector { content: ':host > *'; }
::content > * {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
polyfill-next-selector { content: ':host > *:not(.core-selected):not([animate])'; }
::content > *:not(.core-selected):not([animate]) {
display: none !important;
}
<!--
@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
-->
<link href="../core-selector/core-selector.html" rel="import">
<link href="transitions/hero-transition.html" rel="import">
<link href="transitions/cross-fade.html" rel="import">
<!--
`core-animated-pages` selects one of its children "pages" to show and runs a transition
when switching between them. The transitions are designed to be pluggable, and can
accept any object that is an instance of a `core-transition-pages`. Transitions to run
are specified in the `transitions` attribute as a space-delimited string of `id`s of
transition elements. Several transitions are available with `core-animated-pages` by
default, including `hero-transition`, `cross-fade`, and `tile-cascade`.
Example:
<style>
#hero1 {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background-color: orange;
}
#hero2 {
position: absolute;
top: 200px;
left: 300px;
width: 300px;
height: 300px;
background-color: orange;
}
#bottom1, #bottom2 {
position: absolute;
bottom: 0;
top: 0;
left: 0;
height: 50px;
}
#bottom1 {
background-color: blue;
}
#bottom2 {
background-color: green;
}
</style>
// hero-transition and cross-fade are declared elsewhere
<core-animated-pages transitions="hero-transition cross-fade">
<section id="page1">
<div id="hero1" hero-id="hero" hero></div>
<div id="bottom1" cross-fade></div>
</section>
<section id="page2">
<div id="hero2" hero-id="hero" hero></div>
<div id="bottom2" cross-fade></div>
</section>
</core-animated-pages>
In the above example, two transitions (`hero-transition` and `cross-fade`) are run when switching
between `page1` and `page2`. `hero-transition` transforms elements with the same `hero-id` such
that they appear to be shared across different pages. `cross-fade` fades out the elements marked
`cross-fade` in the outgoing page, and fades in those in the incoming page. See the individual
transition's documentation for specific details.
Finding elements to transition
------------------------------
In general, a transition is applied to elements marked with a certain attribute. For example,
`hero-transition` applies the transition on elements with the `hero` and `hero-id` attribute.
Among the transitions included with `core-animated-pages`, script-based transitions such as
`hero-transition` generally look for elements up to one level of shadowRoot from the
`core-animated-pages` element, and CSS-based transitions such as `cross-fade` look for elements
within any shadowRoot within the `core-animated-pages` element. This means you can use
custom elements as pages and mark elements in their shadowRoots as heroes, or mark
elements in deeper shadowRoots with other transitions.
Example:
<polymer-element name="x-el" noscript>
<template>
<style>
#hero {
position: absolute;
top: 0;
right: 0;
width: 50px;
height: 300px;
background-color: blue;
}
</style>
<div id="hero" hero-id="bar" hero></div>
</template>
</polymer-element>
<polymer-element name="x-page-1" noscript>
<template>
<style>
#hero1 {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background-color: orange;
}
</style>
<div id="hero1" hero-id="foo" hero></div>
<div id="hero2" hero-id="bar" hero></div>
</template>
</polymer-element>
<polymer-element name="x-page-2" noscript>
<template>
<style>
#hero1 {
position: absolute;
top: 200px;
left: 300px;
width: 300px;
height: 300px;
background-color: orange;
}
#hero2 {
background-color: blue;
height: 150px;
width: 400px;
}
</style>
// The below element is one level of shadow from the core-animated-pages and will
// be transitioned.
<div id="hero1" hero-id="foo" hero></div>
// The below element contains a hero inside its shadowRoot making it two levels away
// from the core-animated-pages, and will not be transitioned.
<x-el></x-el>
</template>
</polymer-element>
<core-animated-pages transitions="hero-transition">
<x-page-1></x-page-1>
<x-page-2></x-page-2>
</core-animated-pages>
Note that the container element of the page does not participate in the transition.
// This does not work
<core-animated-pages transitions="cross-fade">
<section cross-fade></section>
<section cross-fade></section>
</core-animated-pages>
// This works
<core-animated-pages transitions="cross-fade">
<section>
<div cross-fade></div>
</section>
<section>
<div cross-fade></div>
</section>
</core-animated-pages>
Dynamically setting up transitions
----------------------------------
An easy way to set up transitions dynamically is to use property binding on
the transition attributes.
Example:
<core-animated-pages selected="{{selected}}">
<section id="page1">
<div hero-id="hero" hero></div>
</section>
<section id="page2">
<div id="foo" hero-id="hero" hero?="{{selected === 1 || selected === 0}}" cross-fade="{{selected === 2}}"></div>
</section>
<section id="page3">
</section>
</core-animated-pages>
In the above example, the "foo" element only behaves as a hero element if transitioning between
`#page1` and `#page2`. It gets cross-faded when transition to or from `#page3`.
Nesting pages
-------------
It is possible to nest core-animated-pages elements for organization. Excessive nesting is
not encouraged, however, since it makes setting up the transition more complex.
To nest core-animated-pages, the page containing the nested core-animated-pages element should
have a `selectedItem` property bound to the `selectedItem` property of the nested element. This
will allow the outer core-animated-pages to know which nested page it is actually transitioning
to.
Example:
<polymer-element name="nested-page" attributes="selectedItem">
<template>
<core-animated-pages selectedItem="{{selectedItem}}">
...
</core-animated-pages>
</template>
</polymer-element>
<core-animated-pages>
<section id="page1"></section>
<nested-page id="page2"></nested-page>
</core-animated-pages>
@element core-animated-pages
@extends core-selector
@status beta
@homepage github.io
-->
<!--
Fired before a page transition occurs. Both pages involved in the transition are visible when
this event fires. This is useful if there is something the client needs to do when a page becomes
visible.
@event core-animated-pages-transition-prepare
-->
<!--
Fired when a page transition completes.
@event core-animated-pages-transition-end
-->
<polymer-element name="core-animated-pages" extends="core-selector" notap attributes="transitions">
<template>
<link href="core-animated-pages.css" rel="stylesheet">
<shadow></shadow>
</template>
<script>
Polymer({
eventDelegates: {
'core-transitionend': 'transitionEnd'
},
/**
* A space-delimited string of transitions to use when switching between pages in this element.
* The strings are `id`s of `core-transition-pages` elements included elsewhere. See the
* individual transition's document for specific details.
*
* @attribute transitions
* @type string
* @default ''
*/
transitions: '',
selected: 0,
/**
* The last page selected. This property is useful to dynamically set transitions based
* on incoming and outgoing pages.
*
* @attribute lastSelected
* @type Object
* @default null
*/
lastSelected: null,
registerCallback: function() {
this.tmeta = document.createElement('core-transition');
},
created: function() {
this._transitions = [];
this.transitioning = [];
},
transitionsChanged: function() {
this._transitions = this.transitions.split(' ');
},
_transitionsChanged: function(old) {
if (this._transitionElements) {
this._transitionElements.forEach(function(t) {
t.teardown(this);
}, this);
}
this._transitionElements = [];
this._transitions.forEach(function(transitionId) {
var t = this.getTransition(transitionId);
if (t) {
this._transitionElements.push(t);
t.setup(this);
}
}, this);
},
getTransition: function(transitionId) {
return this.tmeta.byId(transitionId);
},
selectionSelect: function(e, detail) {
this.updateSelectedItem();
// Wait to call applySelection when we run the transition
},
applyTransition: function(src, dst) {
if (this.animating) {
this.cancelAsync(this.animating);
this.animating = null;
}
Platform.flush();
if (this.transitioning.indexOf(src) === -1) {
this.transitioning.push(src);
}
if (this.transitioning.indexOf(dst) === -1) {
this.transitioning.push(dst);
}
// force src, dst to display
src.setAttribute('animate', '');
dst.setAttribute('animate', '');
//
var options = {
src: src,
dst: dst,
easing: 'cubic-bezier(0.4, 0, 0.2, 1)'
}
// fire an event so clients have a chance to do something when the
// new page becomes visible but before it draws.
this.fire('core-animated-pages-transition-prepare');
//
// prepare transition
this._transitionElements.forEach(function(transition) {
transition.prepare(this, options);
}, this);
//
// force layout!
src.offsetTop;
//
// apply selection
this.applySelection(dst, true);
this.applySelection(src, false);
//
// start transition
this._transitionElements.forEach(function(transition) {
transition.go(this, options);
}, this);
if (!this._transitionElements.length) {
this.complete();
} else {
this.animating = this.async(this.complete.bind(this), null, 5000);
}
},
complete: function() {
if (this.animating) {
this.cancelAsync(this.animating);
this.animating = null;
}
this.transitioning.forEach(function(t) {
t.removeAttribute('animate');
});
this.transitioning = [];
this._transitionElements.forEach(function(transition) {
transition.ensureComplete(this);
}, this);
this.fire('core-animated-pages-transition-end');
},
transitionEnd: function(e) {
if (this.transitioning.length) {
var completed = true;
this._transitionElements.forEach(function(transition) {
if (!transition.completed) {
completed = false;
}
});
if (completed) {
this.job('transitionWatch', function() {
this.complete();
}, 100);
}
}
},
selectedChanged: function(old) {
this.lastSelected = old;
this.super(arguments);
},
selectedItemChanged: function(oldItem) {
this.super(arguments);
if (!oldItem) {
this.applySelection(this.selectedItem, true);
return;
}
if (this.hasAttribute('no-transition') || !this._transitionElements || !this._transitionElements.length) {
this.applySelection(oldItem, false);
this.applySelection(this.selectedItem, true);
return;
}
if (oldItem && this.selectedItem) {
// TODO(sorvell): allow bindings to update first?
var self = this;
Platform.flush();
Platform.endOfMicrotask(function() {
self.applyTransition(oldItem, self.selectedItem);
});
}
}
});
</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
-->
<a href="demos/simple.html">pluggable transitions</a>
<br>
<a href="demos/news.html">icon to top bar</a>
<br>
<a href="demos/music.html">chip to card</a>
<br>
<a href="demos/list.html">list reorder</a>
<br>
<a href="demos/grid.html">grid to full screen</a>
<br>
<a href="demos/nested.html">nested core-animated-pages</a>
<br>
<a href="demos/quiz1.html">quiz: category to splash to question</a>
<br>
<!--
@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>
<script src="../../platform/platform.js"></script>
<link href="../../core-icons/core-icons.html" rel="import">
<link href="../../core-icon-button/core-icon-button.html" rel="import">
<link href="../../core-toolbar/core-toolbar.html" rel="import">
<link href="../core-animated-pages.html" rel="import">
<style>
body {
font-family: sans-serif;
}
.toolbar {
background-color: steelblue;
}
#container {
overflow: auto;
}
.card {
position: relative;
height: 150px;
width: 150px;
font-size: 50px;
margin: 8px;
background-color: tomato;
border-radius: 4px;
cursor: default;
}
.view {
font-size: 250px;
background-color: tomato;
}
</style>
</head>
<body unresolved fullbleed vertical layout>
<template is="auto-binding">
<core-toolbar class="toolbar">
<core-icon-button icon="{{$.pages.selected != 0 ? 'arrow-back' : 'menu'}}" on-tap="{{back}}"></core-icon-button>
<div flex>Stuff</div>
<core-icon-button icon="more-vert"></core-icon-button>
</core-toolbar>
<core-animated-pages id="pages" flex selected="0" on-core-animated-pages-transition-end="{{transitionend}}" transitions="cross-fade-all hero-transition">
<section vertical layout>
<div id="container" flex horizontal wrap around-justified layout hero-p>
<template repeat="{{item in items}}">
<div class="card" vertical center center-justified layout hero-id="item-{{item}}" hero?="{{$.pages.selected === item + 1 || lastSelected === item + 1}}" on-tap="{{selectView}}"><span cross-fade>{{item}}</span></div>
</template>
</div>
</section>
<template repeat="{{item in items}}">
<section vertical layout>
<div class="view" flex vertical center center-justified layout hero-id="item-{{item}}" hero?="{{$.pages.selected === item + 1 || $.pages.selected === 0}}"><span cross-fade>{{item}}</span></div>
</section>
</template>
</core-animated-pages>
</template>
<script>
addEventListener('template-bound', function(e) {
var scope = e.target;
var items = [], count=50;
for (var i=0; i < count; i++) {
items.push(i);
}
scope.items = items;
scope.selectView = function(e) {
var i = e.target.templateInstance.model.item;
this.$.pages.selected = i+1;
}
scope.back = function() {
this.lastSelected = this.$.pages.selected;
console.log(this.lastSelected);
this.$.pages.selected = 0;
}
scope.transitionend = function() {
if (this.lastSelected) {
this.lastSelected = null;
}
}
})
</script>
</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
-->
<!doctype html>
<html>
<head>
<script src="../../platform/platform.js"></script>
<link href="../core-animated-pages.html" rel="import">
<style>
body {
font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
}
</style>
</head>
<body unresolved>
<polymer-element name="list-demo">
<template>
<style>
p {
margin: 8px;
}
.item {
background: #e7e7e7;
padding: 16px;
margin: 8px;
border-radius: 3px;
box-sizing: border-box;
position: relative;
}
</style>
<p>Tap to move to top</p>
<core-animated-pages id="pages" on-tap="{{reorder}}" selected="{{selected}}" on-core-animated-pages-transition-end="{{done}}" transitions="hero-transition">
<section>
<template repeat="{{items}}">
<div hero-id="{{h}}" hero class="item">{{v}}</div>
</template>
</section>
<section>
<template repeat="{{items2}}">
<div hero-id="{{h}}" hero class="item">{{v}}</div>
</template>
</section>
</core-animated-pages>
</template>
<script>
Polymer('list-demo', {
selected: 0,
items: [
{h: 'matt', v: 'Matt McNulty'},
{h: 'scott', v: 'Scott Miles'},
{h: 'steve', v: 'Steve Orvell'},
{h: 'frankie', v: 'Frankie Fu'},
{h: 'daniel', v: 'Daniel Freedman'},
{h: 'yvonne', v: 'Yvonne Yip'},
],
items2: [
{h: 'matt', v: 'Matt McNulty'},
{h: 'scott', v: 'Scott Miles'},
{h: 'steve', v: 'Steve Orvell'},
{h: 'frankie', v: 'Frankie Fu'},
{h: 'daniel', v: 'Daniel Freedman'},
{h: 'yvonne', v: 'Yvonne Yip'},
],
reorder: function(e) {
if (this.$.pages.transitioning.length) {
return;
}
this.lastMoved = e.target;
this.lastMoved.style.zIndex = 10005;
var item = e.target.templateInstance.model;
var items = this.selected ? this.items : this.items2;
var i = this.selected ? this.items2.indexOf(item) : this.items.indexOf(item);
if (i != 0) {
items.splice(0, 0, item);
items.splice(i + 1, 1);
}
this.lastIndex = i;
this.selected = this.selected ? 0 : 1;
},
done: function() {
var i = this.lastIndex;
var items = this.selected ? this.items : this.items2;
var item = items[i];
items.splice(0, 0, item);
items.splice(i + 1, 1);
this.lastMoved.style.zIndex = null;
}
});
</script>
</polymer-element>
<list-demo></list-demo>
</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
-->
<!doctype html>
<html>
<head>
<title>core-animated-pages</title>
<script src="../../platform/platform.js"></script>
<link href="../core-animated-pages.html" rel="import">
<style>
body {
font-family: 'Roboto 2', 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
background: #f1f1f1;
}
.green {
position: absolute;
top: 0;
right: 0;
left: 0;
height: 350px;
background: #70c26f;
}
</style>
</head>
<body>
<polymer-element name="music-demo">
<template>
<style>
.chip-container {
position: absolute;
top: 275px;
right: 0;
left: 0;
text-align: center;
}
.chip {
display: inline-block;
position: relative;
border-radius: 3px;
margin: 4px;
overflow: hidden;
text-align: start;
background-color: #fff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16);
}
.chip-top {
width: 200px;
height: 200px;
}
.chip-bottom {
padding: 8px;
line-height: 1.5;
}
.chip-album-title {
font-weight: bold;
}
#details {
padding: 200px 10% 0;
}
.card {
height: 400px;
border-radius: 3px;
text-align: start;
overflow: hidden;
background: #fff;
box-shadow: 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.card-left {
width: 400px;
}
.card-right {
padding: 24px;
}
.card-icon {
border-radius: 50%;
width: 60px;
height: 60px;
margin-right: 16px;
}
.card-album-title {
font-size: 2em;
}
</style>
<core-animated-pages selected="{{page}}" transitions="hero-transition" on-core-animated-pages-transition-end="{{complete}}">
<section>
<div class="chip-container" hero-p on-tap="{{transition}}">
<template repeat="{{items as item}}">
<div class="chip" hero-id="{{item.artist}}-{{item.album}}" hero?="{{selectedAlbum === item }}">
<div class="chip-top" style="background:{{item.color}};" hero-id="{{item.artist}}-{{item.album}}-art" hero?="{{selectedAlbum === item}}"></div>
<div class="chip-bottom">
<div class="chip-album-title">{{item.album}}</div>
<div class="chip-artist">{{item.artist}}</div>
</div>
</div>
</template>
</div>
</section>
<section id="details">
<div class="card" layout horizontal hero-id="{{selectedAlbum.artist}}-{{selectedAlbum.album}}" hero on-tap="{{transition}}">
<div class="card-left" style="background:{{selectedAlbum.color}};" hero-id="{{selectedAlbum.artist}}-{{selectedAlbum.album}}-art" hero></div>
<div class="card-right" flex>
<div layout horizontal center>
<div>
<div class="card-icon" style="background:{{selectedAlbum.color}};"></div>
</div>
<div flex>
<div class="card-album-title">{{selectedAlbum.album}}</div>
<div class="card-album-artist">{{selectedAlbum.artist}}</div>
</div>
</div>
</div>
</div>
</section>
</core-animated-pages>
</template>
<script>
Polymer('music-demo', {
page: 0,
items: [
{ artist: 'Tycho', album: 'Fragments', color: '#f4db33' },
{ artist: 'Tycho', album: 'Past Prologue', color: '#972ff8' },
{ artist: 'Tycho', album: 'Spectre', color: '#7dd6fe' },
{ artist: 'Tycho', album: 'Awake', color: '#dc3c84' }
],
selectedAlbum: null,
transition: function(e) {
if (this.page === 0 && e.target.templateInstance.model.item) {
this.selectedAlbum = e.target.templateInstance.model.item;
this.page = 1;
} else {
this.page = 0;
}
}
});
</script>
</polymer-element>
<div class="green"></div>
<music-demo></music-demo>
</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
-->
<link href="../../core-icons/core-icons.html" rel="import">
<link href="../../core-icon-button/core-icon-button.html" rel="import">
<link href="../core-animated-pages.html" rel="import">
<polymer-element name="nested-animated-pages">
<template>
<style>
:host {
display: block;
position: relative;
}
core-animated-pages {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.tall-toolbar {
box-sizing: border-box;
height: 240px;
}
.tall-toolbar.colored {
fill: #fff;
color: #fff;
}
.tall-toolbar [flex] {
font-size: 1.5em;
}
core-icon-button {
margin: 16px;
}
.body {
background-color: #f1f1f1;
}
.square {
position: absolute;
width: 150px;
height: 150px;
left: 16px;
top: 175px;
}
</style>
<core-animated-pages id="pages" selected="{{page}}" selectedItem="{{selectedItem}}" transitions="hero-transition" no-transition?="{{noTransition}}">
<section id="page1" cross-fade>
<div class="tall-toolbar colored" style="background-color:orange;" layout vertical hero-id="thing" hero?="{{page === 0 || !noTransition}}">
<div layout horizontal center>
<core-icon-button icon="clear" on-tap="{{back}}"></core-icon-button>
<div flex>One</div>
<core-icon-button icon="arrow-forward" on-tap="{{transition}}"></core-icon-button>
</div>
<div flex></div>
</div>
<div flex class="body"></div>
</section>
<section layout vertical id="page2" cross-fade>
<div class="tall-toolbar" layout vertical>
<div layout horizontal center>
<core-icon-button icon="clear" on-tap="{{back}}"></core-icon-button>
<div flex>Two</div>
<core-icon-button icon="arrow-forward" on-tap="{{transition}}"></core-icon-button>
</div>
<div flex></div>
</div>
<div flex class="body"></div>
<div class="square" style="background-color:orange;" hero-id="thing" hero?="{{page === 1 || !noTransition}}"></div>
</section>
</core-animated-pages>
</template>
<script>
Polymer({
publish: {
page: {value: 0}
},
selectedItem: null,
noTransition: true,
back: function() {
this.noTransition = true;
this.fire('nested-back');
},
transition: function() {
this.noTransition = false;
this.page = this.page === 0 ? 1 : 0;
}
});
</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
-->
<!doctype html>
<html>
<head>
<title>core-animated-pages</title>
<script src="../../platform/platform.js"></script>
<link href="nested-animated-pages.html" rel="import">
<style>
body {
font-family: 'Roboto 2', 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
background: #f1f1f1;
}
nested-demo {
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
</style>
</head>
<body>
<polymer-element name="nested-demo">
<template>
<style>
core-animated-pages {
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
section {
text-align: center;
padding-top: 250px;
}
.square {
display: inline-block;
margin: 8px;
padding: 8px;
width: 200px;
height: 200px;
background-color: orange;
color: #fff;
}
</style>
<core-animated-pages selected="{{page}}" transitions="hero-transition cross-fade">
<section on-tap="{{transition}}" layout horizontal center-justified>
<div class="square" id="thing1" hero-id="thing" hero?="{{subpage === 0}}" cross-fade?="{{subpage !== 0}}">thing 1</div>
<div class="square" id="thing2" hero-id="thing" hero?="{{subpage === 1}}" cross-fade?="{{subpage !== 1}}">thing 2</div>
</section>
<nested-animated-pages page="{{subpage}}" on-nested-back="{{back}}"></nested-animated-pages>
</core-animated-pages>
</template>
<script>
Polymer('nested-demo', {
page: 0,
subpage: 0,
transition: function(e) {
var el = e.target;
if (el.id === "thing1") {
this.subpage = 0;
} else {
this.subpage = 1;
}
setTimeout(function() {
this.page = 1;
}.bind(this), 200);
},
back: function() {
this.page = 0;
}
});
</script>
</polymer-element>
<nested-demo></nested-demo>
</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
-->
<!doctype html>
<html>
<head>
<script src="../../platform/platform.js"></script>
<link href="../../core-icons/core-icons.html" rel="import">
<link href="../../core-icons/social-icons.html" rel="import">
<link href="../../core-toolbar/core-toolbar.html" rel="import">
<link href="../../paper-shadow/paper-shadow.html" rel="import">
<link href="../core-animated-pages.html" rel="import">
<style shim-shadowdom>
body {
font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
}
.fit {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 420px;
}
.toolbar {
background: #8d3efc;
/* FIXME */
color: #fff !important;
fill: #fff;
}
.toolbar-2 {
position: absolute;
top: 0;
left: 0;
background: #000;
color: #fff;
text-align: center;
font-size: 48px;
}
body /deep/ .toolbar-2 {
position: absolute;
top: 0;
left: 0;
margin: 0;
width: 420px;
background: #000;
color: #fff;
text-align: center;
font-size: 48px;
}
.container {
background-color: #e7e7e7;
padding: 16px;
}
.card {
position: relative;
background-color: #fff;
border-radius: 2px;
}
.card-top {
background: #f2da2f;
height: 240px;
}
.card-top-2 {
background: #99f8b7;
height: 240px;
}
.card-bottom {
padding: 24px;
}
.headline {
font-size: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.icon {
position: relative;
background: #000;
color: #fff;
width: 40px;
height: 40px;
border-radius: 50%;
}
.icon::after {
content: 'T';
font-size: 24px;
position: absolute;
top: 7px;
left: 13px;
}
.source-container {
margin-top: 16px;
}
.two-lines {
margin-left: 16px;
}
.source {
font-size: 14px;
}
.time {
color: rgba(0, 0, 0, 0.54);
font-size: 12px;
}
.tiles-container {
margin-top: 16px;
}
.tile {
position: relative;
display: inline-block;
width: 85px;
height: 85px;
background: #fff;
border-radius: 2px;
}
</style>
</head>
<body unresolved>
<polymer-element name="shadow-div" noscript>
<template>
<style>
:host {
display: block;
}
</style>
<paper-shadow target="{{}}" z="1"></paper-shadow>
<content></content>
</template>
</polymer-element>
<core-animated-pages class="fit" selected="0" transitions="cross-fade-all hero-transition">
<section id="first">
<core-toolbar class="tall toolbar">
<core-icon icon="menu"></core-icon>
<div flex>Highlights</div>
<core-icon icon="social:share"></core-icon>
<core-icon icon="bookmark"></core-icon>
<core-icon icon="more-vert"></core-icon>
</core-toolbar>
<div class="container" hero-p>
<shadow-div class="card" hero-p onclick="stuff()">
<div class="card-top"></div>
<div class="card-bottom" hero-p>
<div class="headline">Google's Craziest Offices</div>
<div class="source-container" hero-p layout horizontal center>
<div class="icon" hero-id="icon-header" hero></div>
<div class="two-lines">
<div class="source">The New York Times</div>
<div class="time">36 minutes ago</div>
</div>
</div>
</div>
</shadow-div>
<div class="tiles-container" layout horizontal justified>
<shadow-div class="tile"></shadow-div>
<shadow-div class="tile"></shadow-div>
<shadow-div class="tile"></shadow-div>
<shadow-div class="tile"></shadow-div>
</div>
</div>
</section>
<section id="second">
<core-toolbar class="tall" hero-p>
<core-toolbar class="tall toolbar-2" hero-id="icon-header" hero>
<div flex class="middle">T</div>
</core-toolbar>
</core-toolbar>
<div class="container">
<shadow-div class="card" onclick="stuff()">
<div class="card-top-2"></div>
<div class="card-bottom">
<div class="headline">Some long overflowing headline</div>
<div class="source-container" layout horizontal center>
<div class="icon" style="background:red;"></div>
<div class="two-lines">
<div class="source">The New York Times</div>
<div class="time">36 minutes ago</div>
</div>
</div>
</div>
</shadow-div>
<div class="tiles-container" layout horizontal justified>
<shadow-div class="tile"></shadow-div>
<shadow-div class="tile"></shadow-div>
<shadow-div class="tile"></shadow-div>
<shadow-div class="tile"></shadow-div>
</div>
</div>
</section>
</core-animated-pages>
<script>
function stuff(e) {
var p = document.querySelector('core-animated-pages');
p.selected = p.selected ? 0 : 1;
}
</script>
</body>
</html>
�PNG

IHDR��Y�
AiCCPICC ProfileH ��wTS��Ͻ7��" %�z �;HQ�I�P��&vDF)VdT�G�"cE ��b� �P��QDE�݌k �5�ޚ��Y�����g�}׺P��tX�4�X���\���X��ffG�D��=���HƳ��.�d��,�P&s���"7C$
E�6<~&��S��2����)2�12� ��"�įl���+�ɘ�&�Y��4���Pޚ%ᣌ�\�%�g�|e�TI���(���L0�_��&�l�2E����9�r��9h�x�g��Ib�טi���f��S�b1+��M�xL��� �0��o�E%Ym�h����Y��h���~S�=�z�U�&�ϞA��Y�l�/��$Z����U�m@��O� ��ޜ��l^��� ' ���ls�k.+�7�oʿ�9�����V;�?�#I3eE妧�KD�� ��d�����9i���,�����UQ� ��h��<�X�.d
���6'~�khu_}�9P�I�o=C#$n?z}�[1
Ⱦ�h���s�2z��� \�n�LA"S�� �dr%�,�߄l��t�
4�.0,` �3p� ��H�.Hi@�A>�
A1�v�jpԁz�N�6p\W� p �G@
��K0ށi���A����B�ZyCAP8�C���@��&�*���CP=�#t�]��� 4�}���a ���ٰ;G���Dx����J�>����,�_“@��FX�DB�X$!k�"��E�����H�q���a���Y��bVa�bJ0՘c�VL�6f3��bձ�X'�?v 6��-�V`�`[����a�;���p~�\2n5��׌���� �&�x�*���s�b|!�
ߏƿ'� Zk�!� $l$T���4Q��Ot"�y�\b)���A�I&N�I�$R$)���TIj"]&=&�!��:dGrY@^O�$� _%�?P�(&OJEB�N9J�@y@yC�R �n�X����ZO�D}J}/G�3���ɭ���k��{%O�חw�_.�'_!J���Q�@�S���V�F��=�IE���b�b�b�b��5�Q%�����O�@��%�!BӥyҸ�M�:�e�0G7��ӓ����� e%e[�(����R�0`�3R��������4�����6�i^��)��*n*|�"�f����LUo�՝�m�O�0j&jaj�j��.��ϧ�w�ϝ_4���갺�z��j���=���U�4�5�n�ɚ��4ǴhZ �Z�Z�^0����Tf%��9����-�>�ݫ=�c��Xg�N��]�.[7A�\�SwBOK/X/_�Q�>Q�����G�[��� �`�A�������a�a��c#����*�Z�;�8c�q��>�[&���I�I��MS���T`�ϴ� k�h&4�5�Ǣ��YY�F֠9�<�|�y��+ =�X���_,�,S-�,Y)YXm�����Ěk]c}džj�c�Φ�浭�-�v��};�]���N����"�&�1=�x����tv(��}�������'{'��I�ߝY�)� Σ ��-r�q�r�.d.�_xp��Uە�Z���M׍�v�m���=���+K�G�ǔ���� ^���W�W����b�j�>:>�>�>�v��}/�a��v���������O8� �
�FV> 2 u�����/�_$\�B�Cv�< 5 ]�s.,4�&�y�Ux~xw-bEDCĻH����G��KwF�G�E�GME{E�EK�X,Y��F�Z� �={$vr����K����
��.3\����r���Ϯ�_�Yq*���©�L��_�w�ד�����+��]�e������D��]�cI�II�OA��u�_�䩔���)3�ѩ�i����B%a��+]3='�/�4�0C��i��U�@ёL(sYf����L�H�$�%�Y �j��gGe��Q�����n�����~5f5wug�v����5�k��֮\۹Nw]������m mH���Fˍe�n���Q�Q��`h����B�BQ�-�[l�ll��f��jۗ"^��b���O%ܒ��Y}W�����?���w�vw����X�bY^�Ю�]�����W�Va[q`i�d��2���J�jGէ������{�����׿�m���>���Pk�Am�a�����꺿g_D�H��G�G��u�;��7�7�6�Ʊ�q�o���C{��P3���8!9����� <�y�}��'����Z�Z���։��6i{L{��ӝ�-?��|������gKϑ���9�w~�Bƅ��:Wt>���ҝ����ˁ��^�r�۽��U��g�9];}�}�������_�~i��m��p��㭎�}��]�/���}������.�{�^�=�}����^?�z8�h�c��'
O*��?�����f�����`ϳ�g���C/���O�ϩ�+F�F�G�Gό��z����ˌ��ㅿ)����ѫ�~w�gb���k��?Jި�9���m�d���wi獵�ޫ�?����c�Ǒ��O�O���?w| ��x&mf������2:Y~ pHYs%%IR$��iTXtXML:com.adobe.xmp<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.4.0">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:tiff="http://ns.adobe.com/tiff/1.0/">
<xmp:CreatorTool>Adobe ImageReady</xmp:CreatorTool>
<tiff:Orientation>1</tiff:Orientation>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
).�=�IDATx�Y��y�k���r�{qi�KQ$%R�%Y�aDW+��v$B�� �9��$/A`@ �@��1�<$
�%pL[�%;�D��I��R�������N�?=5�M�LO�LUOO?������~U����c
��׋��H �@Ol.3I�J(vH@�BI�EH�Ba �(��X�(�H@�/A����unQ�9{QM��HݫN�d�;�@�����w���s�<~E�xX�Y�����H� 8��3 j���ԣZ �Ѕ$2 �p"�9����H hfeK`v��R��X ��qbrH���V��YjK(�7���kG�<����:I���Ւ��U�D��Ȱ�vd��Pښ��Hx�^�Υp �,�����H����E�%������ѥ#�)��@�R �%{g�K�5#�:R �wϩu�uLq �K �P�~8\� 4 �J(��ΣI��4�TB�?4 V�H%��˧��v�@b�����+����H,������0��&�X(AS`�H� 
� f�P(�$��������>@ P( � P(�$��������>@ P( � P(�$��������>@ P( � P(�$��������>@ P( � P(�$��������>@ P( � P(�$��@⟦[*���\ޟ�$��@� |k�E�A$J�PP�/�v��H��B���_K�r@(���U�G�B�ǖ�"@�Ԙ��?�?��
%��dU��P��P(5&����--D�B �1Y(li9 J@�ɪ�#@��cK��PjLV�
�[Z��Pc�*�P(���r@(���U�G�B�ǖ�"@�Ԙ��?�?��
%��dU��P��P(5&����--D�B �1Y(li9 ��=ܷ��'�0���*!xC=�z<�8�Ic��PBmY��)
�)N ��j˲^N P(Nq�X�(�P[��rJ�Bq���B%@��ڲ��S�S�4*
%Ԗe���P�⤱P P(��,����'��J�B �eY/�(�8i,TJ�-�z9%@�8�Ic��PBmY��)
�)N ��j˲^N P(Nq�X�(�P[��rJ�Bq���B%@��ڲ��S�S�4*
%Ԗe���P�⤱P P(��,����'��J�B �eY/�(�8i,TJ�-�z9%@�8�Ic��PBmY��)
�)N ��j˲^N P(Nq�X�(�P[��rJ ��g/��g.�w��H��o ���tb� ���n��i��p+��-D�B �1Y(li9 J@�ɪ�#@��cK��PjLV�
�[Z��Pc�*�P(���r@(���U�G�B�ǖ�"@�Ԙ��?�?��
%��dU��P��P(5&����--D�B �1Y(li9 J@�ɪ�#@��cK��PjLV�
�[Z��Pc�*�P(���r@(���U�G �+U Ţz�Hh�rL �Pz���G���04�xC=T]q�ġ��4>
%�6f �P@��|��r��) v��W�ܧ��]����d����oHB��^zT�0��h�2Jjd�!oN]V����j��Rh���'��#��, �˙-j��"���-:�G�Hi0+��ZE���B�dժ����'v�?{�ZX�ksr��@�B����H���)����fՋs``��涶Q(m���Y�@�����kk��JT.M!
% -�͔�X�<�#�@Lp�'�͢�O
�JrAS����{��6<����G{2W�@-#���nlz�Q��ʵuC�+7:�B�8�H� ���3�����&����m�:��l�Bq�����|�ُ7����8��+�>�O��B�����N�WG���w� ^��N]]�S�E��:9���R��*݆;o���$���ˋ~� ���6L&-����Y�;8�>�Tl^h�v������HM`������e�-�~��)���4�h�����m��lg
�!�����cex�G��7�,��3��#�w�t����в���l��B�I��lp�����=�����O��T����&�#����B�G�ۺ�@VG��P��K0H���1����)���{�BQ�ٔi�J����,/�l5�t��~��M�(��sM`M߲ڲ1ۣ �P(����� �!=�3��`��bY����Q���iQ�*dz/�P$ .��ؚ%������B��|9�c�yN����(�<�� c�_�{�m;Uy`����?W\�J�U�w�Z>O淏-� �;s/��B�4V�2^��4��K��ڞ���Y�P}�����c7�#���m�\O����Ν����bY����֟ڽQ�����P� ����oT�F���I��P:E>O~�]�M4���j�D>�&�$>G�;q907��B����3�^��u�<�dM<o�J'��4m5G&֩_̩HP
%m��V���;^��5�����X9NJ�'����g⦑��W��D���l�Pr�
��'��"� O�;�?s����.v���$yn�6�P$�ն|��xjzL=<S�و���)��XP��/d^�i��qv�H�Bɼ���!���3 ���jf���F HJ�]%G�N��]0���O��W�N���]wɗ��s��S��UOܵ!�� ����h7��l���HGF���w���' J�����a���cjߖ�يk&
%�N�y8��z�[�
�=��]�3��o��c�B�%�MO��F�#wv��v�G��g�g�GW�)�{�O�Y�|���E�)��ƻ�;�e%䣈lV
E�}y�����s�{fpm$ܣ��E�H!/�v��ѤPP[��KC��q�u�Pl"!�c��� $����޷c��/���J+Ժm��?k+����ΩU)�B1$B�|�R 7[�� {��wM�J+Ժe �><�.Z�ι�!�o��>���(�HH믾��6�k��m�#��O�&�g5�PBm�W^h� �15�F�޴�G�&�Bi�+�qa�Ƶ����n__��X;��L ����Z_�+��J]��=̕/t���RE�e�R�kjp�yL�պ���6�_s�n�F�0`N�~J����J�٧�~֡��h��Wj�JVi���oL�;��6nVj��3���}�R�&W����S����}��;���/���Y��뎇�����2q��6 ~H���M!v�������JKm/�ů'z ǁ���ɗl���o�D7�Ģ��v������%0Y��X_�"0�KKJ]��K�<|��Pf����v|�~^c�ͥn�ck�&G���R���M3�:3JXߡ� ��Gڸ��;��z\|FsǥF����Hȇx�����n�7l���dl�}���wlqmb�����`�����?�8�&H�������"�R���wY{0֔cl���ٳQ]�7Ԏ��cU�?��#�f=>��`8t��?U:w���1:��L°���~[����S�Rj�z4��Fi��w�c������36�&�nD�,�'E0�����2:�~�l�C"ps������s�1�I8�1[��,E���J]8o�"����$���\���CU��j�� &}���y=�Y~'c��]n>c�����6?��R��̛��kWk��'�8��_d �]&9d�ɻLv��K2W)�v�o�T&�v��>c�c���|��q\���L��f\���:F2�6��vb���ԚP�����?��3%���.�8&a(#�3X�'`�z*�4-�6�M��:�n2uԷ�'b�ۤ�kdDRX�IrAI��lL��6��@����n3;�Yl�w��0#ېQxH�M��_�J ��=L�7� mL�P9�HS�A�c`�:�=9d�v�� vE�a�$��w�w�c��%�mv�6�zG4\�/�M�я���$��酂!�<�T}r�rC��u1�IX��d1�@�Y� z��WO��3`H����Tm�i`�c�1f�:S;D3�~81�7 ߘM���k�y��7�nn3����N(��+�r*�>�x[�̌�)�40:�w�aכ�S�()��O�h�7��q�1���)�|\�1�Ȩ����f����nl>}�9�fmV�iN�� �N�Q��紞�X�c;S�v���f��������̞̗˨kZ[i�Kr�����dl��8�L'���n1�IN�a
Sy&�S�+����V� [��o��}���S�����q\ڍ�����K�c����s?�z=��~���������S�؎|������fJ������T�=t�,V����4b��;ϱ�i`\���\�z����$�p-�tC��ah$��@�Y��=k��[���v&:s��� rL�| �̰O56�2���Dz킾���d`Hf�Mu�¥yU����N�OЕ|/G�C��U�2n�R�K�TA�ߋ��ASHǽ��k��m�d�Rz� �h��ne�*�duڬ[��������2֧��5S��o��C�Nf��&(#�����ss�#%��7tG4��('���<~�蘚�0]7�υ#������k r�����ũo�h��&���c�v~�6�� ��� � ���U��j��4�U�$���]�گ���l�G
�p_�L��M�2�|@4"AL�[ؤ9�F$�f�G�|i�l�ԧK��6��H��W&;�y-b��|�M�]ژ����L��&}�.�L2�%MlׯKKΖ eb�_�n.��հu��ө�AӒ2�icۖ�.�J�X�2ٱٱ�X?�&������l[��f��t�� q���X����ņ;3dr��R�|?�Ȍ:���+�`ē����C�s���|�QVS�x���̭-��z�[�:����ܧ�N��cs C�|��N<�����6l��Ȼ����9�q��:��۷^l���� �r��w쩽����a$�B�|��Rŝ����Jm��8N������ׯ�/~�|.�8�8s���E�_�W�[�‰cj����> �!����/ܵV� Z�(?��U��Խ����� �� ВP�
�|c�z �s�õ;a��嬗,�ȗ�2����bC̈��Ԉ �#?�7b�k�Y�dڬQ>|v*�f��է�m�N��c\����6�/���R{����u��q·�.,E ���W{�iG</_-�Ɩ����Y;)`�t�Yl脧NF�a6��7��iop�5 3�.�fD����u$۷}�F�>�at�&��>��w�ck�����g�#
�~~״��o�w�s�r��G̅����@�e$�z��%�r;�Yl��(�� ��E^�2��$�b��۶-��۾&!����ؚq1<}�$���߹W}���jð���|�\�^vY� k,�s�f{'>��fǺ���Y��˨[Z.>}�9���\?1��jA�9��O�TOݯ�1��m&jh46��!�ͫ�0�˄��>.|�k�L���ņXQ'$ �P^&�׌��al��Ώ��l.X7����o�������8eBY�v�����Ql�m^���l.��S]Gi��k?���J��J���l�v;z�֯}vB���M�o�F����@[C/Y��Hk����գ;e�I�� ��nV�/�s�X���������WsG�G�b�+����L+�q���s�'��6s�#��U�^9��ܾ�v��������ǵ�p�? _������B+\��-����6����$I��ņ����g�1KW�K;��)m������%mDE� H�G��O��2Jf{u��^,lS���[fS��-���{�K���QW}���Z�RY//DQv\�_S�&��/��&�N���R�]Y(տv߲���J���jM��c��j��J%Cڋ��}�T�R�Q,����ji=�+U� �P����xL$�-���V:�X��� �'5�r$��� ���F˦F0�!�cOW}��&�!�نc�E���5_�k���;ՔC�Jve��s�r5�v���v�"�5].ml�l�^�Uc�f�dU�DŅ�z��mQF%������|t�q�D�F����z5�^U�|�|�GF��[�1HƔ�@����U�$����%-L�B �qY5w(w,i)`J��˪�#@��cIK�Pn\V�
�KZ
��p�j�P(�X�R�(���UsG�Bqǒ�&@�ܸ��;�;��0
%��e���Pܱ��� �
�l>�Q�MȪeA x�<z�%��;�V��ܳY�@ ��Q`׌!�_8z�d�|~��ϩ�k�>׬C��E��4"�����'5t���OHD 8�@_�C-s�)l��+�M���%�"�����o�V<ɏ��<I ������o7���`YT�!��8A�G��Ksqu]�g�����En �2�����w����/:}+ �}鿢��C����g��#
���oϨVE"�b��&.�@�@�
͑�R�6�|�/L��0�ݻr�U���2�ʼ0�hv:�CB�{���ݣ��1�h߱��د�~��m���w��֍�h/I2���z-�,���j&"A�Ο+���cA]���ϴ� t�����Kjfw_�Y�-.��,��FM7�Y1%�5�MP�܇�jfO�(���H�k��q�O�/IZXX*+��%������,�`~���tc6���/������V��n&���uY �#@$K ����6��`�&�@�k�Q�ºysQ-/a�M�����][���dN �#
(�Yl�2�$t�����>t�/�IEND�B`�
<!--
@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>core-animated-pages</title>
<script src="../../platform/platform.js"></script>
<link href="../../core-icons/av-icons.html" rel="import">
<link href="../../paper-fab/paper-fab.html" rel="import">
<link href="../core-animated-pages.html" rel="import">
<link href="../transitions/slide-up.html" rel="import">
<link href="../transitions/list-cascade.html" rel="import">
<style>
body {
font-family: 'Roboto 2', 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
background: #f1f1f1;
}
quiz-demo {
display: block;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
</style>
</head>
<body>
<polymer-element name="quiz-demo">
<template>
<style>
core-animated-pages {
height: 100%;
}
section {
overflow: hidden;
}
.fab {
position: absolute;
fill: #fff;
}
.fab-0 {
bottom: 50px;
right: 24px;
}
.fab-1 {
top: 210px;
right: 24px;
}
paper-fab {
background-color: #ff4081;
}
.top {
background-color: #ffff8d;
}
.top-image {
background: url(quiz1-intro.png);
height: 287px;
width: 202px;
}
.bottom {
box-sizing: border-box;
position: relative;
height: 80px;
background-color: #ffeb3b;
padding: 24px;
color: #fff;
font-size: 32px;
}
.tall-toolbar {
box-sizing: border-box;
height: 240px;
position: relative;
color: #fff;
padding: 48px;
font-size: 48px;
}
.tall-toolbar.categories {
background-color: #00bbd3;
margin-bottom: 2px;
}
.tall-toolbar.questions {
background-color: #ffeb3b;
}
.middle {
background-color: #fafafa;
color: #3f3f3f;
padding: 24px 48px;
font-size: 24px;
line-height: 1.5;
}
.footer {
height: 80px;
}
.avatar {
height: 80px;
width: 80px;
background-color: #ff80ab;
}
.footer-right, .score {
border-top: 1px solid #ccc;
background-color: #fff;
padding: 30px;
}
.tile {
box-sizing: border-box;
float: left;
height: 200px;
width: 49%;
margin: 3px;
}
.tile-bottom {
padding: 8px;
color: #fff;
}
</style>
<core-animated-pages selected="{{page}}" transitions="hero-transition slide-up slide-down cross-fade list-cascade" on-core-animated-pages-transition-end="{{complete}}">
<section layout vertical>
<div class="tall-toolbar categories" slide-down>
<span>Your name here</span>
</div>
<div class="tiles-container">
<div class="tile" style="background-color:#ccc;" layout vertical>
<div class="tile-top" flex></div>
<div class="tile-bottom" style="background-color:#aaa;">
Leaderboard
</div>
</div>
<div class="tile" hero-id="category-image" hero style="background-color:#ffff8d;" layout vertical on-tap="{{transition}}">
<div class="tile-top" flex></div>
<div class="tile-bottom" hero-id="footer" hero style="background-color:#ffeb3b;">
General Knowledge
</div>
</div>
<div class="tile" style="background-color:#b9f6ca;" layout vertical>
<div class="tile-top" flex></div>
<div class="tile-bottom" style="background-color:#0f9d58;">
Category 2
</div>
</div>
<div class="tile" style="background-color:#ff8a80;" layout vertical>
<div class="tile-top" flex></div>
<div class="tile-bottom" style="background-color:#db4437;">
Category 3
</div>
</div>
<div class="tile" style="background-color:#82b1ff;" layout vertical>
<div class="tile-top" flex></div>
<div class="tile-bottom" style="background-color:#4285f4;">
Category 4
</div>
</div>
<div class="tile" style="background-color:#b388ff;" layout vertical>
<div class="tile-top" flex></div>
<div class="tile-bottom" style="background-color:#7e57c2;">
Category 5
</div>
</div>
</div>
</section>
<section layout vertical>
<div class="top" hero-id="category-image" hero flex layout horizontal center center-justified>
<div class="top-image" cross-fade></div>
</div>
<div class="bottom" hero-id="footer" hero cross-fade>
<span cross-fade>General Knowledge</span>
</div>
<div class="fab fab-0" hero-id="fab" hero>
<paper-fab icon="av:play-arrow" on-tap="{{transition}}" hero></paper-fab>
</div>
</section>
<section layout vertical>
<div class="tall-toolbar questions" hero-id="footer" hero>
<span cross-fade>Question here</span>
</div>
<div class="fab fab-1" hero-id="fab" hero>
<paper-fab icon="av:play-arrow" on-tap="{{transition}}" hero></paper-fab>
</div>
<div flex class="middle" slide-up list-cascade>
<p>Option 1</p>
<p>Option 2</p>
<p>Option 3</p>
<p>Option 4</p>
<p>Option 5</p>
</div>
<div class="footer" layout horizontal slide-up>
<div class="avatar"></div>
<div class="footer-right" flex>
some text here
</div>
<div class="score">
32 pts
</div>
</div>
</section>
</core-animated-pages>
</template>
<script>
Polymer('quiz-demo', {
page: 0,
transition: function(e) {
if (this.page === 2) {
this.page = 0;
} else {
this.page += 1;
}
}
});
</script>
</polymer-element>
<quiz-demo></quiz-demo>
</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
-->
<!doctype html>
<html>
<head>
<script src="../../platform/platform.js"></script>
<link href="../../core-icons/core-icons.html" rel="import">
<link href="../../core-icon-button/core-icon-button.html" rel="import">
<link href="../../core-toolbar/core-toolbar.html" rel="import">
<link href="../core-animated-pages.html" rel="import">
<style>
body {
font-family: sans-serif;
}
.toolbar {
background-color: steelblue;
}
</style>
</head>
<body unresolved fullbleed vertical layout>
<polymer-element name="grid-toc" attributes="items selected">
<template>
<style>
#container {
overflow: auto;
}
.card {
position: relative;
height: 150px;
width: 150px;
font-size: 50px;
margin: 8px;
background-color: tomato;
border-radius: 4px;
cursor: default;
}
</style>
<div id="container" on-tap="{{selectView}}" flex horizontal wrap around-justified layout hero-p>
<template repeat="{{item in items}}">
<div class="card" vertical center center-justified layout hero-id="item-{{item}}" hero?="{{selected === item + 1 || lastSelected === item + 1}}"><span cross-fade>{{item}}</span></div>
</template>
</div>
</template>
<script>
Polymer('grid-toc', {
selectedChanged: function(old) {
this.lastSelected = old;
},
selectView: function(e) {
var item = e.target.templateInstance.model.item;
if (item !== undefined) {
this.fire('grid-toc-select', {item: item});
}
}
});
</script>
</polymer-element>
<polymer-element name="grid-item" attributes="item isHero">
<template>
<style>
.view {
font-size: 250px;
background-color: tomato;
}
</style>
<div class="view" flex vertical center center-justified layout hero-id="item-{{item}}" hero?="{{isHero}}">
<span cross-fade>{{item}}</span>
</div>
</template>
<script>
Polymer('grid-item', {
isSelected: false
})
</script>
</polymer-element>
<template is="auto-binding">
<core-toolbar class="toolbar">
<core-icon-button icon="{{$.pages.selected != 0 ? 'arrow-back' : 'menu'}}" on-tap="{{back}}"></core-icon-button>
<div flex>Stuff</div>
<core-icon-button icon="more-vert"></core-icon-button>
</core-toolbar>
<core-animated-pages id="pages" flex selected="0" on-core-animated-pages-transition-end="{{transitionend}}" transitions="cross-fade-all hero-transition">
<grid-toc vertical id="toc" layout selected="{{$.pages.selected}}" items="{{items}}" hero-p on-grid-toc-select="{{selectView}}"></grid-toc>
<template repeat="{{item in items}}">
<grid-item vertical layout item="{{item}}" hero-p isHero="{{$.pages.selected === item + 1 || $.pages.selected === 0}}"></grid-item>
</template>
</core-animated-pages>
</template>
<script>
addEventListener('template-bound', function(e) {
var scope = e.target;
var items = [], count=50;
for (var i=0; i < count; i++) {
items.push(i);
}
scope.items = items;
scope.selectView = function(e, detail) {
var i = detail.item;
this.$.pages.selected = i+1;
}
scope.back = function() {
this.lastSelected = this.$.pages.selected;
this.$.pages.selected = 0;
}
scope.transitionend = function() {
if (this.lastSelected) {
this.lastSelected = null;
}
}
})
</script>
</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
-->
<!doctype html>
<html>
<head>
<script src="../../platform/platform.js"></script>
<link href="../core-animated-pages.html" rel="import">
<link href="../transitions/cross-fade.html" rel="import">
<link href="../transitions/slide-from-right.html" rel="import">
<style>
body {
font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
}
core-animated-pages {
position: absolute;
top: 50px;
right: 0;
bottom: 0;
left: 0;
font-size: 72px;
overflow: hidden;
}
section > div {
height: 100%;
color: white;
}
</style>
</head>
<body unresolved>
<select onchange="change();">
<option value="cross-fade-all" selected>cross-fade-all</option>
<option value="slide-from-right">slide-from-right</option>
</select>
<core-animated-pages onclick="stuff();" transitions="cross-fade-all">
<section>
<div layout vertical center center-justified style="background:red;">
<div>1</div>
</div>
</section>
<section>
<div layout vertical center center-justified style="background:blue;">
<div>2</div>
</div>
</section>
<section>
<div layout vertical center center-justified style="background:purple;">
<div>3</div>
</div>
</section>
<section>
<div layout vertical center center-justified style="background:orange;">
<div>4</div>
</div>
</section>
<section>
<div layout vertical center center-justified style="background:green;">
<div>5</div>
</div>
</section>
</core-animated-pages>
<script>
function change() {
var s = document.querySelector('select');
document.querySelector('core-animated-pages').transitions = document.querySelector('select').options[s.selectedIndex].value;
}
var up = true;
var max = 4;
function stuff() {
var p = document.querySelector('core-animated-pages');
if (up && p.selected === max || !up && p.selected === 0) {
up = !up;
}
if (up) {
p.selected += 1;
} else {
p.selected -= 1;
}
}
</script>
</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='["core-animated-pages.html","transitions/core-transition-pages","transitions/hero-transition.html","transitions/cross-fade.html","transitions/cascade-transition.html","transitions/slide-up.html","transitions/slide-down.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="core-animated-pages" label="Animated Pages" group="Core" isContainer>
<!--
TODO(sorvell):
- can't transition without contents; must document or fix.
- transitions syntax awkward: should be space separated
- hero-transition should be renamed `hero`
- hero and cross-fade-all should be always enabled.
-->
<template>
<core-animated-pages style="width:420px;height:582px;overflow:hidden;background-color:#eee;">
<section layout horizontal center center-justified>
</section>
<section>
</section>
<section>
</section>
</core-animated-pages>
</template>
<template id="imports">
<link rel="import" href="core-animated-pages.html">
<link rel="import" href="transitions/hero-transition.html">
<link rel="import" href="transitions/cross-fade.html">
<link rel="import" href="transitions/slide-down.html">
<link rel="import" href="transitions/slide-up.html">
<link rel="import" href="transitions/tile-cascade.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
-->
<link href="core-transition-pages.html" rel="import">
<core-style id="cascade-transition">
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div'; }
:host(.cascade) ::content > * /deep/ [cascade] > div {
-webkit-transition: -webkit-transform {{g.transitions.cascadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1), opacity {{g.transitions.cascadeFadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform {{g.transitions.cascadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1), opacity {{g.transitions.cascadeFadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(2)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(2) {
-webkit-transition-delay: 0.05s;
transition-delay: 0.05s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(3)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(3) {
-webkit-transition-delay: 0.1s;
transition-delay: 0.1s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(4)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(4) {
-webkit-transition-delay: 0.15s;
transition-delay: 0.15s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(5)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(5) {
-webkit-transition-delay: 0.2s;
transition-delay: 0.2s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(6)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(6) {
-webkit-transition-delay: 0.25s;
transition-delay: 0.25s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(7)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(7) {
-webkit-transition-delay: 0.3s;
transition-delay: 0.3s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(8)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(8) {
-webkit-transition-delay: 0.35s;
transition-delay: 0.35s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(9)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(9) {
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(10)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(10) {
-webkit-transition-delay: 0.45s;
transition-delay: 0.45s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(11)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(11) {
-webkit-transition-delay: 0.5s;
transition-delay: 0.5s;
}
polyfill-next-selector { content: ':host(.cascade) > * [cascade] > div:nth-of-type(12)'; }
:host(.cascade) ::content > * /deep/ [cascade] > div:nth-of-type(12) {
-webkit-transition-delay: 0.55s;
transition-delay: 0.55s;
}
polyfill-next-selector { content: '.core-selected [cascade] > div'; }
::content > .core-selected /deep/ [cascade] > div {
}
polyfill-next-selector { content: '[animate]:not(.core-selected) [cascade] > div'; }
::content > [animate]:not(.core-selected) /deep/ [cascade] > div {
-webkit-transform: translateY(100%);
transform: translateY(100%);
}
polyfill-next-selector { content: '[animate]:not(.core-selected) [cascade][fade] > div'; }
::content > [animate]:not(.core-selected) /deep/ [cascade][fade] > div {
opacity: 0;
}
</core-style>
<!--
`cascade-transition` slides the children of a container up in sequence, creating a
reverse waterfall effect. It works well with both grids and lists. Configure the
duration of the transition with the global variable `CoreStyle.g.transitions.cascadeDuration`.
Example:
<core-animated-pages transition="cascade-transition">
<section>
<div id="container" cascade>
<div>item 1</div>
<div>item 2</div>
<div>item 3</div>
<div>item 4</div>
<div>item 5</div>
<div>item 6</div>
<div>item 7</div>
</div>
</section>
<section></section>
</core-animated-pages>
In the above example, the immediate children of `#container` will slide up in
sequence when the page transitions from 0 to 1.
The items can optionally fade in as they slide. Add the `fade` attribute to
the container to do that and configure the duration of the opacity transition with
the global variable `CoreStyle.g.transitions.cascadeFadeDuration`.
@class cascade-transition
@extends core-transition-pages
@status beta
@homepage github.io
-->
<core-transition-pages id="cascade-transition" activeClass="cascade" transitionProperty="transform"></core-transition-pages>
<!--
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 href="../../polymer/polymer.html" rel="import">
<link href="../../core-style/core-style.html" rel="import">
<link href="../../core-transition/core-transition.html" rel="import">
<!--
`core-transition-pages` represents a page transition, which may include CSS and/or
script. It will look for a `core-style` element with the same `id` to install in the
scope of the `core-animated-pages` that's using the transition.
Example:
<core-style id="fooTransition">
// some CSS here
</core-style>
<core-transition-pages id="fooTransition"></core-transition-pages>
There are three stages to a page transition:
1. `prepare`: Called to set up the incoming and outgoing pages to the "before" state,
e.g. setting the incoming page to `opacity: 0` for `cross-fade` or find and
measure hero elements for `hero-transition`.
2. `go`: Called to run the transition. For CSS-based transitions, this generally
applies a CSS `transition` property.
3. `complete`: Called when the elements are finished transitioning.
See the individual transition documentation for specific details.
@element core-transition-pages
@extends core-transition
@status beta
@homepage github.io
-->
<!--
Fired when the transition completes.
@event core-transitionend
-->
<polymer-element name="core-transition-pages" extends="core-transition">
<script>
(function () {
// create some basic transition styling data.
var transitions = CoreStyle.g.transitions = CoreStyle.g.transitions || {};
transitions.duration = '500ms';
transitions.heroDelay = '50ms';
transitions.scaleDelay = '500ms';
transitions.cascadeFadeDuration = '250ms';
Polymer({
publish: {
/**
* This class will be applied to the scope element in the `prepare` function.
* It is removed in the `complete` function. Used to activate a set of CSS
* rules that need to apply before the transition runs, e.g. a default opacity
* or transform for the non-active pages.
*
* @attribute scopeClass
* @type string
* @default ''
*/
scopeClass: '',
/**
* This class will be applied to the scope element in the `go` function. It is
* remoived in the `complete' function. Generally used to apply a CSS transition
* rule only during the transition.
*
* @attribute activeClass
* @type string
* @default ''
*/
activeClass: '',
/**
* Specifies which CSS property to look for when it receives a `transitionEnd` event
* to determine whether the transition is complete. If not specified, the first
* transitionEnd event received will complete the transition.
*
* @attribute transitionProperty
* @type string
* @default ''
*/
transitionProperty: ''
},
/**
* True if this transition is complete.
*
* @attribute completed
* @type boolean
* @default false
*/
completed: false,
prepare: function(scope, options) {
this.boundCompleteFn = this.complete.bind(this, scope);
if (this.scopeClass) {
scope.classList.add(this.scopeClass);
}
},
go: function(scope, options) {
this.completed = false;
if (this.activeClass) {
scope.classList.add(this.activeClass);
}
scope.addEventListener('transitionend', this.boundCompleteFn, false);
},
setup: function(scope) {
if (!scope._pageTransitionStyles) {
scope._pageTransitionStyles = {};
}
var name = this.calcStyleName();
if (!scope._pageTransitionStyles[name]) {
this.installStyleInScope(scope, name);
scope._pageTransitionStyles[name] = true;
}
},
calcStyleName: function() {
return this.id || this.localName;
},
installStyleInScope: function(scope, id) {
if (!scope.shadowRoot) {
scope.createShadowRoot().innerHTML = '<content></content>';
}
var root = scope.shadowRoot;
var scopeStyle = document.createElement('core-style');
root.insertBefore(scopeStyle, root.firstChild);
scopeStyle.applyRef(id);
},
complete: function(scope, e) {
// TODO(yvonne): hack, need to manage completion better
if (e.propertyName !== 'box-shadow' && (!this.transitionProperty || e.propertyName.indexOf(this.transitionProperty) !== -1)) {
this.completed = true;
this.fire('core-transitionend', this, scope);
}
},
// TODO(sorvell): ideally we do this in complete.
ensureComplete: function(scope) {
scope.removeEventListener('transitionend', this.boundCompleteFn, false);
if (this.scopeClass) {
scope.classList.remove(this.scopeClass);
}
if (this.activeClass) {
scope.classList.remove(this.activeClass);
}
}
});
})();
</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
-->
<link href="core-transition-pages.html" rel="import">
<core-style id="cross-fade">
polyfill-next-selector { content: ':host > * [cross-fade]'; }
::content > * /deep/ [cross-fade] {
-webkit-transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host > * [cross-fade][bg]'; }
::content > * /deep/ [cross-fade][bg] {
-webkit-transition: background-color {{g.transitions.xfadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: background-color {{g.transitions.xfadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host > * [cross-fade][hero-p]'; }
::content > * /deep/ [cross-fade][hero-p] {
-webkit-transition: background-color {{g.transitions.xfadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: background-color {{g.transitions.xfadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host > .core-selected [cross-fade]'; }
::content > .core-selected /deep/ [cross-fade] {
opacity: 1;
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [cross-fade]:not([hero-p]):not([bg])'; }
::content > [animate]:not(.core-selected) /deep/ [cross-fade]:not([hero-p]):not([bg]) {
opacity: 0;
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [cross-fade][bg]'; }
::content > [animate]:not(.core-selected) /deep/ [cross-fade][bg] {
background-color: rgba(0, 0, 0, 0);
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [cross-fade][hero-p]'; }
::content > [animate]:not(.core-selected) /deep/ [cross-fade][hero-p] {
background-color: rgba(0, 0, 0, 0);
}
</core-style>
<core-style id="cross-fade-delayed">
polyfill-next-selector { content: ':host > * [cross-fade-delayed]'; }
::content > * /deep/ [cross-fade-delayed] {
-webkit-transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out;
transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out;
}
polyfill-next-selector { content: ':host > .core-selected [cross-fade-delayed]'; }
::content > .core-selected /deep/ [cross-fade-delayed] {
-webkit-transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out {{g.transitions.xfadeDelay || g.transitions.xfadeDuration || g.transitions.duration}};
transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out {{g.transitions.xfadeDelay || g.transitions.xfadeDuration || g.transitions.duration}};
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [cross-fade-delayed]'; }
::content > [animate]:not(.core-selected) /deep/ [cross-fade-delayed] {
opacity: 0;
}
polyfill-next-selector { content: ':host > .core-selected [cross-fade-delayed]'; }
::content > .core-selected /deep/ [cross-fade-delayed] {
opacity: 1;
}
</core-style>
<core-style id="cross-fade-all">
/* cross-fade-all: cross fade everything except for heroes and their parents */
polyfill-next-selector { content: ':host(.cross-fade-all) > * *:not([hero]):not([hero-p]):not([cross-fade])'; }
:host(.cross-fade-all) ::content > * /deep/ *:not([hero]):not([hero-p]):not([cross-fade]) {
-webkit-transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out;
transition: opacity {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out;
}
polyfill-next-selector { content: ':host(.cross-fade-all) > [animate]:not(.core-selected) *:not([hero]):not([hero-p]):not([cross-fade])'; }
:host(.cross-fade-all) ::content > [animate]:not(.core-selected) /deep/ *:not([hero]):not([hero-p]):not([cross-fade]) {
opacity: 0;
}
polyfill-next-selector { content: ':host(.cross-fade-all) > .core-selected *:not([hero])'; }
.host(.cross-fade-all) ::content > .core-selected /deep/ * {
opacity: 1;
}
/* Only background-color is allowed for the hero's parents, no opacity transitions */
polyfill-next-selector { content: ':host(.cross-fade-all) > * [hero-p]'; }
:host(.cross-fade-all) ::content > * /deep/ [hero-p] {
-webkit-transition: background-color {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out;
transition: background-color {{g.transitions.xfadeDuration || g.transitions.duration}} ease-out;
opacity: 1;
}
polyfill-next-selector { content: ':host(.cross-fade-all) > [animate]:not(.core-selected) [hero-p]'; }
:host(.cross-fade-all) ::content > [animate]:not(.core-selected) /deep/ [hero-p] {
background-color: rgba(0, 0, 0, 0);
}
</core-style>
<!--
`cross-fade` fades out elements in the outgoing page and fades in elements in the
incoming page during a page transition. You can configure the duration of the
transition with the global variable `CoreStyle.g.transitions.xfadeDuration`.
Example:
<core-animated-pages transition="cross-fade">
<section>
<div id="div1" cross-fade></div>
</section>
<section>
<div id="div2" cross-fade bg>
<div id="div3" cross-fade></div>
<div id="div4"></div>
</div>
</section>
</core-animated-pages>
In the above example, `#div1` and `#div3` has the `cross-fade` attribute. `#div1`
will fade out and `#div3` will fade in with opacity transitions when the page switches
from 0 to 1. Sometimes, you may want to only fade the background color of an element
but not its children, and you can use the `bg` attribute along with the `#div1`
attribute as in `#div2`.
@class cross-fade
@extends core-transition-pages
@status beta
@homepage github.io
-->
<!--
`cross-fade-delayed` performs a cross-fade after some delay, either specified in
the global variable `CoreStyle.g.transitions.xfadeDelay` or the duration of the
transition.
Example:
<core-animated-pages transition="hero-transition cross-fade-delayed">
<section>
<div id="div1" hero-id hero></div>
</section>
<section>
<div id="div2" hero-id hero>
<div id="div3" cross-fade-delayed></div>
</div>
</section>
</core-animated-pages>
In the above example, `#div3` fades in after the hero transition from `#div1` to
`#div2` completes.
@class cross-fade-delayed
@extends core-transition-pages
@status beta
@homepage github.io
-->
<core-transition-pages id="cross-fade"></core-transition-pages>
<core-transition-pages id="cross-fade-delayed"></core-transition-pages>
<core-transition-pages id="cross-fade-all" scopeClass="cross-fade-all"></core-transition-pages>
/*
* @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
*/
/* Hide heroes that are not currently transitioning */
polyfill-next-selector { content: ':host > [animate] [hero]'; }
::content > [animate] /deep/ [hero], ::content > [animate]::shadow [hero] {
visibility: hidden;
}
polyfill-next-selector { content: ':host > .core-selected[animate] [hero]'; }
::content > .core-selected[animate] /deep/ [hero],
::content > .core-selected[animate]::shadow [hero] {
visibility: visible;
z-index: 10000;
}
<!--
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 href="core-transition-pages.html" rel="import">
<core-style id="hero-transition">
/* Hide heroes that are not currently transitioning */
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [hero]'; }
::content > [animate]:not(.core-selected) /deep/ [hero] {
opacity: 0;
}
polyfill-next-selector { content: ':host > .core-selected[animate] [hero]'; }
::content > .core-selected[animate] /deep/ [hero] {
opacity: 1;
z-index: 10000;
}
polyfill-next-selector { content: ':host > * [hero-p]'; }
::content > * /deep/ [hero-p] {
-webkit-transition: box-shadow 100ms ease-out;
transition: box-shadow 100ms ease-out;
}
polyfill-next-selector { content: ':host > [animate] [hero-p]'; }
::content > [animate] /deep/ [hero-p] {
box-shadow: none !important;
}
</core-style>
<!--
`hero-transition` transforms two elements in different pages such that they appear
to be shared across the pages.
Example:
<core-animated-pages transition="hero-transition">
<section layout horizontal>
<div id="div1" flex></div>
<div id="div2" flex hero-id="shared" hero></div>
</section>
<section>
<section layout horizontal>
<div id="div3" flex hero-id="shared" hero></div>
<div id="div4" flex></div>
</section>
</section>
</core-animated-pages>
In the above example, the elements `#div2` and `#div3` shares the same `hero-id`
attribute and a single element appears to translate and scale smoothly between
the two positions during a page transition.
Both elements from the source and destination pages must share the same `hero-id`
and must both contain the `hero` attribute to trigger the transition. The separate
`hero` attribute allows you to use binding to configure the transition:
Example:
<core-animated-pages transition="hero-transition">
<section layout horizontal>
<div id="div1" flex hero-id="shared" hero?="{{selected == 0}}"></div>
<div id="div2" flex hero-id="shared" hero?="{{selected == 1}}"></div>
</section>
<section>
<section layout horizontal>
<div id="div3" flex hero-id="shared" hero></div>
</section>
</section>
</core-animated-pages>
In the above example, either `#div1` or `#div2` scales to `#div3` during a page transition,
depending on the value of `selected`.
Because it is common to share elements with different `border-radius` values, by default
this transition will also animate the `border-radius` property.
You can configure the duration of the hero transition with the global variable
`CoreStyle.g.transitions.heroDuration`.
@class hero-transition
@extends core-transition-pages
@status beta
@homepage github.io
-->
<polymer-element name="hero-transition" extends="core-transition-pages">
<script>
(function() {
var webkitStyles = '-webkit-transition' in document.documentElement.style
var TRANSITION_CSSNAME = webkitStyles ? '-webkit-transition' : 'transition';
var TRANSFORM_CSSNAME = webkitStyles ? '-webkit-transform' : 'transform';
var TRANSITION_NAME = webkitStyles ? 'webkitTransition' : 'transition';
var TRANSFORM_NAME = webkitStyles ? 'webkitTransform' : 'transform';
var hasShadowDOMPolyfill = window.ShadowDOMPolyfill;
Polymer({
go: function(scope, options) {
var props = [
'border-radius',
'width',
'height',
TRANSFORM_CSSNAME
];
var duration = options && options.duration ||
(CoreStyle.g.transitions.heroDuration ||
CoreStyle.g.transitions.duration);
scope._heroes.forEach(function(h) {
var d = h.h0.hasAttribute('hero-delayed') ? CoreStyle.g.transitions.heroDelay : '';
var wt = [];
props.forEach(function(p) {
wt.push(p + ' ' + duration + ' ' + options.easing + ' ' + d);
});
h.h1.style[TRANSITION_NAME] = wt.join(', ');
h.h1.style.borderRadius = h.r1;
h.h1.style[TRANSFORM_NAME] = '';
});
this.super(arguments);
if (!scope._heroes.length) {
this.completed = true;
}
},
prepare: function(scope, options) {
this.super(arguments);
var src = options.src, dst = options.dst;
if (scope._heroes && scope._heroes.length) {
this.ensureComplete(scope);
} else {
scope._heroes = [];
}
// FIXME(yvonne): basic support for nested pages.
// Look for heroes in the light DOM and one level of shadow DOM of the src and dst,
// and also in src.selectedItem or dst.selectedItem, then transform the dst hero to src
var ss = '[hero]';
var h$ = this.findAllInShadows(src, ss);
if (src.selectedItem) {
hs$ = this.findAllInShadows(src.selectedItem, ss);
hsa$ = [];
// De-duplicate items
Array.prototype.forEach.call(hs$, function(hs) {
if (h$.indexOf(hs) === -1) {
hsa$.push(hs);
}
})
h$ = h$.concat(hsa$);
}
for (var i=0, h0; h0=h$[i]; i++) {
var v = h0.getAttribute('hero-id');
var ds = '[hero][hero-id="' + v + '"]';
var h1 = this.findInShadows(dst, ds);
if (!h1 && dst.selectedItem) {
h1 = this.findInShadows(dst.selectedItem, ds);
}
// console.log('src', src);
// console.log('dst', dst, dst.selectedItem);
// console.log(v, h0, h1);
if (v && h1) {
var c0 = getComputedStyle(h0);
var c1 = getComputedStyle(h1);
var h = {
h0: h0,
b0: h0.getBoundingClientRect(),
r0: c0.borderRadius,
h1: h1,
b1: h1.getBoundingClientRect(),
r1: c1.borderRadius
};
var dl = h.b0.left - h.b1.left;
var dt = h.b0.top - h.b1.top;
var sw = h.b0.width / h.b1.width;
var sh = h.b0.height / h.b1.height;
// h.scaley = h.h0.hasAttribute('scaley');
// if (!h.scaley && (sw !== 1 || sh !== 1)) {
// sw = sh = 1;
// h.h1.style.width = h.b0.width + 'px';
// h.h1.style.height = h.b0.height + 'px';
// }
// Also animate the border-radius for the circle-to-square transition
if (h.r0 !== h.r1) {
h.h1.style.borderRadius = h.r0;
}
// console.log(h);
h.h1.style[TRANSFORM_NAME] = 'translate(' + dl + 'px,' + dt + 'px)' + ' scale(' + sw + ',' + sh + ')';
h.h1.style[TRANSFORM_NAME + 'Origin'] = '0 0';
scope._heroes.push(h);
}
}
},
// carefully look into ::shadow with polyfill specific hack
findInShadows: function(node, selector) {
return node.querySelector(selector) || (hasShadowDOMPolyfill ?
Platform.queryAllShadows(node, selector) :
node.querySelector('::shadow ' + selector));
},
findAllInShadows: function(node, selector) {
if (hasShadowDOMPolyfill) {
var nodes = node.querySelectorAll(selector).array();
var shadowNodes = Platform.queryAllShadows(node, selector, true);
return nodes.concat(shadowNodes);
} else {
return node.querySelectorAll(selector).array().concat(node.shadowRoot ? node.shadowRoot.querySelectorAll(selector).array() : []);
}
},
ensureComplete: function(scope) {
this.super(arguments);
if (scope._heroes) {
scope._heroes.forEach(function(h) {
h.h1.style[TRANSITION_NAME] = '';
h.h1.style[TRANSFORM_NAME] = '';
});
scope._heroes = [];
}
},
complete: function(scope, e) {
// if (e.propertyName === TRANSFORM_CSSNAME) {
var done = false;
scope._heroes.forEach(function(h) {
if (h.h1 === e.path[0]) {
done = true;
}
});
if (done) {
this.super(arguments);
}
// }
}
});
})();
</script>
</polymer-element>
<hero-transition id="hero-transition"></hero-transition>
<!--
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 href="core-transition-pages.html" rel="import">
<core-style id="list-cascade">
polyfill-next-selector { content: ':host.list-cascade > * [list-cascade]'; }
:host(.list-cascade) ::content > * [list-cascade] * {
-webkit-transition: -webkit-transform 1s cubic-bezier(0.4, 0, 0.2, 1), opacity {{g.transitions.cascade || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform 1s cubic-bezier(0.4, 0, 0.2, 1), opacity {{g.transitions.cascade || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host > .core-selected [list-cascade] *'; }
::content > .core-selected [list-cascade] * {
-webkit-transform: none;
transform: none;
}
polyfill-next-selector { content: ':host > *:not(.core-selected) [list-cascade] *'; }
::content > *:not(.core-selected) [list-cascade] * {
-webkit-transform: translateY(200%);
transform: translateY(200%);
opacity: 0.2;
}
polyfill-next-selector { content: ':host > .core-selected [list-cascade] *:nth-child(2)'; }
::content > .core-selected [list-cascade] *:nth-child(2) {
-webkit-transition-delay: 0.1s;
transition-delay: 0.1s;
}
polyfill-next-selector { content: ':host > .core-selected [list-cascade] *:nth-child(3)'; }
::content > .core-selected [list-cascade] *:nth-child(3) {
-webkit-transition-delay: 0.2s;
transition-delay: 0.2s;
}
polyfill-next-selector { content: ':host > .core-selected [list-cascade] *:nth-child(4)'; }
::content > .core-selected [list-cascade] *:nth-child(4) {
-webkit-transition-delay: 0.3s;
transition-delay: 0.3s;
}
polyfill-next-selector { content: ':host > .core-selected [list-cascade] *:nth-child(5)'; }
::content > .core-selected [list-cascade] *:nth-child(5) {
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
}
</core-style>
<core-transition-pages id="list-cascade" activeClass="list-cascade"></core-transition-pages>
<!--
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 href="core-transition-pages.html" rel="import">
<core-style id="scale-up">
polyfill-next-selector { content: ':host > * [scale-up]'; }
::content > * /deep/ [scale-up] {
-webkit-transition: -webkit-transform {{g.transitions.scaleDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1) {{g.transitions.scaleDelay || g.transitions.delay}} !important;
transition: transform {{g.transitions.scaleDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1) {{g.transitions.scaleDelay || g.transitions.delay}} !important;
}
polyfill-next-selector { content: ':host > .core-selected [scale-up]'; }
::content > .core-selected /deep/ [scale-up] {
-webkit-transform: none;
transform: none;
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [scale-up]'; }
::content > [animate]:not(.core-selected) /deep/ [scale-up] {
-webkit-transform: scale(0);
transform: scale(0);
}
polyfill-next-selector { content: ':host > .core-selected[animate] [scale-up]'; }
::content > .core-selected[animate] /deep/ [scale-up] {
z-index: 1000;
}
</core-style>
<core-transition-pages id="scale-up"></core-transition-pages>
<!--
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 href="core-transition-pages.html" rel="import">
<core-style id="slide-down">
polyfill-next-selector { content: ':host.slide-down > * [slide-down]'; }
:host(.slide-down) ::content > * /deep/ [slide-down] {
-webkit-transition: -webkit-transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host > .core-selected [slide-down]'; }
::content > .core-selected /deep/ [slide-down] {
-webkit-transform: none;
transform: none;
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [slide-down]'; }
::content > [animate]:not(.core-selected) /deep/ [slide-down] {
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
}
</core-style>
<!--
`slide-down` slides an element in the outgoing page from the top of the window and
slides in an element in the incoming page from the top of the window during a page
transition. You can configure the duration of the transition with the global variable
`CoreStyle.g.transitions.slideDuration`.
Example:
<core-animated-pages transition="slide-down">
<section>
<div id="div1" slide-down></div>
</section>
<section></section>
</core-animated-pages>
@class slide-down
@extends core-transition-pages
@status beta
@homepage github.io
-->
<core-transition-pages id="slide-down" activeClass="slide-down"></core-transition-pages>
<!--
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 href="core-transition-pages.html" rel="import">
<core-style id="slide-from-bottom">
polyfill-next-selector { content: ':host(.slide-from-bottom) > *'; }
:host(.slide-from-bottom) ::content > * {
-webkit-transition: -webkit-transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host(.slide-from-bottom) > .core-selected ~ [animate]:not(.core-selected)'; }
:host(.slide-from-bottom) ::content > .core-selected ~ [animate]:not(.core-selected) {
-webkit-transform: translateY(100%);
transform: translateY(100%);
}
polyfill-next-selector { content: ':host(.slide-from-bottom) > [animate]:not(.core-selected)'; }
:host(.slide-from-bottom) ::content > [animate]:not(.core-selected) {
-webkit-transform: translateY(-100%);
transform: translateY(-100%);
}
polyfill-next-selector { content: ':host(.slide-from-bottom) > .core-selected'; }
:host(.slide-from-bottom) ::content > .core-selected {
-webkit-transform: none;
transform: none;
}
</core-style>
<core-transition-pages id="slide-from-bottom" scopeClass="slide-from-bottom"></core-transition-pages>
<!--
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 href="core-transition-pages.html" rel="import">
<!--
Warning: This transition does not work well in combination with other transitions, because
it operates on the page rather than the page's children.
-->
<core-style id="slide-from-right">
polyfill-next-selector { content: ':host(.slide-from-right) > *'; }
:host(.slide-from-right) ::content > * {
-webkit-transition: -webkit-transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host(.slide-from-right) > .core-selected ~ [animate]:not(.core-selected)'; }
:host(.slide-from-right) ::content > .core-selected ~ [animate]:not(.core-selected) {
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
polyfill-next-selector { content: ':host(.slide-from-right) > [animate]:not(.core-selected)'; }
:host(.slide-from-right) ::content > [animate]:not(.core-selected) {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
polyfill-next-selector { content: ':host(.slide-from-right) > .core-selected'; }
:host(.slide-from-right) ::content > .core-selected {
-webkit-transform: none;
transform: none;
}
</core-style>
<core-transition-pages id="slide-from-right" scopeClass="slide-from-right"></core-transition-pages>
<!--
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 href="core-transition-pages.html" rel="import">
<core-style id="slide-up">
polyfill-next-selector { content: ':host.slide-up > * [slide-up]'; }
:host(.slide-up) ::content > * /deep/ [slide-up] {
-webkit-transition: -webkit-transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host > .core-selected [slide-up]'; }
::content > .core-selected /deep/ [slide-up] {
-webkit-transform: none;
transform: none;
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [slide-up]'; }
::content > [animate]:not(.core-selected) /deep/ [slide-up] {
-webkit-transform: translateY(150%);
transform: translateY(150%);
}
</core-style>
<core-style id="slide-up-offscreen">
polyfill-next-selector { content: ':host.slide-up-offscreen > * [slide-up-offscreen]'; }
:host(.slide-up-offscreen) ::content > * /deep/ [slide-up-offscreen] {
-webkit-transition: -webkit-transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform {{g.transitions.slideDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host > .core-selected [slide-up-offscreen]'; }
::content > .core-selected /deep/ [slide-up-offscreen] {
-webkit-transform: none;
transform: none;
}
polyfill-next-selector { content: ':host > [animate]:not(.core-selected) [slide-up-offscreen]'; }
::content > [animate]:not(.core-selected) /deep/ [slide-up-offscreen] {
-webkit-transform: translateY(100vh);
transform: translateY(100vh);
z-index: -1;
}
polyfill-rule {
content: ':host > [animate]:not(.core-selected) [slide-up-offscreen]';
-webkit-transform: translateY(1000px);
}
</core-style>
<!--
`slide-up` slides an element in the outgoing page from the bottom of the window
and slides in an element in the incoming page from the bottom of the window during
a page transition. You can configure the duration of the transition with the global
variable `CoreStyle.g.transitions.slideDuration`.
Example:
<core-animated-pages transition="slide-up">
<section>
<div id="div1" slide-up></div>
</section>
<section></section>
</core-animated-pages>
@class slide-up
@extends core-transition-pages
@status beta
@homepage github.io
-->
<core-transition-pages id="slide-up" activeClass="slide-up"></core-transition-pages>
<core-transition-pages id="slide-up-offscreen" activeClass="slide-up-offscreen"></core-transition-pages>
<!--
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 href="core-transition-pages.html" rel="import">
<core-style id="tile-cascade">
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div {
-webkit-transition: -webkit-transform {{g.transitions.cascadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1), opacity {{g.transitions.cascadeFadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
transition: transform {{g.transitions.cascadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1), opacity {{g.transitions.cascadeFadeDuration || g.transitions.duration}} cubic-bezier(0.4, 0, 0.2, 1);
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(2)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(2) {
-webkit-transition-delay: 0.05s;
transition-delay: 0.05s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(3)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(3) {
-webkit-transition-delay: 0.1s;
transition-delay: 0.1s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(4)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(4) {
-webkit-transition-delay: 0.15s;
transition-delay: 0.15s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(5)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(5) {
-webkit-transition-delay: 0.2s;
transition-delay: 0.2s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(6)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(6) {
-webkit-transition-delay: 0.25s;
transition-delay: 0.25s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(7)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(7) {
-webkit-transition-delay: 0.3s;
transition-delay: 0.3s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(8)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(8) {
-webkit-transition-delay: 0.35s;
transition-delay: 0.35s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(9)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(9) {
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(10)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(10) {
-webkit-transition-delay: 0.45s;
transition-delay: 0.45s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(11)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(11) {
-webkit-transition-delay: 0.5s;
transition-delay: 0.5s;
}
polyfill-next-selector { content: ':host(.tile-cascade) > * [tile-cascade] > div:nth-of-type(12)'; }
:host(.tile-cascade) ::content > * /deep/ [tile-cascade] > div:nth-of-type(12) {
-webkit-transition-delay: 0.55s;
transition-delay: 0.55s;
}
polyfill-next-selector { content: '.core-selected [tile-cascade] > div'; }
::content > .core-selected /deep/ [tile-cascade] > div {
}
polyfill-next-selector { content: '[animate]:not(.core-selected) [tile-cascade] > div'; }
::content > [animate]:not(.core-selected) /deep/ [tile-cascade] > div {
-webkit-transform: translateY(100%);
transform: translateY(100%);
}
polyfill-next-selector { content: '[animate]:not(.core-selected) [tile-cascade][fade] > div'; }
::content > [animate]:not(.core-selected) /deep/ [tile-cascade][fade] > div {
opacity: 0;
}
</core-style>
<core-transition-pages id="tile-cascade" activeClass="tile-cascade" transitionProperty="transform"></core-transition-pages>
{
"name": "core-animation",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"web-animations-js": "web-animations/web-animations-js#master"
},
"homepage": "https://github.com/Polymer/core-animation",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "23a21e9a31a89ee7a5e8c4b9cdefe00a3ba83c13"
},
"_source": "git://github.com/Polymer/core-animation.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-animation"
}
{
"name": "core-animation",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"web-animations-js": "web-animations/web-animations-js#master"
}
}
<!--
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="../polymer/polymer.html">
<link rel="import" href="core-animation.html">
<!--
@group Polymer Core Elements
`core-animation-group` combines `core-animation` or `core-animation-group` elements to
create a grouped web animation. The group may be parallel (type is `par`) or sequential
(type is `seq`). Parallel groups play all the children elements simultaneously, and
sequential groups play the children one after another.
Example of an animation group to rotate and then fade an element:
<core-animation-group type="seq">
<core-animation id="fadeout" duration="500">
<core-animation-keyframe>
<core-animation-prop name="transform" value="rotate(0deg)"></core-animation-prop>
<core-animation-prop name="transform" value="rotate(45deg)"></core-animation-prop>
</core-animation-keyframe>
</core-animation>
<core-animation id="fadeout" duration="500">
<core-animation-keyframe>
<core-animation-prop name="opacity" value="1"></core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="opacity" value="0"></core-animation-prop>
</core-animation-keyframe>
</core-animation>
</core-animation-group>
@element core-animation-group
@status beta
@homepage github.io
-->
<polymer-element name="core-animation-group" constructor="CoreAnimationGroup" extends="core-animation" attributes="type">
<script>
(function() {
var ANIMATION_GROUPS = {
'par': AnimationGroup,
'seq': AnimationSequence
};
Polymer({
publish: {
/**
* If target is set, any children without a target will be assigned the group's
* target when this property is set.
*
* @property target
* @type HTMLElement|Node|Array|Array<HTMLElement|Node>
*/
/**
* For a `core-animation-group`, a duration of "auto" means the duration should
* be the specified duration of its children. If set to anything other than
* "auto", any children without a set duration will be assigned the group's duration.
*
* @property duration
* @type number
* @default "auto"
*/
duration: {value: 'auto', reflect: true},
/**
* The type of the animation group. 'par' creates a parallel group and 'seq' creates
* a sequential group.
*
* @property type
* @type String
* @default 'par'
*/
type: {value: 'par', reflect: true}
},
typeChanged: function() {
this.apply();
},
targetChanged: function() {
// Only propagate target to children animations if it's defined.
if (this.target) {
this.doOnChildren(function(c) {
c.target = this.target;
}.bind(this));
}
},
durationChanged: function() {
if (this.duration && this.duration !== 'auto') {
this.doOnChildren(function(c) {
// Propagate to children that is not a group and has no
// duration specified.
if (!c.type && (!c.duration || c.duration === 'auto')) {
c.duration = this.duration;
}
}.bind(this));
}
},
doOnChildren: function(inFn) {
var children = this.children;
if (!children.length) {
children = this.shadowRoot ? this.shadowRoot.childNodes : [];
}
Array.prototype.forEach.call(children, function(c) {
// TODO <template> in the way
c.apply && inFn(c);
}, this);
},
makeAnimation: function() {
return new ANIMATION_GROUPS[this.type](this.childAnimations, this.timingProps);
},
hasTarget: function() {
var ht = this.target !== null;
if (!ht) {
this.doOnChildren(function(c) {
ht = ht || c.hasTarget();
}.bind(this));
}
return ht;
},
apply: function() {
// Propagate target and duration to child animations first.
this.durationChanged();
this.targetChanged();
this.doOnChildren(function(c) {
c.apply();
});
return this.super();
},
get childAnimationElements() {
var list = [];
this.doOnChildren(function(c) {
if (c.makeAnimation) {
list.push(c);
}
});
return list;
},
get childAnimations() {
var list = [];
this.doOnChildren(function(c) {
if (c.animation) {
list.push(c.animation);
}
});
return list;
}
});
})();
</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
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="web-animations.html">
<!--
@group Polymer Core Elements
`core-animation` is a convenience element to use web animations with Polymer elements. It
allows you to create a web animation declaratively. You can extend this class to create
new types of animations and combine them with `core-animation-group`.
Example to create animation to fade out an element over 500ms:
<core-animation id="fadeout" duration="500">
<core-animation-keyframe>
<core-animation-prop name="opacity" value="1"></core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="opacity" value="0"></core-animation-prop>
</core-animation-keyframe>
</core-animation>
<div id="el">Fade me out</div>
<script>
var animation = document.getElementById('fadeout');
animation.target = document.getElementById('el');
animation.play();
</script>
Or do the same imperatively:
var animation = new CoreAnimation();
animation.duration = 500;
animation.keyframes = [
{opacity: 1},
{opacity: 0}
];
animation.target = document.getElementById('el');
animation.play();
You can also provide a javascript function instead of keyframes to the animation. This
behaves essentially the same as `requestAnimationFrame`:
var animation = new CoreAnimation();
animation.customEffect = function(timeFraction, target, animation) {
// do something custom
};
animation.play();
Elements that are targets to a `core-animation` are given the `core-animation-target` class.
@element core-animation
@status beta
@homepage github.io
-->
<polymer-element name="core-animation" constructor="CoreAnimation" attributes="target keyframes sample composite duration fill easing iterationStart iterationCount delay direction autoplay targetSelector">
<script>
(function() {
function toNumber(value, allowInfinity) {
return (allowInfinity && value === 'Infinity') ? Number.POSITIVE_INFINITY : Number(value);
};
Polymer({
/**
* Fired when the animation completes.
*
* @event core-animation-finish
*/
/**
*
* Fired when the web animation object changes.
*
* @event core-animation-change
*/
publish: {
/**
* One or more nodes to animate.
*
* @property target
* @type HTMLElement|Node|Array<HTMLElement|Node>
*/
target: {value: null, reflect: true},
/**
* Animation keyframes specified as an array of dictionaries of
* &lt;css properties&gt;:&lt;array of values&gt; pairs. For example,
*
* @property keyframes
* @type Object
*/
keyframes: {value: null, reflect: true},
/**
* A custom animation function. Either provide this or `keyframes`. The signature
* of the callback is `EffectsCallback(timeFraction, target, animation)`
*
* @property customEffect
* @type Function(number, Object, Object)
*/
customEffect: {value: null, reflect: true},
/**
* Controls the composition behavior. If set to "replace", the effect overrides
* the underlying value for the target. If set the "add", the effect is added to
* the underlying value for the target. If set to "accumulate", the effect is
* accumulated to the underlying value for the target.
*
* In cases such as numbers or lengths, "add" and "accumulate" produce the same
* value. In list values, "add" is appending to the list, while "accumulate" is
* adding the individual components of the list.
*
* For example, adding `translateX(10px)` and `translateX(25px)` produces
* `translateX(10px) translateX(25px)` and accumulating produces `translateX(35px)`.
*
* @property composite
* @type "replace"|"add"|"accumulate"
* @default "replace"
*/
composite: {value: 'replace', reflect: true},
/**
* Animation duration in milliseconds, "Infinity", or "auto". "auto" is
* equivalent to 0.
*
* @property duration
* @type number|"Infinity"
* @default "auto"
*/
duration: {value: 'auto', reflect: true},
/**
* Controls the effect the animation has on the target when it's not playing.
* The possible values are "none", "forwards", "backwards", "both" or "auto".
*
* "none" means the animation has no effect when it's not playing.
*
* "forward" applies the value at the end of the animation after it's finished.
*
* "backwards" applies the value at the start of the animation to the target
* before it starts playing and has no effect when the animation finishes.
*
* "both" means "forwards" and "backwards". "auto" is equivalent to "none".
*
* @property fill
* @type "none"|"forwards"|"backwards"|"both"|"auto"
* @default "auto"
*/
fill: {value: 'auto', reflect: true},
/**
* A transition timing function. The values are equivalent to the CSS
* counterparts.
*
* @property easing
* @type string
* @default "linear"
*/
easing: {value: 'linear', reflect: true},
/**
* The number of milliseconds to delay before beginning the animation.
*
* @property delay
* @type Number
* @default 0
*/
delay: {value: 0, reflect: true},
/**
* The number of milliseconds to wait after the animation finishes. This is
* useful, for example, in an animation group to wait for some time before
* beginning the next item in the animation group.
*
* @property endDelay
* @type number
* @default 0
*/
endDelay: {value: 0, reflect: true},
/**
* The number of iterations this animation should run for.
*
* @property iterations
* @type Number|'Infinity'
* @default 1
*/
iterations: {value: 1, reflect: true},
/**
* Number of iterations into the animation in which to begin the effect.
* For example, setting this property to 0.5 and `iterations` to 2 will
* cause the animation to begin halfway through the first iteration but still
* run twice.
*
* @property iterationStart
* @type Number
* @default 0
*/
iterationStart: {value: 0, reflect: true},
/**
* (not working in web animations polyfill---do not use)
*
* Controls the iteration composition behavior. If set to "replace", the effect for
* every iteration is independent of each other. If set to "accumulate", the effect
* for iterations of the animation will build upon the value in the previous iteration.
*
* Example:
*
* // Moves the target 50px on the x-axis over 5 iterations.
* <core-animation iterations="5" iterationComposite="accumulate">
* <core-animation-keyframe>
* <core-animation-prop name="transform" value="translateX(10px)"></core-animation-prop>
* </core-animation-keyframe>
* </core-animation>
*
* @property iterationComposite
* @type "replace"|"accumulate"
* @default false
*/
iterationComposite: {value: 'replace', reflect: true},
/**
* The playback direction of the animation. "normal" plays the animation in the
* normal direction. "reverse" plays it in the reverse direction. "alternate"
* alternates the playback direction every iteration such that even iterations are
* played normally and odd iterations are reversed. "alternate-reverse" plays
* even iterations in the reverse direction and odd iterations in the normal
* direction.
*
* @property direction
* @type "normal"|"reverse"|"alternate"|"alternate-reverse"
* @default "normal"
*/
direction: {value: 'normal', reflect: true},
/**
* A multiplier to the playback rate to the animation.
*
* @property playbackRate
* @type number
* @default 1
*/
playbackRate: {value: 1, reflect: true},
/**
* If set to true, play the animation when it is created or a property is updated.
*
* @property autoplay
* @type boolean
* @default false
*/
autoplay: {value: false, reflect: true}
},
animation: false,
observe: {
target: 'apply',
keyframes: 'apply',
customEffect: 'apply',
composite: 'apply',
duration: 'apply',
fill: 'apply',
easing: 'apply',
iterations: 'apply',
iterationStart: 'apply',
iterationComposite: 'apply',
delay: 'apply',
endDelay: 'apply',
direction: 'apply',
playbackRate: 'apply',
autoplay: 'apply'
},
ready: function() {
this.apply();
},
/**
* Plays the animation. If the animation is currently paused, seeks the animation
* to the beginning before starting playback.
*
* @method play
* @return AnimationPlayer The animation player.
*/
play: function() {
this.apply();
if (this.animation && !this.autoplay) {
this.player = document.timeline.play(this.animation);
this.player.onfinish = this.animationFinishHandler.bind(this);
return this.player;
}
},
/**
* Stops the animation and clears all effects on the target.
*
* @method cancel
*/
cancel: function() {
if (this.player) {
this.player.cancel();
}
},
/**
* Seeks the animation to the end.
*
* @method finish
*/
finish: function() {
if (this.player) {
this.player.finish();
}
},
/**
* Pauses the animation.
*
* @method pause
*/
pause: function() {
if (this.player) {
this.player.pause();
}
},
/**
* @method hasTarget
* @return boolean True if `target` is defined.
*/
hasTarget: function() {
return this.target !== null;
},
/**
* Creates a web animations object based on this object's properties, and
* plays it if autoplay is true.
*
* @method apply
* @return Object A web animation.
*/
apply: function() {
this.animation = this.makeAnimation();
if (this.autoplay && this.animation) {
this.play();
}
return this.animation;
},
makeSingleAnimation: function(target) {
// XXX(yvonne): for selecting all the animated elements.
target.classList.add('core-animation-target');
return new Animation(target, this.animationEffect, this.timingProps);
},
makeAnimation: function() {
if (!this.target) {
return null;
}
var animation;
if (Array.isArray(this.target)) {
var array = [];
this.target.forEach(function(t) {
array.push(this.makeSingleAnimation(t));
}.bind(this));
animation = new AnimationGroup(array);
} else {
animation = this.makeSingleAnimation(this.target);
}
return animation;
},
animationChanged: function() {
// Sending 'this' with the event so you can always get the animation object
// that fired the event, due to event retargetting in shadow DOM.
this.fire('core-animation-change', this);
},
targetChanged: function(old) {
if (old) {
old.classList.remove('core-animation-target');
}
},
get timingProps() {
var props = {};
var timing = {
delay: {isNumber: true},
endDelay: {isNumber: true},
fill: {},
iterationStart: {isNumber: true},
iterations: {isNumber: true, allowInfinity: true},
duration: {isNumber: true},
playbackRate: {isNumber: true},
direction: {},
easing: {}
};
for (t in timing) {
if (this[t] !== null) {
var name = timing[t].property || t;
props[name] = timing[t].isNumber && this[t] !== 'auto' ?
toNumber(this[t], timing[t].allowInfinity) : this[t];
}
}
return props;
},
get animationEffect() {
var props = {};
var frames = [];
var effect;
if (this.keyframes) {
frames = this.keyframes;
} else if (!this.customEffect) {
var children = this.querySelectorAll('core-animation-keyframe');
if (children.length === 0) {
children = this.shadowRoot.querySelectorAll('core-animation-keyframe');
}
Array.prototype.forEach.call(children, function(c) {
frames.push(c.properties);
});
}
if (this.customEffect) {
effect = this.customEffect;
} else {
effect = new KeyframeEffect(frames, this.composite);
}
return effect;
},
animationFinishHandler: function() {
this.fire('core-animation-finish');
}
});
})();
</script>
</polymer-element>
<!--
`core-animation-keyframe` represents a keyframe in a `core-animation`. Use them as children of
`core-animation` elements to create web animations declaratively. If the `offset` property is
unset, the keyframes will be distributed evenly within the animation duration. Use
`core-animation-prop` elements as children of this element to specify the CSS properties for
the animation.
@element core-animation-keyframe
@status beta
@homepage github.io
-->
<polymer-element name="core-animation-keyframe" attributes="offset">
<script>
Polymer({
publish: {
/**
* An offset from 0 to 1.
*
* @property offset
* @type Number
*/
offset: {value: null, reflect: true}
},
get properties() {
var props = {};
var children = this.querySelectorAll('core-animation-prop');
Array.prototype.forEach.call(children, function(c) {
props[c.name] = c.value;
});
if (this.offset !== null) {
props.offset = this.offset;
}
return props;
}
});
</script>
</polymer-element>
<!--
`core-animation-prop` represents a CSS property and value pair to use with
`core-animation-keyframe`.
@element core-animation-prop
@status beta
@homepage github.io
-->
<polymer-element name="core-animation-prop" attributes="name value">
<script>
Polymer({
publish: {
/**
* A CSS property name.
*
* @property name
* @type string
*/
name: {value: '', reflect: true},
/**
* The value for the CSS property.
*
* @property value
* @type string|number
*/
value: {value: '', reflect: true}
}
});
</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
-->
<!DOCTYPE html>
<html>
<head>
<title>core-animation</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-animation.html">
<link rel="import" href="core-animation-group.html">
<!-- <link rel="import" href="polymer-blink.html">
<link rel="import" href="polymer-bounce.html">
<link rel="import" href="polymer-fadein.html">
<link rel="import" href="polymer-fadeout.html">
<link rel="import" href="polymer-flip.html">
<link rel="import" href="polymer-shake.html">
-->
<style>
body {
text-align: center;
font-family: Helvetica, sans-serif;
}
div#target {
display: inline-block;
background-color: dimgrey;
border-radius: 5px;
padding: 5px 10px;
margin: 50px;
font-size: 30px;
color: white;
}
div.animations > * {
display: inline-block;
background-color: darkgrey;
border-radius: 5px;
padding: 5px 10px;
margin: 5px;
color: white;
}
</style>
</head>
<body>
<div id="target">animated!</div>
<div class="animations">
<core-animation id="raw" duration="1000">
raw
<core-animation-keyframe>
<core-animation-prop name="opacity" value="1">
</core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="opacity" value="0.3">
</core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="opacity" value="1">
</core-animation-prop>
</core-animation-keyframe>
</core-animation>
<core-animation-group type="seq">
raw group
<core-animation duration="300">
<core-animation-keyframe>
<core-animation-prop name="opacity" value="1">
</core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="opacity" value="0.3">
</core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="opacity" value="1">
</core-animation-prop>
</core-animation-keyframe>
</core-animation>
<core-animation duration="300">
<core-animation-keyframe>
<core-animation-prop name="transform" value="scale(1)">
</core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="transform" value="scale(1.2)">
</core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="transform" value="scale(1)">
</core-animation-prop>
</core-animation-keyframe>
</core-animation>
</core-animation-group>
<core-animation id="custom-animation" duration="500">custom</core-animation>
<core-animation duration="1000" iterations="Infinity" direction="alternate">
infinite
<core-animation-keyframe>
<core-animation-prop name="opacity" value="1">
</core-animation-prop>
</core-animation-keyframe>
<core-animation-keyframe>
<core-animation-prop name="opacity" value="0.3">
</core-animation-prop>
</core-animation-keyframe>
</core-animation>
<!-- <polymer-bounce duration="1000">bounce</polymer-bounce>
<polymer-shake>shake</polymer-shake>
<polymer-flip>flip X</polymer-flip>
<polymer-flip axis="y">flip Y</polymer-flip>
<polymer-blink>blink</polymer-blink>
<polymer-fadein>fade in</polymer-fadein>
--> </div>
<script>
var customAnimationFn = function(timeFraction, target) {
if (timeFraction < 1) {
target.textContent = timeFraction;
} else {
target.textContent = 'animated!';
}
};
document.addEventListener('polymer-ready', function() {
document.querySelector('.animations').addEventListener('click',
function(e) {
var animation = e.target;
if (animation.id === 'custom-animation') {
animation.customEffect = customAnimationFn;
}
animation.target = target;
animation.play();
});
document.getElementById('raw').addEventListener(
'core-animation-finish', function(e) {
console.log('finish!');
});
});
</script>
</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='["core-animation.html", "core-animation-group.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
-->
<script src="../web-animations-js/web-animations.js"></script>
{
"name": "core-collapse",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
},
"homepage": "https://github.com/Polymer/core-collapse",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "5cf45f3f12f9f7ed148499f0a0d51ace2ec5be27"
},
"_source": "git://github.com/Polymer/core-collapse.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-collapse"
}
{
"name": "core-collapse",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
}
}
/*
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 /deep/ core-collapse {
display: block;
}
html /deep/ .core-collapse-closed {
display: 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
-->
<!--
`core-collapse` creates a collapsible block of content. By default, the content
will be collapsed. Use `opened` to show/hide the content.
<button on-click="{{toggle}}">toggle collapse</button>
<core-collapse id="collapse">
...
</core-collapse>
...
toggle: function() {
this.$.collapse.toggle();
}
@group Polymer Core Elements
@element core-collapse
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="stylesheet" href="core-collapse.css" shim-shadowdom>
<polymer-element name="core-collapse" attributes="target horizontal opened duration fixedSize">
<template>
<content></content>
</template>
<script>
Polymer('core-collapse', {
/**
* Fired when the `core-collapse`'s `opened` property changes.
*
* @event core-collapse-open
*/
/**
* Fired when the target element has been resized as a result of the opened
* state changing.
*
* @event core-resize
*/
/**
* The target element.
*
* @attribute target
* @type object
* @default null
*/
target: null,
/**
* If true, the orientation is horizontal; otherwise is vertical.
*
* @attribute horizontal
* @type boolean
* @default false
*/
horizontal: false,
/**
* Set opened to true to show the collapse element and to false to hide it.
*
* @attribute opened
* @type boolean
* @default false
*/
opened: false,
/**
* Collapsing/expanding animation duration in second.
*
* @attribute duration
* @type number
* @default 0.33
*/
duration: 0.33,
/**
* If true, the size of the target element is fixed and is set
* on the element. Otherwise it will try to
* use auto to determine the natural size to use
* for collapsing/expanding.
*
* @attribute fixedSize
* @type boolean
* @default false
*/
fixedSize: false,
created: function() {
this.transitionEndListener = this.transitionEnd.bind(this);
},
ready: function() {
this.target = this.target || this;
},
domReady: function() {
this.async(function() {
this.afterInitialUpdate = true;
});
},
detached: function() {
if (this.target) {
this.removeListeners(this.target);
}
},
targetChanged: function(old) {
if (old) {
this.removeListeners(old);
}
if (!this.target) {
return;
}
this.isTargetReady = !!this.target;
this.classList.toggle('core-collapse-closed', this.target !== this);
this.target.style.overflow = 'hidden';
this.horizontalChanged();
this.addListeners(this.target);
// set core-collapse-closed class initially to hide the target
this.toggleClosedClass(true);
this.update();
},
addListeners: function(node) {
node.addEventListener('transitionend', this.transitionEndListener);
},
removeListeners: function(node) {
node.removeEventListener('transitionend', this.transitionEndListener);
},
horizontalChanged: function() {
this.dimension = this.horizontal ? 'width' : 'height';
},
openedChanged: function() {
this.update();
this.fire('core-collapse-open', this.opened);
},
/**
* Toggle the opened state.
*
* @method toggle
*/
toggle: function() {
this.opened = !this.opened;
},
setTransitionDuration: function(duration) {
var s = this.target.style;
s.transition = duration ? (this.dimension + ' ' + duration + 's') : null;
if (duration === 0) {
this.async('transitionEnd');
}
},
transitionEnd: function() {
if (this.opened && !this.fixedSize) {
this.updateSize('auto', null);
}
this.setTransitionDuration(null);
this.toggleClosedClass(!this.opened);
this.asyncFire('core-resize', null, this.target);
},
toggleClosedClass: function(closed) {
this.hasClosedClass = closed;
this.target.classList.toggle('core-collapse-closed', closed);
},
updateSize: function(size, duration, forceEnd) {
this.setTransitionDuration(duration);
this.calcSize();
var s = this.target.style;
var nochange = s[this.dimension] === size;
s[this.dimension] = size;
// transitonEnd will not be called if the size has not changed
if (forceEnd && nochange) {
this.transitionEnd();
}
},
update: function() {
if (!this.target) {
return;
}
if (!this.isTargetReady) {
this.targetChanged();
}
this.horizontalChanged();
this[this.opened ? 'show' : 'hide']();
},
calcSize: function() {
return this.target.getBoundingClientRect()[this.dimension] + 'px';
},
getComputedSize: function() {
return getComputedStyle(this.target)[this.dimension];
},
show: function() {
this.toggleClosedClass(false);
// for initial update, skip the expanding animation to optimize
// performance e.g. skip calcSize
if (!this.afterInitialUpdate) {
this.transitionEnd();
return;
}
if (!this.fixedSize) {
this.updateSize('auto', null);
var s = this.calcSize();
if (s == '0px') {
this.transitionEnd();
return;
}
this.updateSize(0, null);
}
this.async(function() {
this.updateSize(this.size || s, this.duration, true);
});
},
hide: function() {
// don't need to do anything if it's already hidden
if (this.hasClosedClass && !this.fixedSize) {
return;
}
if (this.fixedSize) {
// save the size before hiding it
this.size = this.getComputedSize();
} else {
this.updateSize(this.calcSize(), null);
}
this.async(function() {
this.updateSize(0, this.duration);
});
}
});
</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
-->
<!doctype html>
<html>
<head>
<title>core-collapse</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-collapse.html">
<style>
body {
overflow: auto;
margin: 8px 24px;
}
.box {
background: #eee;
}
.content {
margin: 10px;
}
section {
padding: 10px;
}
</style>
</head>
<body unresolved>
<section style="background: steelblue;">
<button onclick="document.querySelector('#collapse1').toggle()">toggle collapse</button>
<core-collapse id="collapse1" fixedSize class="box" style="height: 300px;">
<div class="content">Forma temperiemque cornua sidera dissociata cornua recessit innabilis ligavit: solidumque coeptis nullus caelum sponte phoebe di regat mentisque tanta austro capacius amphitrite sui quin postquam semina fossae liquidum umor galeae coeptis caligine liberioris quin liquidum matutinis invasit posset: flexi glomeravit radiis certis invasit oppida postquam onerosior inclusum dominari opifex terris pace finxit quam aquae nunc sine altae auroram quam habentem homo totidemque scythiam in pondus ensis tegit caecoque poena lapidosos humanas coeperunt poena aetas totidem nec natura aethera locavit caelumque distinxit animalibus phoebe cingebant moderantum porrexerat terrae possedit sua sole diu summaque obliquis melioris orbem</div>
</core-collapse>
</section>
<section style="background: seagreen;">
<button onclick="document.querySelector('#collapse2').toggle()">toggle collapse</button>
<core-collapse id="collapse2" class="box">
<div class="content">Coercuit iunctarum vix sic aberant spisso imagine litem cetera nubes ambitae tanta usu circumfuso fulminibus umentia rectumque iuga pluviaque meis semina regat ne campoque meis coeperunt nix cura iunctarum ligavit: secant ventos seductaque permisit sic iunctarum locoque his coeptis tum terras animalia recepta aethera cornua invasit tollere videre tonitrua humanas otia tuba alta dissociata sanctius adsiduis inclusum caesa ita onus sine pluviaque litem manebat fixo extendi ubi inposuit cum sublime membra undas orba forma deducite aethera turba coercuit retinebat obliquis bracchia nisi mentisque origine peregrinum manebat</div>
<section style="background: lightgreen;">
<button onclick="document.querySelector('#collapse3').toggle()">toggle collapse</button>
<core-collapse id="collapse3" class="box" opened>
<div class="content">Forma temperiemque cornua sidera dissociata cornua recessit innabilis ligavit: solidumque coeptis nullus caelum sponte phoebe di regat mentisque tanta austro capacius amphitrite sui quin postquam semina fossae liquidum umor galeae coeptis caligine liberioris quin liquidum matutinis invasit posset: flexi glomeravit radiis certis invasit oppida postquam onerosior inclusum dominari opifex terris pace finxit quam aquae nunc sine altae auroram quam habentem homo totidemque scythiam in pondus ensis tegit caecoque poena lapidosos humanas coeperunt poena aetas totidem nec natura aethera locavit caelumque distinxit animalibus phoebe cingebant moderantum porrexerat terrae possedit sua sole diu summaque obliquis melioris orbem</div>
<section style="background: #00FF99;">
<button onclick="document.querySelector('#collapse4').toggle()">toggle collapse</button>
<core-collapse id="collapse4" class="box">
<div class="content">Forma temperiemque cornua sidera dissociata cornua recessit innabilis ligavit: solidumque coeptis nullus caelum sponte phoebe di regat mentisque tanta austro capacius amphitrite sui quin postquam semina fossae liquidum umor galeae coeptis caligine liberioris quin liquidum matutinis invasit posset: flexi glomeravit radiis certis invasit oppida postquam onerosior inclusum dominari opifex terris pace finxit quam aquae nunc sine altae auroram quam habentem homo totidemque scythiam in pondus ensis tegit caecoque poena lapidosos humanas coeperunt poena aetas totidem nec natura aethera locavit caelumque distinxit animalibus phoebe cingebant moderantum porrexerat terrae possedit sua sole diu summaque obliquis melioris orbem</div>
</core-collapse>
</section>
</core-collapse>
</section>
<div class="content">Obstabatque cingebant nitidis rapidisque cepit moderantum discordia habentia frigore solidumque fert inter caecoque sine coeperunt corpore quarum fluminaque coercuit vultus animal austro quem os sectamque animus origo solidumque quoque melioris adspirate recepta utramque rapidisque caelumque orba unus pluviaque erant mutastis gravitate illic quisque alta calidis speciem mixtam ante contraria duae</div>
</core-collapse>
</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>
<!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>core-collapse</title>
<script src="../../../platform/platform.js"></script>
<script src="../../../polymer-test-tools/chai/chai.js"></script>
<script src="../../../polymer-test-tools/htmltest.js"></script>
<link rel="import" href="../../core-collapse.html">
</head>
<body unresolved>
<button onclick="document.querySelector('#collapse').toggle()">toggle collapse</button>
<core-collapse id="collapse" duration="0.1" opened>
<div>
Forma temperiemque cornua sidera dissociata cornua recessit innabilis ligavit: solidumque coeptis nullus caelum sponte phoebe di regat mentisque tanta austro capacius amphitrite sui quin postquam semina fossae liquidum umor galeae coeptis caligine liberioris quin liquidum matutinis invasit posset: flexi glomeravit radiis certis invasit oppida postquam onerosior inclusum dominari opifex terris pace finxit quam aquae nunc sine altae auroram quam habentem homo totidemque scythiam in pondus ensis tegit caecoque poena lapidosos humanas coeperunt poena aetas totidem nec natura aethera locavit caelumque distinxit animalibus phoebe cingebant moderantum porrexerat terrae possedit sua sole diu summaque obliquis melioris orbem
</div>
</core-collapse>
<script>
var delay = 200;
document.addEventListener('polymer-ready', function() {
var assert = chai.assert;
var c = document.querySelector('#collapse');
// verify take attribute for opened is correct
assert.equal(c.opened, true);
setTimeout(function() {
// get the height for the opened state
var h = getCollapseComputedStyle().height;
// verify the height is not 0px
assert.notEqual(getCollapseComputedStyle().height, '0px');
// close it
c.opened = false;
Platform.flush();
setTimeout(function() {
// verify is closed
assert.notEqual(getCollapseComputedStyle().height, h);
// open it
c.opened = true;
Platform.flush();
setTimeout(function() {
// verify is opened
assert.equal(getCollapseComputedStyle().height, h);
done();
}, delay);
}, delay);
}, delay);
});
function getCollapseComputedStyle() {
var b = document.querySelector('#collapse');
return getComputedStyle(b);
}
</script>
</body>
</html>
htmlSuite('core-collapse', function() {
htmlTest('html/core-collapse.html');
});
<!doctype htmlz>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>Web Component Test Runner</title>
<script src="../../polymer-test-tools/ci-support.js"></script>
</head>
<body>
<script>
runTests('tests.json');
</script>
</body>
</html>
{
"tools": ["chai", "mocha-tdd"],
"tests": [
"js/htmltests.js"
]
}
{
"name": "core-component-page",
"private": true,
"dependencies": {
"platform": "Polymer/platform#^0.4.0",
"polymer": "Polymer/polymer#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-component-page",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "e1e750856224647d37cac4614b3b14cf57fcb37d"
},
"_source": "git://github.com/Polymer/core-component-page.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-component-page"
}
�PNG

IHDR@@�iq� pHYs  ��
OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*! J�!��Q�EEȠ�����Q, �
��!���������{�kּ������>���� �H3Q5� �B�������.@�
$p�d!s�#�~<<+"��x� �M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'�����{[�!�� e�Dh;��V�EX0fK�9�-0IWfH���� � 0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4���������x����6��_-��"bb���ϫp@�t~��,/��;�m��%�h^ �u��f�@����W�p�~<<E���������J�B[a�W}�g�_�W�l�~<�����$�2]�G�����L�ϒ �b��G� ���"�Ib�X*�Qq�D���2�"�B�)�%��d��,�>�5�j>{�-�]c�K'Xt����o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A��,���� �`6�B$��BB
d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(�� A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2��G1���Q=� �C��7�F� �dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8, �c˱"� ���V����cϱw�E� 6wB aAHXLXN�H� $4� 7 �Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[
�b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w ��Ljg(�gw��L�Ӌ�T071���oUX*�*|��
�J�&�*/T����ު U�U�T��^S}�FU3S� Ԗ�U��P�SSg�;���g�oT?�~Y�Y�L�OC�Q��_�� c�x,!k ��u�5�&���|v*�����=���9C3J3W�R�f?�q�tN �(���~���)�)�4L�1e\k����X�H�Q�G�6�?��E�Y�A�J'\'Gg����S�Sݧ
�M=:��.�k���Dw�n��^��Lo��y���}/�T�m��G X� $� �<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��= ���Z~s�r:V:ޚΜ�?}����/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z��������ۯ�6�i�ܟ�4�)�Y3s���C�Q��? ��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�������!h�쐭!��Α�i�P~���a�a��~ '���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl������� �{�/�]py�����.,:�@L�N8��A*��%�w%�
y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y-
�B��TZ(�*�geWf�͉�9���+��̳�ې7�����ᒶ��KW-X潬j9�<qy�
�+�V�<���*m�O��W��~�&zMk�^�ʂ��k� U
�}����]OX/Yߵa�>������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n �ڴ �V����E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa��n��{��4���[���>ɾ�UUM�f�e�I��?������m]�Nmq����#�׹���=TR��+�G�����w- 6 U����#pDy��� �� :�v�{���vg/jB��F�S��[b[�O�>����z�G��4<YyJ�T�i��ӓg�ό���}~.��`ۢ�{�c��jo�t��E���;�;�\�t���W�W��:_m�t�<���Oǻ�����\k��z��{f���7����y���՞9=ݽ�zo������~r'��˻�w'O�_�@�A�C݇�?[�����j�w����G��������C���ˆ ��8>99�?r���C�d�&����ˮ/~�����јѡ�򗓿m|������������x31^�V���w�w��O�| (�h��SЧ�������c3-� cHRMz%������u0�`:�o�_�F XIDATx��[]�dG���;=ݽӻ3�}{z�'������#��'+�!�0/B����d}I�H���A0�1�H����!?dwf�g�wf��t��ULJ����t���NG�)(��[u�W���Ω;��M�o�p�!�p��ۂ����ɓ'GZ�Z{���~j�Rjg����ӝ�,//��N�������X�~m�\B��y� ��{_*��<�����+++�ӑ�I�ZKt@���n��y�$�p�;�������sW���������Э���s?�� V*�#$�pJDb�\]]�݉'���� �ɏZko�7wB)(�y��Rou[���җD�s$�����j��3���r�<��~�)km½��<���zeii�� �cz.����JEr�s���YZZ���"bDD�R�kƘ�kkk7�@�����*�@R��$s"bE�:K|&�u�����3w#"6���1����z4�0H��G�e�5�M�Z`�ZkdOr����~�{������5����2��7 2I�׃ h���}�o;���A�"�N��u7F���z�H2PJ?��+�H2�����t49h<ʲ���<�-�ʟݩ��w�̖�A�d;p Σ����g��z�R�]�?�<$������e���$I�^��~ 8���d��6���Er�d@����Wy�n���"�t��A��ǝ�ڴ���f�(�6RB�P(�r�܃>E�*�L��)"���0 X__���g�L��J��9���=���f��(��S;&��5??fvv�1�'\���H^�V��rV SO�����"R���F��tEUm�������f��xZDVH�^��Z G��r�|�� ��ɇ��Ϊ"�����Z��VJ�6�NW��[���j�ۿ�������C�b�p��P�R9�C�p���%iE�'�O�����~����_�Tny�Z�z�4��r���y��ttY�|��]�쓤�� �4�9k��I�EDH�J�`�������.S�Tl��RH�Z��}�/d��O�0��f��R��B�KDΐ�4<6�c���q�g�1�#�G��F��CU?廀�>�6��R��A_�l�c��8Y�0�p `�^��0�c�RE��JF(�y�a��u "��2�h����a��Pp�,..��+�0�a-`X�8l����& )�|i��F�BG�٦ KZk����Zkmiaa!7D-,,��ڒ�lHBkM��rY;Yo+����og��j���RJ ,q���� ~9N��������\���$I^���_�Z�0<@9�2.>k*��)
_vEN�k�����FuX?P����=~L2�0IO�_���q�� Յ��ė�&9�5i@'��F�ӹ�r6��[ Z���ŹX�R�$�<�WW�N�RǍ�li�u;|���I�oooo�A��+��LD\�LE�!��=n�~��v_������FZ&דa#��#�x���a7I�߻c�s�D��Z+"g<�q��P��qO��Y�̠��vk�v=I�N�=g� ���������"�uk�m��RH�W��o鬯�?�vܛ����$���-��H歵ɠ�+"0��%PPJ��RaӤ��ܯb�����s�z��r�M��^A|m�_��'nv��(�֞�U�I`�\~TDBg�S+�;�"� ��w� �J���< ����5��<\*�*��͐R�~9wv��q*������4���H��:�{�q�
ɫJ)��>F+���J)�y�0�����n���kx&H�jǯ�k�A�g���������w=n\=_����t~����Z�X�x_��'UC\��d=I�����_�e2����q�g�RJ�v�ƍ4��M��C~�z\y���
������������\JPǎ;��d>C�c�^�������i{{���9J��#$?Kr�rE?l�Z�).`G��pK�2������w:�W�(��ؘ��~A6�=Z(~�+��SE�p���Y?�� ��b&�9�l6��*���A!��@���l�Z�|e
�^Wy�6qo=z��z�"�N�[)Z�� ��h�Jj��I*G�2A�P)`�o~�/"W�&ysw��p%��Mj ���g�65fl&8�{�6�4ӥ�����j5H��W�֟�QN�1抷����4��Z�Ɣ5 �D$d�%}�V�q�����v�r.�k��u�������9U(Ez-��tv���FY˝�YW]
R<��|Q�L����Ǫ�:E{��gXn��S9c� t9O;M�� �t��^2�̊��9z��C8��n�[۠���0sIEND�B`�
{
"name": "core-component-page",
"private": true,
"dependencies": {
"platform": "Polymer/platform#^0.4.0",
"polymer": "Polymer/polymer#^0.4.0"
}
}
<!--
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>body{margin:0}</style>
<div hidden><link rel="import" href="../polymer/polymer.html"><polymer-element name="core-meta" attributes="label type" hidden assetpath="../core-meta/"><script>(function(){var SKIP_ID="meta";var metaData={},metaArray={};Polymer("core-meta",{type:"default",alwaysPrepare:true,ready:function(){this.register(this.id)},get metaArray(){var t=this.type;if(!metaArray[t]){metaArray[t]=[]}return metaArray[t]},get metaData(){var t=this.type;if(!metaData[t]){metaData[t]={}}return metaData[t]},register:function(id,old){if(id&&id!==SKIP_ID){this.unregister(this,old);this.metaData[id]=this;this.metaArray.push(this)}},unregister:function(meta,id){delete this.metaData[id||meta.id];var i=this.metaArray.indexOf(meta);if(i>=0){this.metaArray.splice(i,1)}},get list(){return this.metaArray},byId:function(id){return this.metaData[id]}})})();</script></polymer-element><polymer-element name="core-iconset" extends="core-meta" attributes="src width icons iconSize" assetpath="../core-iconset/"><script>Polymer("core-iconset",{src:"",width:0,icons:"",iconSize:24,offsetX:0,offsetY:0,type:"iconset",created:function(){this.iconMap={};this.iconNames=[];this.themes={}},ready:function(){if(this.src&&this.ownerDocument!==document){this.src=this.resolvePath(this.src,this.ownerDocument.baseURI)}this.super();this.updateThemes()},iconsChanged:function(){var ox=this.offsetX;var oy=this.offsetY;this.icons&&this.icons.split(/\s+/g).forEach(function(name,i){this.iconNames.push(name);this.iconMap[name]={offsetX:ox,offsetY:oy};if(ox+this.iconSize<this.width){ox+=this.iconSize}else{ox=this.offsetX;oy+=this.iconSize}},this)},updateThemes:function(){var ts=this.querySelectorAll("property[theme]");ts&&ts.array().forEach(function(t){this.themes[t.getAttribute("theme")]={offsetX:parseInt(t.getAttribute("offsetX"))||0,offsetY:parseInt(t.getAttribute("offsetY"))||0}},this)},getOffset:function(icon,theme){var i=this.iconMap[icon];if(!i){var n=this.iconNames[Number(icon)];i=this.iconMap[n]}var t=this.themes[theme];if(i&&t){return{offsetX:i.offsetX+t.offsetX,offsetY:i.offsetY+t.offsetY}}return i},applyIcon:function(element,icon,scale){var offset=this.getOffset(icon);scale=scale||1;if(element&&offset){var icon=element._icon||document.createElement("div");var style=icon.style;style.backgroundImage="url("+this.src+")";style.backgroundPosition=-offset.offsetX*scale+"px"+" "+(-offset.offsetY*scale+"px");style.backgroundSize=scale===1?"auto":this.width*scale+"px";if(icon.parentNode!==element){element.appendChild(icon)}return icon}}});</script></polymer-element><style shim-shadowdom="">html /deep/ core-icon{display:inline-block;vertical-align:middle;background-repeat:no-repeat;fill:currentcolor;position:relative;height:24px;width:24px}</style><polymer-element name="core-icon" attributes="src icon alt" assetpath="../core-icon/"><script>(function(){var meta;Polymer("core-icon",{src:"",icon:"",alt:null,observe:{icon:"updateIcon",alt:"updateAlt"},defaultIconset:"icons",ready:function(){if(!meta){meta=document.createElement("core-iconset")}if(this.hasAttribute("aria-label")){if(!this.hasAttribute("role")){this.setAttribute("role","img")}return}this.updateAlt()},srcChanged:function(){var icon=this._icon||document.createElement("div");icon.textContent="";icon.setAttribute("fit","");icon.style.backgroundImage="url("+this.src+")";icon.style.backgroundPosition="center";icon.style.backgroundSize="100%";if(!icon.parentNode){this.appendChild(icon)}this._icon=icon},getIconset:function(name){return meta.byId(name||this.defaultIconset)},updateIcon:function(oldVal,newVal){if(!this.icon){this.updateAlt();return}var parts=String(this.icon).split(":");var icon=parts.pop();if(icon){var set=this.getIconset(parts.pop());if(set){this._icon=set.applyIcon(this,icon);if(this._icon){this._icon.setAttribute("fit","")}}}if(oldVal){if(oldVal.split(":").pop()==this.getAttribute("aria-label")){this.updateAlt()}}},updateAlt:function(){if(this.getAttribute("aria-hidden")){return}if(this.alt===""){this.setAttribute("aria-hidden","true");if(this.hasAttribute("role")){this.removeAttribute("role")}if(this.hasAttribute("aria-label")){this.removeAttribute("aria-label")}}else{this.setAttribute("aria-label",this.alt||this.icon.split(":").pop());if(!this.hasAttribute("role")){this.setAttribute("role","img")}if(this.hasAttribute("aria-hidden")){this.removeAttribute("aria-hidden")}}}})})();</script></polymer-element><polymer-element name="core-iconset-svg" extends="core-meta" attributes="iconSize" assetpath="../core-iconset-svg/"><script>Polymer("core-iconset-svg",{iconSize:24,type:"iconset",created:function(){this._icons={}},ready:function(){this.super();this.updateIcons()},iconById:function(id){return this._icons[id]||(this._icons[id]=this.querySelector("#"+id))},cloneIcon:function(id){var icon=this.iconById(id);if(icon){var content=icon.cloneNode(true);content.removeAttribute("id");var svg=document.createElementNS("http://www.w3.org/2000/svg","svg");svg.setAttribute("viewBox","0 0 "+this.iconSize+" "+this.iconSize);svg.style.pointerEvents="none";svg.appendChild(content);return svg}},get iconNames(){if(!this._iconNames){this._iconNames=this.findIconNames()}return this._iconNames},findIconNames:function(){var icons=this.querySelectorAll("[id]").array();if(icons.length){return icons.map(function(n){return n.id})}},applyIcon:function(element,icon){var root=element;var old=root.querySelector("svg");if(old){old.remove()}var svg=this.cloneIcon(icon);if(!svg){return}svg.setAttribute("height","100%");svg.setAttribute("width","100%");svg.setAttribute("preserveAspectRatio","xMidYMid meet");svg.style.display="block";root.insertBefore(svg,root.firstElementChild);return svg},updateIcons:function(selector,method){selector=selector||"[icon]";method=method||"updateIcon";var deep=window.ShadowDOMPolyfill?"":"html /deep/ ";var i$=document.querySelectorAll(deep+selector);for(var i=0,e;e=i$[i];i++){if(e[method]){e[method].call(e)}}}});</script></polymer-element><core-iconset-svg id="icons" iconsize="24"><svg><defs><g id="accessibility"><path d="M12,2c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,2,12,2z M21,9h-6v13h-2v-6h-2v6H9V9H3V7h18V9z"/></g><g id="account-balance"><path d="M4,10v7h3v-7H4z M10,10v7h3v-7H10z M2,22h19v-3H2V22z M16,10v7h3v-7H16z M11.5,1L2,6v2h19V6L11.5,1z"/></g><g id="account-box"><path d="M3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5z M15,9c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3c0-1.7,1.3-3,3-3C13.7,6,15,7.3,15,9z M6,17c0-2,4-3.1,6-3.1s6,1.1,6,3.1v1H6V17z"/></g><g id="account-child"><path d="M16.5,12c1.4,0,2.5-1.1,2.5-2.5C19,8.1,17.9,7,16.5,7C15.1,7,14,8.1,14,9.5C14,10.9,15.1,12,16.5,12z M9,11c1.7,0,3-1.3,3-3s-1.3-3-3-3C7.3,5,6,6.3,6,8S7.3,11,9,11z M16.5,14c-1.8,0-5.5,0.9-5.5,2.7V19h11v-2.2C22,14.9,18.3,14,16.5,14z M9,13c-2.3,0-7,1.2-7,3.5V19h7v-2.2c0-0.8,0.3-2.3,2.4-3.5C10.5,13.1,9.7,13,9,13z"/></g><g id="account-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,5c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,6.3,10.3,5,12,5z M12,19.2c-2.5,0-4.7-1.3-6-3.2c0-2,4-3.1,6-3.1c2,0,6,1.1,6,3.1C16.7,17.9,14.5,19.2,12,19.2z"/></g><g id="add"><path d="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6V13z"/></g><g id="add-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g><g id="add-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g><g id="add-circle-outline"><path d="M13,7h-2v4H7v2h4v4h2v-4h4v-2h-4V7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g><g id="add-shopping-cart"><polygon points="18.3,6 18.3,6 15.6,11 "><path d="M11,9h2V6h3V4h-3V1h-2v3H8v2h3V9z M7,18c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S8.1,18,7,18z M17,18c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S18.1,18,17,18z M7.2,14.8c0,0,0-0.1,0-0.1L8.1,13h7.4c0.8,0,1.4-0.4,1.7-1l3.9-7l-1.7-1h0l-1.1,2l-2.8,5h-7l-0.1-0.3L6.2,6L5.2,4L4.3,2H1v2h2l3.6,7.6L5.2,14C5.1,14.3,5,14.7,5,15c0,1.1,0.9,2,2,2h12v-2H7.4C7.3,15,7.2,14.9,7.2,14.8z"/></polygon></g><g id="alarm"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g><g id="alarm-add"><path d="M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z M13,9h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g><g id="alarm-off"><path d="M12,6c3.9,0,7,3.1,7,7c0,0.8-0.2,1.6-0.4,2.4l1.5,1.5c0.6-1.2,0.9-2.5,0.9-3.9c0-5-4-9-9-9c-1.4,0-2.7,0.3-3.9,0.9l1.5,1.5C10.4,6.2,11.2,6,12,6z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M2.9,2.3L1.6,3.6L3,4.9L1.9,5.8l1.4,1.4l1.1-0.9l0.8,0.8C3.8,8.7,3,10.7,3,13c0,5,4,9,9,9c2.3,0,4.3-0.8,5.9-2.2l2.2,2.2l1.3-1.3L3.9,3.3L2.9,2.3z M16.5,18.4c-1.2,1-2.8,1.6-4.5,1.6c-3.9,0-7-3.1-7-7c0-1.7,0.6-3.3,1.6-4.5L16.5,18.4z M8,3.3L6.6,1.9L5.7,2.6L7.2,4L8,3.3z"/></g><g id="alarm-on"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,16.9,15.9,20,12,20z M10.5,14.5l-2.1-2.1l-1.1,1.1l3.2,3.2l6-6l-1.1-1.1L10.5,14.5z"/></g><g id="android"><path d="M6,18c0,0.6,0.4,1,1,1h1v3.5C8,23.3,8.7,24,9.5,24c0.8,0,1.5-0.7,1.5-1.5V19h2v3.5c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5V19h1c0.6,0,1-0.4,1-1V8H6V18z M3.5,8C2.7,8,2,8.7,2,9.5v7C2,17.3,2.7,18,3.5,18C4.3,18,5,17.3,5,16.5v-7C5,8.7,4.3,8,3.5,8z M20.5,8C19.7,8,19,8.7,19,9.5v7c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5v-7C22,8.7,21.3,8,20.5,8z M15.5,2.2l1.3-1.3c0.2-0.2,0.2-0.5,0-0.7c-0.2-0.2-0.5-0.2-0.7,0l-1.5,1.5C13.9,1.2,13,1,12,1c-1,0-1.9,0.2-2.7,0.6L7.9,0.1C7.7,0,7.3,0,7.1,0.1C7,0.3,7,0.7,7.1,0.9l1.3,1.3C7,3.3,6,5,6,7h12C18,5,17,3.2,15.5,2.2z M10,5H9V4h1V5z M15,5h-1V4h1V5z"/></g><g id="announcement"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M13,11h-2V5h2V11z M13,15h-2v-2h2V15z"/></g><g id="apps"><path d="M4,8h4V4H4V8z M10,20h4v-4h-4V20z M4,20h4v-4H4V20z M4,14h4v-4H4V14z M10,14h4v-4h-4V14z M16,4v4h4V4H16z M10,8h4V4h-4V8z M16,14h4v-4h-4V14z M16,20h4v-4h-4V20z"/></g><g id="archive"><path d="M20.5,5.2l-1.4-1.7C18.9,3.2,18.5,3,18,3H6C5.5,3,5.1,3.2,4.8,3.5L3.5,5.2C3.2,5.6,3,6,3,6.5V19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6.5C21,6,20.8,5.6,20.5,5.2z M12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5z M5.1,5l0.8-1h12l0.9,1H5.1z"/></g><g id="arrow-back"><path d="M20,11H7.8l5.6-5.6L12,4l-8,8l8,8l1.4-1.4L7.8,13H20V11z"/></g><g id="arrow-drop-down"><polygon points="7,10 12,15 17,10 "></polygon></g><g id="arrow-drop-down-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,14l-4-4h8L12,14z"/></g><g id="arrow-drop-up"><polygon points="7,14 12,9 17,14 "></polygon></g><g id="arrow-forward"><polygon points="12,4 10.6,5.4 16.2,11 4,11 4,13 16.2,13 10.6,18.6 12,20 20,12 "></polygon></g><g id="aspect-ratio"><path d="M19,12h-2v3h-3v2h5V12z M7,9h3V7H5v5h2V9z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g><g id="assessment"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g><g id="assignment"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M14,17H7v-2h7V17z M17,13H7v-2h10V13z M17,9H7V7h10V9z"/></g><g id="assignment-ind"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,7c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,8.3,10.3,7,12,7z M18,19H6v-1.4c0-2,4-3.1,6-3.1s6,1.1,6,3.1V19z"/></g><g id="assignment-late"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g><g id="assignment-return"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,3,12,3z M16,15h-4v3l-5-5l5-5v3h4V15z"/></g><g id="assignment-returned"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,18l-5-5h3V9h4v4h3L12,18z"/></g><g id="attachment"><path d="M7.5,18c-3,0-5.5-2.5-5.5-5.5S4.5,7,7.5,7H18c2.2,0,4,1.8,4,4s-1.8,4-4,4H9.5C8.1,15,7,13.9,7,12.5S8.1,10,9.5,10H17v1.5H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H18c1.4,0,2.5-1.1,2.5-2.5S19.4,8.5,18,8.5H7.5c-2.2,0-4,1.8-4,4s1.8,4,4,4H17V18H7.5z"/></g><g id="backspace"><path d="M22,3H7C6.3,3,5.8,3.3,5.4,3.9L0,12l5.4,8.1C5.8,20.6,6.3,21,7,21h15c1.1,0,2-0.9,2-2V5C24,3.9,23.1,3,22,3z M19,15.6L17.6,17L14,13.4L10.4,17L9,15.6l3.6-3.6L9,8.4L10.4,7l3.6,3.6L17.6,7L19,8.4L15.4,12L19,15.6z"/></g><g id="backup"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M14,13v4h-4v-4H7l5-5l5,5H14z"/></g><g id="block"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M4,12c0-4.4,3.6-8,8-8c1.8,0,3.5,0.6,4.9,1.7L5.7,16.9C4.6,15.5,4,13.8,4,12z M12,20c-1.8,0-3.5-0.6-4.9-1.7L18.3,7.1C19.4,8.5,20,10.2,20,12C20,16.4,16.4,20,12,20z"/></g><g id="book"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g><g id="bookmark"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z"/></g><g id="bookmark-outline"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z M17,18l-5-2.2L7,18V5h10V18z"/></g><g id="bug-report"><path d="M20,8h-2.8c-0.5-0.8-1.1-1.5-1.8-2L17,4.4L15.6,3l-2.2,2.2C13,5.1,12.5,5,12,5s-1,0.1-1.4,0.2L8.4,3L7,4.4L8.6,6C7.9,6.5,7.3,7.2,6.8,8H4v2h2.1C6,10.3,6,10.7,6,11v1H4v2h2v1c0,0.3,0,0.7,0.1,1H4v2h2.8c1,1.8,3,3,5.2,3s4.2-1.2,5.2-3H20v-2h-2.1c0.1-0.3,0.1-0.7,0.1-1v-1h2v-2h-2v-1c0-0.3,0-0.7-0.1-1H20V8z M14,16h-4v-2h4V16z M14,12h-4v-2h4V12z"/></g><g id="cached"><path d="M19,8l-4,4h3c0,3.3-2.7,6-6,6c-1,0-2-0.3-2.8-0.7l-1.5,1.5C9,19.5,10.4,20,12,20c4.4,0,8-3.6,8-8h3L19,8z M6,12c0-3.3,2.7-6,6-6c1,0,2,0.3,2.8,0.7l1.5-1.5C15,4.5,13.6,4,12,4c-4.4,0-8,3.6-8,8H1l4,4l4-4H6z"/></g><g id="cancel"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g><g id="check"><polygon points="9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6 "></polygon></g><g id="check-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g><g id="check-box-blank"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g><g id="check-box-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M19,19L5,19V5h10V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-8h-2V19z"/></g><g id="check-box-outline-blank"><path d="M19,5v14L5,19V5H19 M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3L19,3z"/></g><g id="check-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g><g id="check-circle-blank"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z"/></g><g id="check-circle-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M20,12c0,4.4-3.6,8-8,8s-8-3.6-8-8s3.6-8,8-8c0.8,0,1.5,0.1,2.2,0.3l1.6-1.6C14.6,2.3,13.3,2,12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10H20z"/></g><g id="check-circle-outline-blank"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g><g id="chevron-left"><polygon points="15.4,7.4 14,6 8,12 14,18 15.4,16.6 10.8,12 "></polygon></g><g id="chevron-right"><polygon points="10,6 8.6,7.4 13.2,12 8.6,16.6 10,18 16,12 "></polygon></g><g id="class"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g><g id="clear"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "></polygon></g><g id="close"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "></polygon></g><g id="cloud"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z"/></g><g id="cloud-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M16.5,16c0,0-8.5,0-8.5,0c-1.7,0-3-1.3-3-3s1.3-3,3-3c0,0,0.1,0,0.1,0c0.4-1.7,2-3,3.9-3c2.2,0,4,1.8,4,4h0.5c1.4,0,2.5,1.1,2.5,2.5C19,14.9,17.9,16,16.5,16z"/></g><g id="cloud-done"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M10,17l-3.5-3.5l1.4-1.4l2.1,2.1L15.2,9l1.4,1.4L10,17z"/></g><g id="cloud-download"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M17,13l-5,5l-5-5h3V9h4v4H17z"/></g><g id="cloud-off"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6c-1.5,0-2.9,0.4-4,1.2l1.5,1.5C10.2,6.2,11.1,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3c0,1.1-0.6,2.1-1.6,2.6l1.5,1.5c1.3-0.9,2.1-2.4,2.1-4.1C24,12.4,21.9,10.2,19.4,10z M3,5.3L5.8,8C2.6,8.2,0,10.8,0,14c0,3.3,2.7,6,6,6h11.7l2,2l1.3-1.3L4.3,4L3,5.3z M7.7,10l8,8H6c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4H7.7z"/></g><g id="cloud-queue"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M19,18H6c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4h0.7C7.4,7.7,9.5,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3S20.7,18,19,18z"/></g><g id="cloud-upload"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M14,13v4h-4v-4H7l5-5l5,5H14z"/></g><g id="content-copy"><path d="M16,1H4C2.9,1,2,1.9,2,3v14h2V3h12V1z M19,5H8C6.9,5,6,5.9,6,7v14c0,1.1,0.9,2,2,2h11c1.1,0,2-0.9,2-2V7C21,5.9,20.1,5,19,5z M19,21H8V7h11V21z"/></g><g id="content-cut"><path d="M10,6c0-2.2-1.8-4-4-4S2,3.8,2,6c0,2.2,1.8,4,4,4c0.6,0,1.1-0.1,1.6-0.4L10,12l-2.4,2.4C7.1,14.1,6.6,14,6,14c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4s4-1.8,4-4c0-0.6-0.1-1.1-0.4-1.6L12,14l7,7h4L9.6,7.6C9.9,7.1,10,6.6,10,6z M6,8C4.9,8,4,7.1,4,6s0.9-2,2-2c1.1,0,2,0.9,2,2S7.1,8,6,8z M6,20c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S7.1,20,6,20z M12,11.5c0.3,0,0.5,0.2,0.5,0.5c0,0.3-0.2,0.5-0.5,0.5c-0.3,0-0.5-0.2-0.5-0.5C11.5,11.7,11.7,11.5,12,11.5z M23,3h-4l-6,6l2,2L23,3z"/></g><g id="content-paste"><path d="M19,2h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,2,3,2.9,3,4v16c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V4C21,2.9,20.1,2,19,2z M12,2c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,2,12,2z M19,20H5V4h2v3h10V4h2V20z"/></g><g id="create"><path d="M3,17.2V21h3.8L17.8,9.9l-3.8-3.8L3,17.2z M20.7,7c0.4-0.4,0.4-1,0-1.4l-2.3-2.3c-0.4-0.4-1-0.4-1.4,0l-1.8,1.8l3.8,3.8L20.7,7z"/></g><g id="credit-card"><path d="M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18H4v-6h16V18z M20,8H4V6h16V8z"/></g><g id="delete"><path d="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z M19,4h-3.5l-1-1h-5l-1,1H5v2h14V4z"/></g><g id="description"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,18H8v-2h8V18z M16,14H8v-2h8V14z M13,9V3.5L18.5,9H13z"/></g><g id="developer-mode-tv"><path d="M4,5h16v2h2l0-2c0-1.1-0.9-2-2-2H4C2.9,3,2,3.9,2,5v2h2V5z M7.6,13.8L4.7,11l2.8-2.8L6.1,6.8L1.9,11l4.2,4.2L7.6,13.8z M20,17H4v-2H2v2c0,1.1,0.9,2,2,2h4v2h8v-2h4c1.1,0,2-0.9,2-2l0-2h-2V17z M22,11l-4.2-4.2l-1.4,1.4l2.8,2.8l-2.8,2.8l1.4,1.4L22,11L22,11L22,11L22,11L22,11z"/></g><g id="done"><polygon points="9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6 "></polygon></g><g id="done-all"><path d="M18,7l-1.4-1.4l-6.3,6.3l1.4,1.4L18,7z M22.2,5.6L11.7,16.2L7.5,12l-1.4,1.4l5.6,5.6l12-12L22.2,5.6z M0.4,13.4L6,19l1.4-1.4L1.8,12L0.4,13.4z"/></g><g id="drafts"><path d="M22,8c0-0.7-0.4-1.3-0.9-1.7L12,1L2.9,6.3C2.4,6.7,2,7.3,2,8v10c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2L22,8z M12,13L3.7,7.8L12,3l8.3,4.8L12,13z"/></g><g id="drawer"><path d="M12,8c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,8,12,8z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z M12,16c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,16,12,16z"/></g><g id="drive"><path d="M22.3,14L15.4,2H8.6l0,0l6.9,12H22.3z M9.7,15l-3.4,6h13.1l3.4-6H9.7z M7.7,3.5L1.2,15l3.4,6l6.6-11.5L7.7,3.5z"/></g><g id="drive-archive"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,18l-4-4h8L12,18z M16,12H8v-2h8V12z M16,8H8V6h8V8z"/></g><g id="drive-audio"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M7.2,18C6.5,18,6,17.5,6,16.8v-3.6V12c0-3.3,2.7-6,6-6s6,2.7,6,6v1.2v3.6c0,0.7-0.5,1.2-1.2,1.2H14v-4h2v-2c0-2.2-1.8-4-4-4s-4,1.8-4,4v2h2v4H7.2z"/></g><g id="drive-chart"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g><g id="drive-document"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17,9H7V7h10V9z M17,13H7v-2h10V13z M14,17H7v-2h7V17z"/></g><g id="drive-drawing"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M18,18h-6v-5.8c-0.7,0.6-1.5,1-2.5,1c-2,0-3.7-1.7-3.7-3.7s1.7-3.7,3.7-3.7c2,0,3.7,1.7,3.7,3.7c0,1-0.4,1.8-1,2.5H18V18z"/></g><g id="drive-file"><path d="M6,2C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8l-6-6H6z M13,9V3.5L18.5,9H13z"/></g><g id="drive-file-move"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M9,18v-3H5v-4h4V8l5,5L9,18z"/></g><g id="drive-file-rename"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M6,17v-2.5l7.9-7.9c0.2-0.2,0.5-0.2,0.7,0l1.8,1.8c0.2,0.2,0.2,0.5,0,0.7L8.5,17H6z M18,17h-7.5l2-2H18V17z"/></g><g id="drive-form"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-2h2V17z M9,13H7v-2h2V13z M9,9H7V7h2V9z M17,17h-7v-2h7V17z M17,13h-7v-2h7V13z M17,9h-7V7h7V9z"/></g><g id="drive-fusiontable"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,10.2L13,17l-4-4l-4,4v-3l4-4l4,4l6-6.8V10.2z"/></g><g id="drive-image"><path d="M21,19V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14C20.1,21,21,20.1,21,19z M8.5,13.5l2.5,3l3.5-4.5l4.5,6H5L8.5,13.5z"/></g><g id="drive-keep"><path d="M9,21c0,0.6,0.4,1,1,1h4c0.6,0,1-0.4,1-1v-1H9V21z M12,2C8.1,2,5,5.1,5,9c0,2.4,1.2,4.5,3,5.7V17c0,0.6,0.4,1,1,1h6c0.6,0,1-0.4,1-1v-2.3c1.8-1.3,3-3.4,3-5.7C19,5.1,15.9,2,12,2z"/></g><g id="drive-ms-excel"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M16.2,17h-2L12,13.2L9.8,17h-2l3.2-5L7.8,7h2l2.2,3.8L14.2,7h2L13,12L16.2,17z"/></g><g id="drive-ms-powerpoint"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9.8,13.4V17H8V7h4.3c1.5,0,2.2,0.3,2.8,0.9c0.7,0.6,0.9,1.4,0.9,2.3c0,1-0.3,1.8-0.9,2.3c-0.6,0.5-1.3,0.8-2.8,0.8H9.8z"/><path d="M9.8,12V8.4h2.3c0.7,0,1.2,0.2,1.5,0.6c0.3,0.4,0.5,0.7,0.5,1.2c0,0.6-0.2,0.9-0.5,1.3c-0.3,0.3-0.7,0.5-1.4,0.5H9.8z"/></g><g id="drive-ms-word"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M15.5,17H14l-2-7.5L10,17H8.5L6.1,7h1.7l1.5,7.5l2-7.5h1.4l2,7.5L16.2,7h1.7L15.5,17z"/></g><g id="drive-pdf"><path d="M11.3,8.6L11.3,8.6C11.4,8.6,11.4,8.6,11.3,8.6c0.1-0.4,0.2-0.6,0.2-0.9l0-0.2c0.1-0.5,0.1-0.9,0-1c0,0,0,0,0-0.1l-0.1-0.1c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0.1-0.1,0.1C11.1,7,11.1,7.7,11.3,8.6C11.3,8.6,11.3,8.6,11.3,8.6z M8.3,15.5c-0.2,0.1-0.4,0.2-0.5,0.3c-0.7,0.6-1.2,1.3-1.3,1.6c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0C7.1,17.3,7.7,16.7,8.3,15.5C8.4,15.5,8.4,15.5,8.3,15.5C8.4,15.5,8.3,15.5,8.3,15.5z M17.5,14c-0.1-0.1-0.5-0.4-1.9-0.4c-0.1,0-0.1,0-0.2,0c0,0,0,0,0,0c0,0,0,0,0,0.1c0.7,0.3,1.4,0.5,1.9,0.5c0.1,0,0.1,0,0.2,0l0,0c0,0,0.1,0,0.1,0c0,0,0,0,0-0.1c0,0,0,0,0,0C17.6,14.1,17.5,14.1,17.5,14z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17.9,14.8C17.7,14.9,17.4,15,17,15c-0.8,0-2-0.2-3-0.7c-1.7,0.2-3,0.4-4,0.8c-0.1,0-0.1,0-0.2,0.1c-1.2,2.1-2.2,3.1-3,3.1c-0.2,0-0.3,0-0.4-0.1l-0.5-0.3l0-0.1c-0.1-0.2-0.1-0.3-0.1-0.5c0.1-0.5,0.7-1.4,1.9-2.1c0.2-0.1,0.5-0.3,0.9-0.5c0.3-0.5,0.6-1.1,1-1.8c0.5-1,0.8-2,1.1-2.9l0,0c-0.4-1.2-0.6-1.9-0.2-3.3c0.1-0.4,0.4-0.8,0.8-0.8l0.2,0c0.2,0,0.4,0.1,0.6,0.2c0.7,0.7,0.4,2.3,0,3.6c0,0.1,0,0.1,0,0.1c0.4,1.1,1,2,1.6,2.6c0.3,0.2,0.5,0.4,0.9,0.6c0.5,0,0.9-0.1,1.3-0.1c1.2,0,2,0.2,2.3,0.7c0.1,0.2,0.1,0.4,0.1,0.6C18.2,14.3,18.1,14.6,17.9,14.8z M11.4,10.9c-0.2,0.7-0.6,1.5-1,2.4c-0.2,0.4-0.4,0.7-0.6,1.1c0,0,0.1,0,0.1,0l0.1,0v0c1.3-0.5,2.5-0.8,3.3-0.9c-0.2-0.1-0.3-0.2-0.4-0.3C12.4,12.6,11.8,11.8,11.4,10.9z"/></g><g id="drive-presentation"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,16H5V8h14V16z"/></g><g id="drive-script"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,4h0v6h0l0,4c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M11,17v-3H5v-4h6V7l5,5L11,17z"/></g><g id="drive-site"><path d="M19,4H5C3.9,4,3,4.9,3,6l0,12c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M14,18H5v-4h9V18z M14,13H5V9h9V13z M19,18h-4V9h4V18z"/></g><g id="drive-spreadsheet"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,3h0v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,11h-8v8H9v-8H5V9h4V5h2v4h8V11z"/></g><g id="drive-text"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,18H8v-2h8V18z M16,14H8v-2h8V14z M13,9V3.5L18.5,9H13z"/></g><g id="drive-video"><path d="M18,4l2,4h-3l-2-4h-2l2,4h-3l-2-4H8l2,4H7L5,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4H18z"/></g><g id="drive-zip"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M14,9h-2v2h2v2h-2v-2h-2V9h2V7h-2V5h2v2h2V9z M14,17h-2v-2h-2v-2h2v2h2V17z"/></g><g id="due-date"><path d="M17,12h-5v5h5V12z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g><g id="error"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,17h-2v-2h2V17z M13,13h-2V7h2V13z"/></g><g id="event"><path d="M17,12h-5v5h5V12z M16,1v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2h-1V1H16z M19,19H5V8h14V19z"/></g><g id="exit-to-app"><path d="M10.1,15.6l1.4,1.4l5-5l-5-5l-1.4,1.4l2.6,2.6H3v2h9.7L10.1,15.6z M19,3H5C3.9,3,3,3.9,3,5v4h2V5h14v14H5v-4H3v4c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g><g id="expand-less"><polygon points="12,8 6,14 7.4,15.4 12,10.8 16.6,15.4 18,14 "></polygon></g><g id="expand-more"><polygon points="16.6,8.6 12,13.2 7.4,8.6 6,10 12,16 18,10 "></polygon></g><g id="explore"><path d="M12,10.9c-0.6,0-1.1,0.5-1.1,1.1s0.5,1.1,1.1,1.1c0.6,0,1.1-0.5,1.1-1.1S12.6,10.9,12,10.9z M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M14.2,14.2L6,18l3.8-8.2L18,6L14.2,14.2z"/></g><g id="extension"><path d="M20.5,11H19V7c0-1.1-0.9-2-2-2h-4V3.5C13,2.1,11.9,1,10.5,1C9.1,1,8,2.1,8,3.5V5H4C2.9,5,2,5.9,2,7l0,3.8h1.5c1.5,0,2.7,1.2,2.7,2.7S5,16.2,3.5,16.2H2L2,20c0,1.1,0.9,2,2,2h3.8v-1.5c0-1.5,1.2-2.7,2.7-2.7c1.5,0,2.7,1.2,2.7,2.7V22H17c1.1,0,2-0.9,2-2v-4h1.5c1.4,0,2.5-1.1,2.5-2.5S21.9,11,20.5,11z"/></g><g id="favorite"><path d="M12,21.4L10.6,20C5.4,15.4,2,12.3,2,8.5C2,5.4,4.4,3,7.5,3c1.7,0,3.4,0.8,4.5,2.1C13.1,3.8,14.8,3,16.5,3C19.6,3,22,5.4,22,8.5c0,3.8-3.4,6.9-8.6,11.5L12,21.4z"/></g><g id="favorite-outline"><path d="M16.5,3c-1.7,0-3.4,0.8-4.5,2.1C10.9,3.8,9.2,3,7.5,3C4.4,3,2,5.4,2,8.5c0,3.8,3.4,6.9,8.6,11.5l1.4,1.3l1.4-1.3c5.1-4.7,8.6-7.8,8.6-11.5C22,5.4,19.6,3,16.5,3z M12.1,18.6L12,18.6l-0.1-0.1C7.1,14.2,4,11.4,4,8.5C4,6.5,5.5,5,7.5,5c1.5,0,3,1,3.6,2.4h1.9C13.5,6,15,5,16.5,5c2,0,3.5,1.5,3.5,3.5C20,11.4,16.9,14.2,12.1,18.6z"/></g><g id="file-download"><path d="M19,9h-4V3H9v6H5l7,7L19,9z M5,18v2h14v-2H5z"/></g><g id="file-map"><path d="M12,6.5c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5S12.8,6.5,12,6.5z M19,1H5C3.9,1,3,1.9,3,3v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V3C21,1.9,20.1,1,19,1z M12.5,17h-1c-1-4.1-4-5.8-4-9c0-2.5,2-4.5,4.5-4.5c2.5,0,4.5,2,4.5,4.5C16.5,11.2,13.5,12.9,12.5,17z"/></g><g id="file-upload"><polygon points="9,16 15,16 15,10 19,10 12,3 5,10 9,10 "><rect x="5" y="18" width="14" height="2"/></polygon></g><g id="filter"><path d="M10,18h4v-2h-4V18z M3,6v2h18V6H3z M6,13h12v-2H6V13z"/></g><g id="flag"><polygon points="14.4,6 14,4 5,4 5,21 7,21 7,14 12.6,14 13,16 20,16 20,6 "></polygon></g><g id="flip-to-back"><path d="M9,7H7l0,2h2V7z M9,11H7v2h2V11z M9,3C7.9,3,7,3.9,7,5h2V3z M13,15h-2v2h2V15z M19,3v2h2C21,3.9,20.1,3,19,3z M13,3h-2v2h2V3z M9,17v-2H7C7,16.1,7.9,17,9,17z M19,13h2v-2h-2V13z M19,9h2V7h-2V9z M19,17c1.1,0,2-0.9,2-2h-2V17z M5,7H3v2h0l0,10c0,1.1,0.9,2,2,2h12v-2H5V7z M15,5h2V3h-2V5z M15,17h2v-2h-2V17z"/></g><g id="flip-to-front"><path d="M3,13h2v-2H3L3,13z M3,17h2v-2H3V17z M5,21v-2H3C3,20.1,3.9,21,5,21z M3,9h2V7H3V9z M15,21h2v-2h-2V21z M19,3H9C7.9,3,7,3.9,7,5v2h0v2v6c0,1.1,0.9,2,2,2h5h4h1c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,15H9V5h10V15z M11,21h2v-2h-2V21z M7,21h2v-2H7V21z"/></g><g id="folder"><path d="M10,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8c0-1.1-0.9-2-2-2h-8L10,4z"/></g><g id="folder-mydrive"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M11.5,17l-1.1-2.1l2.8-5l1.5,2.7L12.3,17H11.5z M18.3,17h-5.5l1.4-2.5h5.1l0.3,0.5L18.3,17z M13.8,9h2.4l2.8,5H16l-2.6-4.5L13.8,9z"/></g><g id="folder-open"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M20,18H4V8h16V18z"/></g><g id="folder-shared"><path d="M20,6h-8l-2-2H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,9c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C13,9.9,13.9,9,15,9z M19,17h-8v-1c0-1.3,2.7-2,4-2c1.3,0,4,0.7,4,2V17z"/></g><g id="forward"><polygon points="12,8 12,4 20,12 12,20 12,16 4,16 4,8 "></polygon></g><g id="fullscreen"><path d="M7,14H5v5h5v-2H7V14z M5,10h2V7h3V5H5V10z M17,17h-3v2h5v-5h-2V17z M14,5v2h3v3h2V5H14z"/></g><g id="fullscreen-exit"><path d="M5,16h3v3h2v-5H5V16z M8,8H5v2h5V5H8V8z M14,19h2v-3h3v-2h-5V19z M16,8V5h-2v5h5V8H16z"/></g><g id="gesture"><path d="M4.6,6.9C5.3,6.2,6,5.5,6.3,5.7c0.5,0.2,0,1-0.3,1.5c-0.3,0.4-2.9,3.9-2.9,6.3c0,1.3,0.5,2.3,1.3,3c0.8,0.6,1.7,0.7,2.6,0.5c1.1-0.3,1.9-1.4,3.1-2.8c1.2-1.5,2.8-3.4,4.1-3.4c1.6,0,1.6,1,1.8,1.8c-3.8,0.6-5.4,3.7-5.4,5.4c0,1.7,1.4,3.1,3.2,3.1c1.6,0,4.3-1.3,4.7-6.1H21v-2.5h-2.5c-0.2-1.6-1.1-4.2-4-4.2c-2.2,0-4.2,1.9-4.9,2.8c-0.6,0.7-2.1,2.5-2.3,2.7c-0.3,0.3-0.7,0.8-1.1,0.8c-0.4,0-0.7-0.8-0.4-1.9c0.4-1.1,1.4-2.9,1.9-3.5C8.4,8,8.9,7.2,8.9,5.9C8.9,3.7,7.3,3,6.4,3C5.1,3,4,4,3.7,4.3C3.4,4.6,3.1,4.9,2.8,5.2L4.6,6.9z M13.9,18.6c-0.3,0-0.7-0.3-0.7-0.7c0-0.6,0.7-2.2,2.9-2.8C15.7,17.8,14.6,18.6,13.9,18.6z"/></g><g id="get-app"><path d="M19,9h-4V3H9v6H5l7,7L19,9z M5,18v2h14v-2H5z"/></g><g id="google"><path d="M16.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L18.9,0h-6.2C8.3,0,6.1,2.8,6.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C18.8,15.7,17.7,14.6,16.3,13.4z M8.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C10,9.7,8.7,6.6,8.7,4.3z M12.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C16.9,20.8,15,22.3,12.3,22.3z"/></g><g id="google-plus"><path d="M21,10V7h-2v3h-3v2h3v3h2v-3h3v-2H21z M13.3,13.4l-1.1-0.8c-0.4-0.3-0.8-0.7-0.8-1.4c0-0.7,0.5-1.3,1-1.6c1.3-1,2.6-2.1,2.6-4.3c0-2.1-1.3-3.3-2-3.9h1.7L15.9,0H9.7C5.3,0,3.1,2.8,3.1,5.8c0,2.3,1.8,4.8,5,4.8h0.8c-0.1,0.3-0.4,0.8-0.4,1.3c0,1,0.4,1.4,0.9,2c-1.4,0.1-4,0.4-5.9,1.6c-1.8,1.1-2.3,2.6-2.3,3.7c0,2.3,2.1,4.5,6.6,4.5c5.4,0,8-3,8-5.9C15.8,15.7,14.7,14.6,13.3,13.4z M5.7,4.3c0-2.2,1.3-3.2,2.7-3.2c2.6,0,4,3.5,4,5.5c0,2.6-2.1,3.1-2.9,3.1C7,9.7,5.7,6.6,5.7,4.3z M9.3,22.3c-3.3,0-5.4-1.5-5.4-3.7c0-2.2,2-2.9,2.6-3.2c1.3-0.4,3-0.5,3.3-0.5c0.3,0,0.5,0,0.7,0c2.4,1.7,3.4,2.4,3.4,4C13.9,20.8,12,22.3,9.3,22.3z"/></g><g id="grade"><polygon points="12,17.3 18.2,21 16.5,14 22,9.2 14.8,8.6 12,2 9.2,8.6 2,9.2 7.5,14 5.8,21 "></polygon></g><g id="group-work"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M8,17.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5S9.4,17.5,8,17.5z M9.5,8c0-1.4,1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5s-1.1,2.5-2.5,2.5S9.5,9.4,9.5,8z M16,17.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5s2.5,1.1,2.5,2.5S17.4,17.5,16,17.5z"/></g><g id="help"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,19h-2v-2h2V19z M15.1,11.3l-0.9,0.9C13.4,12.9,13,13.5,13,15h-2v-0.5c0-1.1,0.4-2.1,1.2-2.8l1.2-1.3C13.8,10.1,14,9.6,14,9c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2H8c0-2.2,1.8-4,4-4c2.2,0,4,1.8,4,4C16,9.9,15.6,10.7,15.1,11.3z"/></g><g id="highlight-remove"><path d="M14.6,8L12,10.6L9.4,8L8,9.4l2.6,2.6L8,14.6L9.4,16l2.6-2.6l2.6,2.6l1.4-1.4L13.4,12L16,9.4L14.6,8z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8s8,3.6,8,8S16.4,20,12,20z"/></g><g id="history"><path opacity="0.9" d="M13,3c-5,0-9,4-9,9H1l3.9,3.9c0,0,0,0.1,0.1,0.1l4-4H6c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7s-3.1,7-7,7c-1.9,0-3.7-0.8-4.9-2.1l-1.4,1.4C8.3,20,10.5,21,13,21c5,0,9-4,9-9S18,3,13,3z M12,8v5l4.3,2.5l0.7-1.2l-3.5-2.1V8H12z"/></g><g id="home"><polygon points="10,20 10,14 14,14 14,20 19,20 19,12 22,12 12,3 2,12 5,12 5,20 "></polygon></g><g id="https"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z M15.1,8H8.9V6c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1V8z"/></g><g id="inbox"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,15h-4c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3H5V5h14V15z M16,10h-2V7h-4v3H8l4,4L16,10z"/></g><g id="info"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M13,17h-2v-6h2V17z M13,9h-2V7h2V9z"/></g><g id="info-outline"><path d="M11,17h2v-6h-2V17z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M11,9h2V7h-2V9z"/></g><g id="input"><path d="M21,3H3C1.9,3,1,3.9,1,5v4h2V5h18v14H3v-4H1v4c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M11,16l4-4l-4-4v3H1v2h10V16z"/></g><g id="invert-colors"><path d="M17.7,7.9L12,2.3l0,0v0L6.3,7.9c-3.1,3.1-3.1,8.2,0,11.3c1.6,1.6,3.6,2.3,5.7,2.3c2,0,4.1-0.8,5.7-2.3C20.8,16.1,20.8,11.1,17.7,7.9z M12,19.6L12,19.6c-1.6,0-3.1-0.6-4.2-1.8C6.6,16.7,6,15.2,6,13.6c0-1.6,0.6-3.1,1.8-4.2L12,5.1L12,19.6z"/></g><g id="keep"><path d="M16,12V4h1V2H7v2h1v8l-2,2v2h5.2v6h1.6v-6H18v-2L16,12z"/></g><g id="label"><path d="M17.6,5.8C17.3,5.3,16.7,5,16,5L5,5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2l11,0c0.7,0,1.3-0.3,1.6-0.8L22,12L17.6,5.8z"/></g><g id="label-outline"><path d="M17.6,5.8C17.3,5.3,16.7,5,16,5L5,5C3.9,5,3,5.9,3,7v10c0,1.1,0.9,2,2,2l11,0c0.7,0,1.3-0.3,1.6-0.8L22,12L17.6,5.8z M16,17H5V7h11l3.5,5L16,17z"/></g><g id="language"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M18.9,8H16c-0.3-1.3-0.8-2.4-1.4-3.6C16.4,5.1,18,6.3,18.9,8z M12,4c0.8,1.2,1.5,2.5,1.9,4h-3.8C10.5,6.6,11.2,5.2,12,4z M4.3,14C4.1,13.4,4,12.7,4,12s0.1-1.4,0.3-2h3.4c-0.1,0.7-0.1,1.3-0.1,2s0.1,1.3,0.1,2H4.3z M5.1,16H8c0.3,1.3,0.8,2.4,1.4,3.6C7.6,18.9,6,17.7,5.1,16z M8,8H5.1c1-1.7,2.5-2.9,4.3-3.6C8.8,5.6,8.3,6.7,8,8z M12,20c-0.8-1.2-1.5-2.5-1.9-4h3.8C13.5,17.4,12.8,18.8,12,20z M14.3,14H9.7c-0.1-0.7-0.2-1.3-0.2-2s0.1-1.3,0.2-2h4.7c0.1,0.7,0.2,1.3,0.2,2S14.4,13.3,14.3,14z M14.6,19.6c0.6-1.1,1.1-2.3,1.4-3.6h2.9C18,17.7,16.4,18.9,14.6,19.6z M16.4,14c0.1-0.7,0.1-1.3,0.1-2s-0.1-1.3-0.1-2h3.4c0.2,0.6,0.3,1.3,0.3,2s-0.1,1.4-0.3,2H16.4z"/></g><g id="launch"><path d="M19,19H5V5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7h-2V19z M14,3v2h3.6l-9.8,9.8l1.4,1.4L19,6.4V10h2V3H14z"/></g><g id="link"><path d="M3.9,12c0-1.7,1.4-3.1,3.1-3.1h4V7H7c-2.8,0-5,2.2-5,5s2.2,5,5,5h4v-1.9H7C5.3,15.1,3.9,13.7,3.9,12z M8,13h8v-2H8V13z M17,7h-4v1.9h4c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1h-4V17h4c2.8,0,5-2.2,5-5S19.8,7,17,7z"/></g><g id="list"><path d="M3,13h2v-2H3V13z M3,17h2v-2H3V17z M3,9h2V7H3V9z M7,13h14v-2H7V13z M7,17h14v-2H7V17z M7,7v2h14V7H7z"/></g><g id="lock"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z M15.1,8H8.9V6c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1V8z"/></g><g id="lock-open"><path d="M12,17c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,17,12,17z M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6h1.9c0-1.7,1.4-3.1,3.1-3.1c1.7,0,3.1,1.4,3.1,3.1v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M18,20H6V10h12V20z"/></g><g id="lock-outline"><path d="M18,8h-1V6c0-2.8-2.2-5-5-5C9.2,1,7,3.2,7,6v2H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10C20,8.9,19.1,8,18,8z M12,2.9c1.7,0,3.1,1.4,3.1,3.1v2H9V6H8.9C8.9,4.3,10.3,2.9,12,2.9z M18,20H6V10h12V20z M12,17c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,17,12,17z"/></g><g id="loyalty"><path d="M21.4,11.6l-9-9C12.1,2.2,11.6,2,11,2H4C2.9,2,2,2.9,2,4v7c0,0.6,0.2,1.1,0.6,1.4l9,9c0.4,0.4,0.9,0.6,1.4,0.6c0.6,0,1.1-0.2,1.4-0.6l7-7c0.4-0.4,0.6-0.9,0.6-1.4C22,12.4,21.8,11.9,21.4,11.6z M5.5,7C4.7,7,4,6.3,4,5.5S4.7,4,5.5,4S7,4.7,7,5.5S6.3,7,5.5,7z M17.3,15.3L13,19.5l-4.3-4.3l0,0C8.3,14.8,8,14.2,8,13.5c0-1.4,1.1-2.5,2.5-2.5c0.7,0,1.3,0.3,1.8,0.7l0.7,0.7l0.7-0.7c0.5-0.5,1.1-0.7,1.8-0.7c1.4,0,2.5,1.1,2.5,2.5C18,14.2,17.7,14.8,17.3,15.3L17.3,15.3z"/></g><g id="mail"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,8l-8,5L4,8V6l8,5l8-5V8z"/></g><g id="markunread"><path d="M20,6H10v6H8V4h6V0H6v6H4C2.9,6,2,6.9,2,8l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z"/></g><g id="markunread"><path d="M22,6l2-2l-2-2l-2,2l-2-2l-2,2l-2-2l-2,2l-2-2L8,4L6,2L4,4L2,2L0,4l2,2L0,8l2,2l-2,2l2,2l-2,2l2,2l-2,2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l2,2l2-2l-2-2l2-2l-2-2l2-2l-2-2l2-2L22,6z M20,8l-8,5L4,8V6l8,5l8-5V8z"/></g><g id="menu"><path d="M3,18h18v-2H3V18z M3,13h18v-2H3V13z M3,6v2h18V6H3z"/></g><g id="more-horiz"><path d="M6,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S7.1,10,6,10z M18,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S19.1,10,18,10z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z"/></g><g id="more-vert"><path d="M12,8c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,8,12,8z M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,10,12,10z M12,16c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,16,12,16z"/></g><g id="note-add"><path d="M14,2H6C4.9,2,4,2.9,4,4l0,16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V8L14,2z M16,16h-3v3h-2v-3H8v-2h3v-3h2v3h3V16z M13,9V3.5L18.5,9H13z"/></g><g id="open-in-browser"><path d="M19,4H5C3.9,4,3,4.9,3,6v12c0,1.1,0.9,2,2,2h3v-2H5V8h14v10h-3v2h3c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M12,10l-5,5h3v5h4v-5h3L12,10z"/></g><g id="open-in-new"><path d="M19,19H5V5h7V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-7h-2V19z M14,3v2h3.6l-9.8,9.8l1.4,1.4L19,6.4V10h2V3H14z"/></g><g id="open-with"><path d="M10,9h4V6h3l-5-5L7,6h3V9z M9,10H6V7l-5,5l5,5v-3h3V10z M23,12l-5-5v3h-3v4h3v3L23,12z M14,15h-4v3H7l5,5l5-5h-3V15z"/></g><g id="payment"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18H4v-6h16V18z M20,8H4V6h16V8z"/></g><g id="perm-camera-mic"><path d="M20,5h-3.2L15,3H9L7.2,5H4C2.9,5,2,5.9,2,7v12c0,1.1,0.9,2,2,2h7v-2.1C8.2,18.4,6,16,6,13h2c0,2.2,1.8,4,4,4s4-1.8,4-4h2c0,3-2.2,5.4-5,5.9V21h7c1.1,0,2-0.9,2-2V7C22,5.9,21.1,5,20,5z M14,13c0,1.1-0.9,2-2,2s-2-0.9-2-2V9c0-1.1,0.9-2,2-2s2,0.9,2,2V13z"/></g><g id="perm-contact-cal"><path d="M19,3h-1V1h-2v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,6c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3s-3-1.3-3-3C9,7.3,10.3,6,12,6z M18,18H6v-1c0-2,4-3.1,6-3.1s6,1.1,6,3.1V18z"/></g><g id="perm-data-setting"><path d="M19,11.5c0.3,0,0.7,0,1,0.1V0L0,20h11.6c0-0.3-0.1-0.7-0.1-1C11.5,14.9,14.9,11.5,19,11.5z M22.7,19.5c0-0.2,0-0.3,0-0.5c0-0.2,0-0.3,0-0.5l1.1-0.8c0.1-0.1,0.1-0.2,0.1-0.3l-1-1.7c-0.1-0.1-0.2-0.2-0.3-0.1L21.3,16c-0.3-0.2-0.5-0.4-0.8-0.5l-0.2-1.3c0-0.1-0.1-0.2-0.2-0.2h-2c-0.1,0-0.2,0.1-0.2,0.2l-0.2,1.3c-0.3,0.1-0.6,0.3-0.8,0.5l-1.2-0.5c-0.1,0-0.2,0-0.3,0.1l-1,1.7c-0.1,0.1,0,0.2,0.1,0.3l1.1,0.8c0,0.2,0,0.3,0,0.5c0,0.2,0,0.3,0,0.5l-1.1,0.8c-0.1,0.1-0.1,0.2-0.1,0.3l1,1.7c0.1,0.1,0.2,0.2,0.3,0.1l1.2-0.5c0.3,0.2,0.5,0.4,0.8,0.5l0.2,1.3c0,0.1,0.1,0.2,0.2,0.2h2c0.1,0,0.2-0.1,0.2-0.2l0.2-1.3c0.3-0.1,0.6-0.3,0.8-0.5l1.2,0.5c0.1,0,0.2,0,0.3-0.1l1-1.7c0.1-0.1,0-0.2-0.1-0.3L22.7,19.5z M19,20.5c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5s1.5,0.7,1.5,1.5S19.8,20.5,19,20.5z"/></g><g id="perm-device-info"><path d="M13,7h-2v2h2V7z M13,11h-2v6h2V11z M17,1L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g><g id="perm-identity"><path d="M12,5.9c1.2,0,2.1,0.9,2.1,2.1s-0.9,2.1-2.1,2.1S9.9,9.2,9.9,8S10.8,5.9,12,5.9 M12,14.9c3,0,6.1,1.5,6.1,2.1v1.1H5.9V17C5.9,16.4,9,14.9,12,14.9 M12,4C9.8,4,8,5.8,8,8c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,5.8,14.2,4,12,4L12,4z M12,13c-2.7,0-8,1.3-8,4v3h16v-3C20,14.3,14.7,13,12,13L12,13z"/></g><g id="perm-media"><path d="M2,6H0v5h0l0,9c0,1.1,0.9,2,2,2h18v-2H2V6z M22,4h-8l-2-2H6C4.9,2,4,2.9,4,4l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C24,4.9,23.1,4,22,4z M7,15l4.5-6l3.5,4.5l2.5-3L21,15H7z"/></g><g id="perm-phone-msg"><path d="M20,15.5c-1.2,0-2.4-0.2-3.6-0.6c-0.3-0.1-0.7,0-1,0.2l-2.2,2.2c-2.8-1.4-5.1-3.8-6.6-6.6l2.2-2.2c0.3-0.3,0.4-0.7,0.2-1C8.7,6.4,8.5,5.2,8.5,4c0-0.6-0.4-1-1-1H4C3.5,3,3,3.4,3,4c0,9.4,7.6,17,17,17c0.6,0,1-0.4,1-1v-3.5C21,15.9,20.6,15.5,20,15.5z M12,3v10l3-3h6V3H12z"/></g><g id="perm-scan-wifi"><path d="M12,3C7,3,3.2,4.9,0,7.2L12,22L24,7.3C20.9,4.9,17.1,3,12,3z M13,16h-2v-6h2V16z M11,8V6h2v2H11z"/></g><g id="picture-in-picture"><path d="M19,7h-8v6h8V7z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g><g id="polymer"><polygon points="19,4 15,4 7.1,16.6 4.5,12 9,4 5,4 0.5,12 5,20 9,20 16.9,7.4 19.5,12 15,20 19,20 23.5,12 "></polygon></g><g id="print"><path d="M19,8H5c-1.7,0-3,1.3-3,3v6h4v4h12v-4h4v-6C22,9.3,20.7,8,19,8z M16,19H8v-5h8V19z M19,12c-0.6,0-1-0.4-1-1s0.4-1,1-1c0.6,0,1,0.4,1,1S19.6,12,19,12z M18,3H6v4h12V3z"/></g><g id="query-builder"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.3 "></polygon></g><g id="question-answer"><path d="M21,6h-2v9H6v2c0,0.6,0.4,1,1,1h11l4,4V7C22,6.4,21.6,6,21,6z M17,12V3c0-0.6-0.4-1-1-1H3C2.4,2,2,2.4,2,3v14l4-4h10C16.6,13,17,12.6,17,12z"/></g><g id="radio-button-off"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g><g id="radio-button-on"><path d="M12,7c-2.8,0-5,2.2-5,5s2.2,5,5,5c2.8,0,5-2.2,5-5S14.8,7,12,7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g><g id="receipt"><path d="M18,17H6v-2h12V17z M18,13H6v-2h12V13z M18,9H6V7h12V9z M3,22l1.5-1.5L6,22l1.5-1.5L9,22l1.5-1.5L12,22l1.5-1.5L15,22l1.5-1.5L18,22l1.5-1.5L21,22V2l-1.5,1.5L18,2l-1.5,1.5L15,2l-1.5,1.5L12,2l-1.5,1.5L9,2L7.5,3.5L6,2L4.5,3.5L3,2V22z"/></g><g id="redeem"><path d="M20,6h-2.2C17.9,5.7,18,5.4,18,5c0-1.7-1.3-3-3-3c-1,0-2,0.5-2.5,1.3l0,0L12,4l-0.5-0.7l0,0C11,2.5,10.1,2,9,2C7.4,2,6,3.3,6,5c0,0.4,0.1,0.7,0.2,1H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,4c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S14.5,4,15,4z M9,4c0.6,0,1,0.4,1,1S9.6,6,9,6S8,5.6,8,5S8.5,4,9,4z M20,19H4v-2h16V19z M20,14H4V8h5.1L7,10.8L8.6,12L11,8.8l1-1.4l1,1.4l2.4,3.2l1.6-1.2L14.9,8H20V14z"/></g><g id="refresh"><path d="M17.6,6.4C16.2,4.9,14.2,4,12,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c3.7,0,6.8-2.6,7.7-6h-2.1c-0.8,2.3-3,4-5.6,4c-3.3,0-6-2.7-6-6s2.7-6,6-6c1.7,0,3.1,0.7,4.2,1.8L13,11h7V4L17.6,6.4z"/></g><g id="reminder"><path d="M16.9,13c1.3-1.3,2.1-3,2.1-5c0-3.9-3.1-7-7-7C8.1,1,5,4.1,5,8c0,2,0.8,3.7,2.1,5l0,0l3.5,3.5L6,21.1l1.4,1.4L16.9,13z M15.5,11.5L15.5,11.5L12,15.1l-3.5-3.5l0,0l0,0C7.6,10.6,7,9.4,7,8c0-2.8,2.2-5,5-5c2.8,0,5,2.2,5,5C17,9.4,16.4,10.6,15.5,11.5L15.5,11.5z M13.4,19.3l3.2,3.2l1.4-1.4l-3.2-3.2L13.4,19.3z"/></g><g id="remove"><path d="M19,13H5v-2h14V13z"/></g><g id="remove-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,13H7v-2h10V13z"/></g><g id="remove-circle-outline"><path d="M7,11v2h10v-2H7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g><g id="reorder"><path d="M4,16h16v-2H4V16z M4,9v2h16V9H4z"/></g><g id="reply"><path d="M10,9V5l-7,7l7,7v-4.1c5,0,8.5,1.6,11,5.1C20,15,17,10,10,9z"/></g><g id="reply-all"><path d="M7,8V5l-7,7l7,7v-3l-4-4L7,8z M13,9V5l-7,7l7,7v-4.1c5,0,8.5,1.6,11,5.1C23,15,20,10,13,9z"/></g><g id="report"><path d="M15.7,3H8.3L3,8.3v7.5L8.3,21h7.5l5.3-5.3V8.3L15.7,3z M12,17.3c-0.7,0-1.3-0.6-1.3-1.3c0-0.7,0.6-1.3,1.3-1.3c0.7,0,1.3,0.6,1.3,1.3C13.3,16.7,12.7,17.3,12,17.3z M13,13h-2V7h2V13z"/></g><g id="report-problem"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g><g id="restore"><path d="M13,3c-5,0-9,4-9,9H1l3.9,3.9c0,0,0,0.1,0.1,0.1l4-4H6c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7s-3.1,7-7,7c-1.9,0-3.7-0.8-4.9-2.1l-1.4,1.4C8.3,20,10.5,21,13,21c5,0,9-4,9-9S18,3,13,3z M12,8v5l4.3,2.5l0.7-1.2l-3.5-2.1V8H12z"/></g><g id="room"><path d="M12,2C8.1,2,5,5.1,5,9c0,5.2,7,13,7,13s7-7.8,7-13C19,5.1,15.9,2,12,2z M12,11.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5c1.4,0,2.5,1.1,2.5,2.5S13.4,11.5,12,11.5z"/></g><g id="rotate-left"><path d="M7.1,8.5L5.7,7.1C4.8,8.3,4.2,9.6,4.1,11h2C6.2,10.1,6.6,9.3,7.1,8.5z M6.1,13h-2c0.2,1.4,0.7,2.7,1.6,3.9l1.4-1.4C6.6,14.7,6.2,13.9,6.1,13z M7.1,18.3c1.2,0.9,2.5,1.4,3.9,1.6v-2c-0.9-0.1-1.7-0.5-2.5-1L7.1,18.3z M13,4.1V1L8.5,5.5L13,10V6.1c2.8,0.5,5,2.9,5,5.9s-2.2,5.4-5,5.9v2c3.9-0.5,7-3.9,7-7.9S16.9,4.6,13,4.1z"/></g><g id="rotate-right"><path d="M15.5,5.5L11,1v3.1C7.1,4.6,4,7.9,4,12s3.1,7.4,7,7.9v-2C8.2,17.4,6,15,6,12s2.2-5.4,5-5.9V10L15.5,5.5z M19.9,11c-0.2-1.4-0.7-2.7-1.6-3.9l-1.4,1.4c0.5,0.8,0.9,1.6,1,2.5H19.9z M13,17.9v2c1.4-0.2,2.7-0.7,3.9-1.6l-1.4-1.4C14.7,17.4,13.9,17.8,13,17.9z M16.9,15.5l1.4,1.4c0.9-1.2,1.5-2.5,1.6-3.9h-2C17.8,13.9,17.4,14.7,16.9,15.5z"/></g><g id="rotation-3d"><path d="M11,14v-1c0-0.6-0.4-1-1-1c0.6,0,1-0.4,1-1v-1c0-1.1-0.9-2-2-2H6v2h3v1H7v2h2v1l0,0l0,0v0h0H6v2h3C10.1,16,11,15.1,11,14z M15,8h-3v8h3c1.7,0,3-1.3,3-3v-2C18,9.3,16.7,8,15,8z M16,13c0,0.6-0.4,1-1,1h-1v-4h1c0.6,0,1,0.4,1,1V13z M12,0c-0.2,0-0.4,0-0.7,0l3.8,3.8l1.3-1.3c3.3,1.5,5.6,4.7,6,8.5h1.5C23.4,4.8,18.3,0,12,0z M7.5,21.5c-3.3-1.5-5.6-4.7-6-8.5H0.1C0.6,19.2,5.7,24,12,24c0.2,0,0.4,0,0.7,0l-3.8-3.8L7.5,21.5z"/></g><g id="save"><path d="M17,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V7L17,3z M12,19c-1.7,0-3-1.3-3-3s1.3-3,3-3c1.7,0,3,1.3,3,3S13.7,19,12,19z M15,9H5V5h10V9z"/></g><g id="schedule"><path fill-opacity="0.9" d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/><polygon fill-opacity="0.9" points="12.5,7 11,7 11,13 16.2,16.2 17,14.9 12.5,12.2 "></polygon></g><g id="search"><path d="M15.5,14h-0.8l-0.3-0.3c1-1.1,1.6-2.6,1.6-4.2C16,5.9,13.1,3,9.5,3C5.9,3,3,5.9,3,9.5S5.9,16,9.5,16c1.6,0,3.1-0.6,4.2-1.6l0.3,0.3v0.8l5,5l1.5-1.5L15.5,14z M9.5,14C7,14,5,12,5,9.5S7,5,9.5,5C12,5,14,7,14,9.5S12,14,9.5,14z"/></g><g id="select-all"><path d="M3,5h2V3C3.9,3,3,3.9,3,5z M3,13h2v-2H3V13z M7,21h2v-2H7V21z M3,9h2V7H3V9z M13,3h-2v2h2V3z M19,3v2h2C21,3.9,20.1,3,19,3z M5,21v-2H3C3,20.1,3.9,21,5,21z M3,17h2v-2H3V17z M9,3H7v2h2V3z M11,21h2v-2h-2V21z M19,13h2v-2h-2V13z M19,21c1.1,0,2-0.9,2-2h-2V21z M19,9h2V7h-2V9z M19,17h2v-2h-2V17z M15,21h2v-2h-2V21z M15,5h2V3h-2V5z M7,17h10V7H7V17z M9,9h6v6H9V9z"/></g><g id="send"><polygon points="2,21 23,12 2,3 2,10 17,12 2,14 "></polygon></g><g id="send-money"><path d="M2,12c0-2.6,1.7-4.8,4-5.7V4.3c-3.4,0.9-6,4-6,7.7s2.6,6.8,6,7.7v-2.1C3.7,16.8,2,14.6,2,12z M24,12l-4-4v3h-7v2h7v3L24,12z M14,18c-3.3,0-6-2.7-6-6s2.7-6,6-6c1.7,0,3.2,0.7,4.2,1.8l1.4-1.4C18.2,4.9,16.2,4,14,4c-4.4,0-8,3.6-8,8s3.6,8,8,8c2.2,0,4.2-0.9,5.7-2.3l-1.4-1.4C17.2,17.3,15.7,18,14,18z"/></g><g id="settings"><path d="M19.4,13c0-0.3,0.1-0.6,0.1-1s0-0.7-0.1-1l2.1-1.7c0.2-0.2,0.2-0.4,0.1-0.6l-2-3.5C19.5,5.1,19.3,5,19,5.1l-2.5,1c-0.5-0.4-1.1-0.7-1.7-1l-0.4-2.6C14.5,2.2,14.2,2,14,2h-4C9.8,2,9.5,2.2,9.5,2.4L9.1,5.1C8.5,5.3,8,5.7,7.4,6.1L5,5.1C4.7,5,4.5,5.1,4.3,5.3l-2,3.5C2.2,8.9,2.3,9.2,2.5,9.4L4.6,11c0,0.3-0.1,0.6-0.1,1s0,0.7,0.1,1l-2.1,1.7c-0.2,0.2-0.2,0.4-0.1,0.6l2,3.5C4.5,18.9,4.7,19,5,18.9l2.5-1c0.5,0.4,1.1,0.7,1.7,1l0.4,2.6c0,0.2,0.2,0.4,0.5,0.4h4c0.2,0,0.5-0.2,0.5-0.4l0.4-2.6c0.6-0.3,1.2-0.6,1.7-1l2.5,1c0.2,0.1,0.5,0,0.6-0.2l2-3.5c0.1-0.2,0.1-0.5-0.1-0.6L19.4,13z M12,15.5c-1.9,0-3.5-1.6-3.5-3.5s1.6-3.5,3.5-3.5s3.5,1.6,3.5,3.5S13.9,15.5,12,15.5z"/></g><g id="settings-applications"><path d="M12,10c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S13.1,10,12,10z M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17.2,12c0,0.2,0,0.5,0,0.7l1.5,1.2c0.1,0.1,0.2,0.3,0.1,0.4l-1.4,2.4c-0.1,0.2-0.3,0.2-0.4,0.2l-1.7-0.7c-0.4,0.3-0.8,0.5-1.2,0.7l-0.3,1.9c0,0.2-0.2,0.3-0.3,0.3h-2.8c-0.2,0-0.3-0.1-0.3-0.3L10,16.9c-0.4-0.2-0.8-0.4-1.2-0.7l-1.7,0.7c-0.2,0.1-0.3,0-0.4-0.2l-1.4-2.4c-0.1-0.2,0-0.3,0.1-0.4l1.5-1.2c0-0.2,0-0.5,0-0.7s0-0.5,0-0.7l-1.5-1.2c-0.1-0.1-0.2-0.3-0.1-0.4l1.4-2.4c0.1-0.2,0.3-0.2,0.4-0.2l1.7,0.7C9.2,7.6,9.6,7.3,10,7.1l0.3-1.9c0-0.2,0.2-0.3,0.3-0.3h2.8c0.2,0,0.3,0.1,0.3,0.3L14,7.1c0.4,0.2,0.8,0.4,1.2,0.7l1.7-0.7c0.2-0.1,0.3,0,0.4,0.2l1.4,2.4c0.1,0.2,0,0.3-0.1,0.4l-1.5,1.2C17.2,11.5,17.2,11.8,17.2,12z"/></g><g id="settings-backup-restore"><path d="M14,12c0-1.1-0.9-2-2-2s-2,0.9-2,2s0.9,2,2,2S14,13.1,14,12z M12,3c-5,0-9,4-9,9H0l4,4l4-4H5c0-3.9,3.1-7,7-7s7,3.1,7,7s-3.1,7-7,7c-1.5,0-2.9-0.5-4.1-1.3l-1.4,1.4C8,20.3,9.9,21,12,21c5,0,9-4,9-9S17,3,12,3z"/></g><g id="settings-bluetooth"><path d="M11,24h2v-2h-2V24z M7,24h2v-2H7V24z M15,24h2v-2h-2V24z M17.7,5.7L12,0h-1v7.6L6.4,3L5,4.4l5.6,5.6L5,15.6L6.4,17l4.6-4.6V20h1l5.7-5.7L13.4,10L17.7,5.7z M13,3.8l1.9,1.9L13,7.6V3.8z M14.9,14.3L13,16.2v-3.8L14.9,14.3z"/></g><g id="settings-cell"><path d="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z M16,0L8,0C6.9,0,6,0.9,6,2v16c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V2C18,0.9,17.1,0,16,0z M16,16H8V4h8V16z"/></g><g id="settings-display"><path d="M21,19H3V5h18V19z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3L21,3z"/><path d="M10,12c0-1.1,0.9-2,2-2V8c0.3,0,0.7,0.1,1,0.1V6h-2v2.1c-0.4,0.1-0.7,0.2-1,0.4L8.5,7.1L7.1,8.5L8.6,10c-0.2,0.3-0.3,0.7-0.4,1H6v2h2.1c0.1,0.4,0.2,0.7,0.4,1l-1.5,1.5l1.4,1.4l1.5-1.5c0.3,0.2,0.7,0.3,1,0.4V18h2v-2.1c-0.3,0.1-0.7,0.1-1,0.1v-2C10.9,14,10,13.1,10,12z M15.4,10l1.5-1.5l-1.4-1.4L14,8.6C14.6,8.9,15.1,9.4,15.4,10z M14,15.4l1.5,1.5l1.4-1.4L15.4,14C15.1,14.6,14.6,15.1,14,15.4z M12,10v4c1.1,0,2-0.9,2-2C14,10.9,13.1,10,12,10z M15.9,11c0.1,0.3,0.1,0.7,0.1,1s-0.1,0.7-0.1,1H18v-2H15.9z"/></g><g id="settings-ethernet"><path d="M7.8,6.8L6.2,5.5L0.8,12l5.4,6.5l1.5-1.3L3.4,12L7.8,6.8z M7,13h2v-2H7V13z M17,11h-2v2h2V11z M11,13h2v-2h-2V13z M17.8,5.5l-1.5,1.3l4.3,5.2l-4.3,5.2l1.5,1.3l5.4-6.5L17.8,5.5z"/></g><g id="settings-input-antenna"><path d="M12,5c-3.9,0-7,3.1-7,7h2c0-2.8,2.2-5,5-5s5,2.2,5,5h2C19,8.1,15.9,5,12,5z M13,14.3c0.9-0.4,1.5-1.3,1.5-2.3c0-1.4-1.1-2.5-2.5-2.5S9.5,10.6,9.5,12c0,1,0.6,1.9,1.5,2.3v3.3L7.6,21L9,22.4l3-3l3,3l1.4-1.4L13,17.6V14.3z M12,1C5.9,1,1,5.9,1,12h2c0-5,4-9,9-9s9,4,9,9h2C23,5.9,18.1,1,12,1z"/></g><g id="settings-input-component"><path d="M5,2c0-0.6-0.4-1-1-1S3,1.4,3,2v4H1v6h6V6H5V2z M9,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H9V16z M1,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H1V16z M21,6V2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4h-2v6h6V6H21z M13,2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4H9v6h6V6h-2V2z M17,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2h-6V16z"/></g><g id="settings-input-composite"><path d="M5,2c0-0.6-0.4-1-1-1S3,1.4,3,2v4H1v6h6V6H5V2z M9,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H9V16z M1,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2H1V16z M21,6V2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4h-2v6h6V6H21z M13,2c0-0.6-0.4-1-1-1s-1,0.4-1,1v4H9v6h6V6h-2V2z M17,16c0,1.3,0.8,2.4,2,2.8V23h2v-4.2c1.2-0.4,2-1.5,2-2.8v-2h-6V16z"/></g><g id="settings-input-hdmi"><path d="M18,7V4c0-1.1-0.9-2-2-2H8C6.9,2,6,2.9,6,4v3H5v6l3,6v3h8v-3l3-6V7H18z M8,4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"/></g><g id="settings-input-svideo"><path d="M8,11.5C8,10.7,7.3,10,6.5,10S5,10.7,5,11.5S5.7,13,6.5,13S8,12.3,8,11.5z M15,6.5C15,5.7,14.3,5,13.5,5h-3C9.7,5,9,5.7,9,6.5S9.7,8,10.5,8h3C14.3,8,15,7.3,15,6.5z M8.5,15C7.7,15,7,15.7,7,16.5S7.7,18,8.5,18s1.5-0.7,1.5-1.5S9.3,15,8.5,15z M12,1C5.9,1,1,5.9,1,12s4.9,11,11,11s11-4.9,11-11S18.1,1,12,1z M12,21c-5,0-9-4-9-9s4-9,9-9s9,4,9,9S17,21,12,21z M17.5,10c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S18.3,10,17.5,10z M15.5,15c-0.8,0-1.5,0.7-1.5,1.5s0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5S16.3,15,15.5,15z"/></g><g id="settings-overscan"><path d="M12,5.5L10,8h4L12,5.5z M18,10v4l2.5-2L18,10z M6,10l-2.5,2L6,14V10z M14,16h-4l2,2.5L14,16z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g><g id="settings-phone"><path d="M13,9h-2v2h2V9z M17,9h-2v2h2V9z M20,15.5c-1.2,0-2.4-0.2-3.6-0.6c-0.3-0.1-0.7,0-1,0.2l-2.2,2.2c-2.8-1.4-5.1-3.8-6.6-6.6l2.2-2.2c0.3-0.3,0.4-0.7,0.2-1C8.7,6.4,8.5,5.2,8.5,4c0-0.6-0.4-1-1-1H4C3.4,3,3,3.4,3,4c0,9.4,7.6,17,17,17c0.6,0,1-0.4,1-1v-3.5C21,15.9,20.6,15.5,20,15.5z M19,9v2h2V9H19z"/></g><g id="settings-power"><path d="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M13,2h-2v10h2V2z M16.6,4.4l-1.4,1.4C16.8,6.9,18,8.8,18,11c0,3.3-2.7,6-6,6c-3.3,0-6-2.7-6-6c0-2.2,1.2-4.1,2.9-5.1L7.4,4.4C5.4,5.9,4,8.3,4,11c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8C20,8.3,18.6,5.9,16.6,4.4z M15,24h2v-2h-2V24z"/></g><g id="settings-remote"><path d="M15,9H9c-0.6,0-1,0.4-1,1v12c0,0.6,0.4,1,1,1h6c0.6,0,1-0.4,1-1V10C16,9.4,15.6,9,15,9z M12,15c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,15,12,15z M7.1,6.1l1.4,1.4C9.4,6.6,10.6,6,12,6s2.6,0.6,3.5,1.5l1.4-1.4C15.7,4.8,13.9,4,12,4S8.3,4.8,7.1,6.1z M12,0C9,0,6.2,1.2,4.2,3.2l1.4,1.4C7.3,3,9.5,2,12,2s4.7,1,6.4,2.6l1.4-1.4C17.8,1.2,15,0,12,0z"/></g><g id="settings-voice"><path d="M7,24h2v-2H7V24z M12,13c1.7,0,3-1.3,3-3l0-6c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v6C9,11.7,10.3,13,12,13z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z M19,10h-1.7c0,3-2.5,5.1-5.3,5.1c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V20h2v-3.3C16.3,16.2,19,13.4,19,10z"/></g><g id="shop"><path d="M16,6V4l-2-2h-4L8,4v2H2v13c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6H16z M10,4h4v2h-4V4z M9,18V9l7.5,4L9,18z"/></g><g id="shop-two"><path d="M18,5V3l-2-2h-4l-2,2v2H5v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5H18z M12,3h4v2h-4V3z M12,15V8l5.5,3L12,15z M3,9H1v11c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2H3V9z"/></g><g id="shopping-basket"><path d="M17.2,9l-4.4-6.6C12.6,2.2,12.3,2,12,2c-0.3,0-0.6,0.1-0.8,0.4L6.8,9H2c-0.6,0-1,0.4-1,1c0,0.1,0,0.2,0,0.3l2.5,9.3c0.2,0.8,1,1.5,1.9,1.5h13c0.9,0,1.7-0.6,1.9-1.5l2.5-9.3c0-0.1,0-0.2,0-0.3c0-0.6-0.4-1-1-1H17.2z M9,9l3-4.4L15,9H9z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S13.1,17,12,17z"/></g><g id="shopping-cart"><path d="M7,18c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S8.1,18,7,18z M1,2v2h2l3.6,7.6L5.2,14C5.1,14.3,5,14.7,5,15c0,1.1,0.9,2,2,2h12v-2H7.4c-0.1,0-0.2-0.1-0.2-0.2c0,0,0-0.1,0-0.1L8.1,13h7.4c0.8,0,1.4-0.4,1.7-1l3.6-6.5C21,5.3,21,5.2,21,5c0-0.6-0.4-1-1-1H5.2L4.3,2H1z M17,18c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S18.1,18,17,18z"/></g><g id="sort"><path d="M3,18h6v-2H3V18z M3,6v2h18V6H3z M3,13h12v-2H3V13z"/></g><g id="star"><polygon points="12,17.273 18.18,21 16.545,13.971 22,9.244 14.809,8.627 12,2 9.191,8.627 2,9.244 7.455,13.971 5.82,21 "></polygon></g><g id="star-half"><path d="M22,9.744l-7.191-0.617L12,2.5L9.191,9.127L2,9.744v0l0,0l5.455,4.727L5.82,21.5L12,17.772l0,0l6.18,3.727l-1.635-7.029L22,9.744z M12,15.896V6.595l1.71,4.036l4.38,0.376l-3.322,2.878l0.996,4.281L12,15.896z"/></g><g id="star-outline"><path d="M22,9.244l-7.191-0.617L12,2L9.191,8.627L2,9.244l5.455,4.727L5.82,21L12,17.272L18.18,21l-1.635-7.029L22,9.244z M12,15.396l-3.763,2.27l0.996-4.281L5.91,10.507l4.38-0.376L12,6.095l1.71,4.036l4.38,0.376l-3.322,2.878l0.996,4.281L12,15.396z"/></g><g id="star-rate"><polygon points="12,14.3 15.7,17 14.3,12.6 18,10 13.5,10 12,5.5 10.5,10 6,10 9.7,12.6 8.3,17 "></polygon></g><g id="stars"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M16.2,18L12,15.4L7.8,18l1.1-4.8L5.2,10l4.9-0.4L12,5l1.9,4.5l4.9,0.4l-3.7,3.2L16.2,18z"/></g><g id="store"><path d="M20,4H4v2h16V4z M21,14v-2l-1-5H4l-1,5v2h1v6h10v-6h4v6h2v-6H21z M12,18H6v-4h6V18z"/></g><g id="subject"><path d="M14,17H4v2h10V17z M20,9H4v2h16V9z M4,15h16v-2H4V15z M4,5v2h16V5H4z"/></g><g id="swap-driving-apps"><circle cx="6.5" cy="15.5" r="1.5"/><circle cx="17.5" cy="15.5" r="1.5"/><path d="M18.9,7c-0.2-0.6-0.8-1-1.4-1H16H6V4L3,7l2,2l1,1V8h11.7l1.3,4H3v9c0,0.6,0.4,1,1,1h1c0.6,0,1-0.4,1-1v-1h12v1c0,0.6,0.4,1,1,1h1c0.6,0,1-0.4,1-1v-8L18.9,7z M6.5,17C5.7,17,5,16.3,5,15.5S5.7,14,6.5,14C7.3,14,8,14.7,8,15.5S7.3,17,6.5,17z M17.5,17c-0.8,0-1.5-0.7-1.5-1.5s0.7-1.5,1.5-1.5c0.8,0,1.5,0.7,1.5,1.5S18.3,17,17.5,17z M16,0v2H8v2h8v2l3-3L16,0z"/></g><g id="swap-driving-apps-wheel"><path d="M14.4,6.1c-0.5-0.2-1.1,0-1.3,0.6L11.7,10c-1,0.1-1.7,1-1.7,2c0,1.1,0.9,2,2,2s2-0.9,2-2c0-0.5-0.2-0.9-0.4-1.2l1.4-3.4C15.1,6.9,14.9,6.3,14.4,6.1z M7,9c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1s1-0.4,1-1C8,9.4,7.6,9,7,9z M11,7c0-0.6-0.4-1-1-1S9,6.4,9,7c0,0.6,0.4,1,1,1S11,7.6,11,7z M17,9c-0.6,0-1,0.4-1,1c0,0.6,0.4,1,1,1s1-0.4,1-1C18,9.4,17.6,9,17,9z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M17.3,18c-1.4-1.2-3.2-2-5.3-2s-3.9,0.8-5.3,2C5.1,16.5,4,14.4,4,12c0-4.4,3.6-8,8-8s8,3.6,8,8C20,14.4,18.9,16.5,17.3,18z"/></g><g id="swap-horiz"><path d="M7,11l-4,4l4,4v-3h7v-2H7V11z M21,9l-4-4v3h-7v2h7v3L21,9z"/></g><g id="swap-vert"><path d="M16,17v-7h-2v7h-3l4,4l4-4H16z M9,3L5,7h3v7h2V7h3L9,3z"/></g><g id="swap-vert-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M6.5,9L10,5.5L13.5,9H11v4H9V9H6.5z M17.5,15L14,18.5L10.5,15H13v-4h2v4H17.5z"/></g><g id="system-update-tv"><path d="M12,15l4-4h-3V3h-2v8H8L12,15z M20,3h-5v2h5v12H4V5h5V3H4C2.9,3,2,3.9,2,5v12c0,1.1,0.9,2,2,2h4v2h8v-2h4c1.1,0,2-0.9,2-2l0-12C22,3.9,21.1,3,20,3z"/></g><g id="tab"><path d="M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19L3,19V5h10v4h8V19z"/></g><g id="tab-unselected"><path d="M1,9h2V7H1V9z M1,13h2v-2H1V13z M1,5h2V3C1.9,3,1,3.9,1,5z M9,21h2v-2l-2,0V21z M1,17h2v-2H1V17z M3,21v-2H1C1,20.1,1.9,21,3,21z M21,3h-8v6h10V5C23,3.9,22.1,3,21,3z M21,17h2v-2h-2V17z M9,5h2V3H9V5z M5,21h2v-2l-2,0V21z M5,5h2V3H5V5z M21,21c1.1,0,2-0.9,2-2h-2V21z M21,13h2v-2h-2V13z M13,21h2v-2l-2,0V21z M17,21h2v-2l-2,0V21z"/></g><g id="text-format"><path d="M5,17v2h14v-2H5z M9.5,12.8h5l0.9,2.2h2.1L12.8,4h-1.5L6.5,15h2.1L9.5,12.8z M12,6l1.9,5h-3.7L12,6z"/></g><g id="theaters"><path d="M18,3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3H18z M8,17H6v-2h2V17z M8,13H6v-2h2V13z M8,9H6V7h2V9z M18,17h-2v-2h2V17z M18,13h-2v-2h2V13z M18,9h-2V7h2V9z"/></g><g id="thumb-down"><path d="M15,3H6C5.2,3,4.5,3.5,4.2,4.2l-3,7.1C1.1,11.5,1,11.7,1,12v1.9l0,0c0,0,0,0.1,0,0.1c0,1.1,0.9,2,2,2h6.3l-1,4.6c0,0.1,0,0.2,0,0.3c0,0.4,0.2,0.8,0.4,1.1L9.8,23l6.6-6.6c0.4-0.4,0.6-0.9,0.6-1.4V5C17,3.9,16.1,3,15,3z M19,3v12h4V3H19z"/></g><g id="thumb-up"><path d="M1,21h4V9H1V21z M23,10c0-1.1-0.9-2-2-2h-6.3l1-4.6c0-0.1,0-0.2,0-0.3c0-0.4-0.2-0.8-0.4-1.1L14.2,1L7.6,7.6C7.2,7.9,7,8.4,7,9v10c0,1.1,0.9,2,2,2h9c0.8,0,1.5-0.5,1.8-1.2l3-7.1c0.1-0.2,0.1-0.5,0.1-0.7V10L23,10C23,10.1,23,10,23,10z"/></g><g id="toc"><path d="M3,9h14V7H3V9z M3,13h14v-2H3V13z M3,17h14v-2H3V17z M19,17h2v-2h-2V17z M19,7v2h2V7H19z M19,13h2v-2h-2V13z"/></g><g id="today"><path d="M19,3h-1V1h-2v2H8V1H6v2H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19H5V8h14V19z"/><rect x="7" y="10" width="5" height="5"/></g><g id="translate"><path d="M12.9,15.1l-2.5-2.5l0,0c1.7-1.9,3-4.2,3.7-6.5H17V4h-7V2H8v2H1v2l11.2,0c-0.7,1.9-1.7,3.8-3.2,5.4c-0.9-1-1.7-2.2-2.3-3.4h-2c0.7,1.6,1.7,3.2,3,4.6l-5.1,5L4,19l5-5l3.1,3.1L12.9,15.1z M18.5,10h-2L12,22h2l1.1-3h4.8l1.1,3h2L18.5,10z M15.9,17l1.6-4.3l1.6,4.3H15.9z"/></g><g id="trending-down"><polygon points="16,18 18.3,15.7 13.4,10.8 9.4,14.8 2,7.4 3.4,6 9.4,12 13.4,8 19.7,14.3 22,12 22,18 "></polygon></g><g id="trending-neutral"><polygon points="22,12 18,8 18,11 3,11 3,13 18,13 18,16 "></polygon></g><g id="trending-up"><polygon points="16,6 18.3,8.3 13.4,13.2 9.4,9.2 2,16.6 3.4,18 9.4,12 13.4,16 19.7,9.7 22,12 22,6 "></polygon></g><g id="turned-in"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z"/></g><g id="turned-in-not"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z M17,18l-5-2.2L7,18V5h10V18z"/></g><g id="undo"><path d="M12,5V1.5l-5,5l5,5V7c3.3,0,6,2.7,6,6s-2.7,6-6,6c-3.3,0-6-2.7-6-6H4c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8S16.4,5,12,5z"/></g><g id="unfold-less"><path d="M7.4,18.6L8.8,20l3.2-3.2l3.2,3.2l1.4-1.4L12,14L7.4,18.6z M16.6,5.4L15.2,4L12,7.2L8.8,4L7.4,5.4L12,10L16.6,5.4z"/></g><g id="unfold-more"><path d="M12,5.8L15.2,9l1.4-1.4L12,3L7.4,7.6L8.8,9L12,5.8z M12,18.2L8.8,15l-1.4,1.4L12,21l4.6-4.6L15.2,15L12,18.2z"/></g><g id="view-array"><path d="M4,18h3V5H4V18z M18,5v13h3V5H18z M8,18h9V5H8V18z"/></g><g id="view-column"><path d="M10,18h5V5h-5V18z M4,18h5V5H4V18z M16,5v13h5V5H16z"/></g><g id="view-headline"><path d="M4,15h17v-2H4V15z M4,19h17v-2H4V19z M4,11h17V9H4V11z M4,5v2h17V5H4z"/></g><g id="view-list"><path d="M4,14h4v-4H4V14z M4,19h4v-4H4V19z M4,9h4V5H4V9z M9,14h12v-4H9V14z M9,19h12v-4H9V19z M9,5v4h12V5H9z"/></g><g id="view-module"><path d="M4,11h5V5H4V11z M4,18h5v-6H4V18z M10,18h5v-6h-5V18z M16,18h5v-6h-5V18z M10,11h5V5h-5V11z M16,5v6h5V5H16z"/></g><g id="view-quilt"><path d="M10,18h5v-6h-5V18z M4,18h5V5H4V18z M16,18h5v-6h-5V18z M10,5v6h11V5H10z"/></g><g id="view-stream"><path d="M4,18h17v-6H4V18z M4,5v6h17V5H4z"/></g><g id="visibility"><path d="M12,4.5C7,4.5,2.7,7.6,1,12c1.7,4.4,6,7.5,11,7.5c5,0,9.3-3.1,11-7.5C21.3,7.6,17,4.5,12,4.5z M12,17c-2.8,0-5-2.2-5-5s2.2-5,5-5c2.8,0,5,2.2,5,5S14.8,17,12,17z M12,9c-1.7,0-3,1.3-3,3s1.3,3,3,3c1.7,0,3-1.3,3-3S13.7,9,12,9z"/></g><g id="visibility-off"><path d="M12,7c2.8,0,5,2.2,5,5c0,0.6-0.1,1.3-0.4,1.8l2.9,2.9c1.5-1.3,2.7-2.9,3.4-4.7c-1.7-4.4-6-7.5-11-7.5c-1.4,0-2.7,0.3-4,0.7l2.2,2.2C10.7,7.1,11.4,7,12,7z M2,4.3l2.3,2.3L4.7,7c-1.7,1.3-3,3-3.7,5c1.7,4.4,6,7.5,11,7.5c1.5,0,3-0.3,4.4-0.8l0.4,0.4l2.9,2.9l1.3-1.3L3.3,3L2,4.3z M7.5,9.8l1.5,1.5C9,11.6,9,11.8,9,12c0,1.7,1.3,3,3,3c0.2,0,0.4,0,0.7-0.1l1.5,1.5C13.5,16.8,12.8,17,12,17c-2.8,0-5-2.2-5-5C7,11.2,7.2,10.5,7.5,9.8z M11.8,9l3.1,3.1c0-0.1,0-0.1,0-0.2c0-1.7-1.3-3-3-3C11.9,9,11.9,9,11.8,9z"/></g><g id="wallet-giftcard"><path d="M20,6h-2.2C17.9,5.7,18,5.4,18,5c0-1.7-1.3-3-3-3c-1,0-2,0.5-2.5,1.3l0,0L12,4l-0.5-0.7l0,0C11,2.5,10,2,9,2C7.3,2,6,3.3,6,5c0,0.4,0.1,0.7,0.2,1H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M15,4c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S14.4,4,15,4z M9,4c0.6,0,1,0.4,1,1S9.6,6,9,6S8,5.6,8,5S8.4,4,9,4z M20,19H4v-2h16V19z M20,14H4V8h5.1L7,10.8L8.6,12L11,8.8l1-1.4l1,1.4l2.4,3.2l1.6-1.2L14.9,8H20V14z"/></g><g id="wallet-membership"><path d="M20,2H4C2.9,2,2,2.9,2,4v11c0,1.1,0.9,2,2,2h4v5l4-2l4,2v-5h4c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M20,15H4v-2h16V15z M20,10H4V4h16V10z"/></g><g id="wallet-travel"><path d="M20,6h-3V4l-2-2H9L7,4v2H4C2.9,6,2,6.9,2,8v11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M9,4h6v2H9V4z M20,19H4v-2h16V19z M20,14H4V8h3v4h2V8h6v4h2V8h3V14z"/></g><g id="warning"><path d="M1,21h22L12,2L1,21z M13,18h-2v-2h2V18z M13,14h-2v-4h2V14z"/></g><g id="work"><path d="M20,6h-4V4l-2-2h-4L8,4v2H4C2.9,6,2,6.9,2,8l0,11c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8C22,6.9,21.1,6,20,6z M14,6h-4V4h4V6z"/></g></defs></svg></core-iconset-svg><polymer-element name="core-icon-button" attributes="src icon active" assetpath="../core-icon-button/"><template><style>:host{display:inline-block;box-sizing:border-box;-moz-box-sizing:border-box;user-select:none;-moz-user-select:none;-webkit-user-select:none;border-radius:2px;padding:7px;margin:2px;vertical-align:middle;font-size:1rem;cursor:pointer}:host([disabled]){opacity:.6;pointer-events:none}:host(.outline){box-shadow:0 0 0 1px rgba(0,0,0,.1)}:host(:hover:not([disabled])){box-shadow:0 1px 0 0 rgba(0,0,0,.12),0 0 0 1px rgba(0,0,0,.1)}:host(.selected:not([disabled])){background-color:rgba(0,0,0,.05);box-shadow:inset 0 1px 0 0 rgba(0,0,0,.05),0 0 0 1px rgba(0,0,0,.12)}:host(:active:not([disabled]),.selected:active:not([disabled])){background-color:rgba(0,0,0,.05);box-shadow:inset 0 1px 0 0 rgba(0,0,0,.1),0 0 0 1px rgba(0,0,0,.12)}:host(.core-dark-theme.outline){background-color:rgba(200,200,200,.05);box-shadow:0 0 0 1px rgba(200,200,200,.1)}:host(.core-dark-theme:hover){background-color:rgba(200,200,200,.05);box-shadow:0 1px 0 0 rgba(200,200,200,.12),0 0 0 1px rgba(200,200,200,.1)}:host(.core-dark-theme.selected){background-color:rgba(220,220,220,.05);box-shadow:inset 0 1px 0 0 rgba(200,200,200,.05),0 0 0 1px rgba(200,200,200,.12)}:host(.core-dark-theme:active,.core-dark-theme.selected:active){background-color:rgba(200,200,200,.05);box-shadow:inset 0 1px 0 0 rgba(200,200,200,.1),0 0 0 1px rgba(200,200,200,.12)}core-icon{pointer-events:none}:host ::content>:not(core-icon){margin-left:4px}</style><core-icon src="{{src}}" icon="{{icon}}"></core-icon><content></content></template><script>Polymer("core-icon-button",{src:"",active:false,icon:"",activeChanged:function(){this.classList.toggle("selected",this.active)}});</script></polymer-element><polymer-element name="core-toolbar" assetpath="../core-toolbar/"><template><style>:host{display:block;position:relative;box-sizing:border-box;-moz-box-sizing:border-box;height:64px;font-size:1.3em;background-color:#CFD8DC}:host(.animate){transition:height .18s ease-in}:host(.medium-tall){height:128px}:host(.tall){height:192px}.toolbar-tools{position:relative;height:64px;padding:0 8px;pointer-events:none}:host(.narrow){height:56px}:host(.narrow.medium-tall){height:112px}:host(.narrow.tall){height:168px}:host(.narrow) .toolbar-tools{height:56px;padding:0}#middleBar{position:absolute;top:0;right:0;left:0}:host(.tall,.medium-tall) #middleBar{-webkit-transform:translateY(100%);transform:translateY(100%)}#bottomBar{position:absolute;right:0;bottom:0;left:0}polyfill-next-selector{content:'.toolbar-tools > *'}::content>*{pointer-events:auto}polyfill-next-selector{content:'.toolbar-tools > *'}::content>*{margin:0 8px}polyfill-next-selector{content:'.toolbar-tools > .fit'}::content>.fit{position:absolute;top:auto;right:0;bottom:0;left:0;width:auto;margin:0}polyfill-next-selector{content:':host .indent'}::content>.indent{margin-left:60px}</style><div id="bottomBar" class="toolbar-tools" center="" horizontal="" layout=""><content select=".bottom"></content></div><div id="middleBar" class="toolbar-tools" center="" horizontal="" layout=""><content select=".middle"></content></div><div id="topBar" class="toolbar-tools" center="" horizontal="" layout=""><content></content></div></template><script>Polymer("core-toolbar");</script></polymer-element><polymer-element name="core-header-panel" assetpath="../core-header-panel/"><template><style>:host{display:block;position:relative}#outerContainer{position:absolute;top:0;right:0;bottom:0;left:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch}#mainPanel{position:relative}#mainContainer{position:relative;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch}#dropShadow{position:absolute;top:0;left:0;right:0;height:6px;box-shadow:inset 0 5px 6px -3px rgba(0,0,0,.4)}#dropShadow.hidden{display:none}:host([mode=scroll]) #mainContainer{overflow:visible}:host([mode=cover]) #mainPanel{position:static}:host([mode=cover]) #mainContainer{position:absolute;top:0;right:0;bottom:0;left:0}:host([mode=cover]) #dropShadow{position:static;width:100%}</style><div id="outerContainer" on-scroll="{{scroll}}" vertical="" layout=""><content id="headerContent" select="core-toolbar, .core-header"></content><div id="mainPanel" flex="" vertical="" layout=""><div id="mainContainer" flex?="{{mode !== &apos;cover&apos;}}" on-scroll="{{scroll}}"><content id="mainContent" select="*"></content></div><div id="dropShadow"></div></div></div></template><script>Polymer("core-header-panel",{publish:{mode:{value:"",reflect:true},tallClass:"tall",shadow:false},domReady:function(){this.async("scroll")},modeChanged:function(){this.scroll()},get header(){return this.$.headerContent.getDistributedNodes()[0]},get scroller(){return this.mode==="scroll"?this.$.outerContainer:this.$.mainContainer},scroll:function(){var shadowMode={waterfall:1,"waterfall-tall":1};var noShadow={seamed:1,cover:1,scroll:1};var tallMode={"waterfall-tall":1};var main=this.$.mainContainer;var header=this.header;var sTop=main.scrollTop;var atTop=sTop===0;if(header){this.$.dropShadow.classList.toggle("hidden",!this.shadow&&(atTop&&shadowMode[this.mode]||noShadow[this.mode]));if(tallMode[this.mode]){header.classList.toggle(this.tallClass,atTop||main.scrollHeight<this.$.outerContainer.offsetHeight)}header.classList.toggle("animate",tallMode[this.mode])}this.fire("scroll",{target:this.scroller},this,false)}});</script></polymer-element><script>(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:cap[1]==="pre"||cap[1]==="script"||cap[1]==="style",text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(this.smartypants(cap[0]));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/--/g,"—").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(){var out,err;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occured:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());</script><polymer-element name="marked-element" attributes="text" assetpath="../marked-element/"><script>Polymer("marked-element",{text:"",attached:function(){marked.setOptions({highlight:this.highlight.bind(this)});if(!this.text){this.text=this.innerHTML}},textChanged:function(){this.innerHTML=marked(this.text)},highlight:function(code,lang){var event=this.fire("marked-js-highlight",{code:code,lang:lang});return event.detail.code||code}});</script></polymer-element><script>var IN_GLOBAL_SCOPE=true;window["PR_SHOULD_USE_CONTINUATION"]=true;var prettyPrintOne;var prettyPrint;(function(){var win=window;var FLOW_CONTROL_KEYWORDS=["break,continue,do,else,for,if,return,while"];var C_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default,"+"double,enum,extern,float,goto,inline,int,long,register,short,signed,"+"sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var COMMON_KEYWORDS=[C_KEYWORDS,"catch,class,delete,false,import,"+"new,operator,private,protected,public,this,throw,true,try,typeof"];var CPP_KEYWORDS=[COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool,"+"concept,concept_map,const_cast,constexpr,decltype,delegate,"+"dynamic_cast,explicit,export,friend,generic,late_check,"+"mutable,namespace,nullptr,property,reinterpret_cast,static_assert,"+"static_cast,template,typeid,typename,using,virtual,where"];var JAVA_KEYWORDS=[COMMON_KEYWORDS,"abstract,assert,boolean,byte,extends,final,finally,implements,import,"+"instanceof,interface,null,native,package,strictfp,super,synchronized,"+"throws,transient"];var CSHARP_KEYWORDS=[JAVA_KEYWORDS,"as,base,by,checked,decimal,delegate,descending,dynamic,event,"+"fixed,foreach,from,group,implicit,in,internal,into,is,let,"+"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,"+"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,"+"var,virtual,where"];var COFFEE_KEYWORDS="all,and,by,catch,class,else,extends,false,finally,"+"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,"+"throw,true,try,unless,until,when,while,yes";var JSCRIPT_KEYWORDS=[COMMON_KEYWORDS,"debugger,eval,export,function,get,null,set,undefined,var,with,"+"Infinity,NaN"];var PERL_KEYWORDS="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,"+"goto,if,import,last,local,my,next,no,our,print,package,redo,require,"+"sub,undef,unless,until,use,wantarray,while,BEGIN,END";var PYTHON_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"and,as,assert,class,def,del,"+"elif,except,exec,finally,from,global,import,in,is,lambda,"+"nonlocal,not,or,pass,print,raise,try,with,yield,"+"False,True,None"];var RUBY_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"alias,and,begin,case,class,"+"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,"+"rescue,retry,self,super,then,true,undef,unless,until,when,yield,"+"BEGIN,END"];var RUST_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"as,assert,const,copy,drop,"+"enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,"+"pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"];var SH_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"case,done,elif,esac,eval,fi,"+"function,in,local,set,then,until"];var ALL_KEYWORDS=[CPP_KEYWORDS,CSHARP_KEYWORDS,JSCRIPT_KEYWORDS,PERL_KEYWORDS,PYTHON_KEYWORDS,RUBY_KEYWORDS,SH_KEYWORDS];var C_TYPES=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;var PR_STRING="str";var PR_KEYWORD="kwd";var PR_COMMENT="com";var PR_TYPE="typ";var PR_LITERAL="lit";var PR_PUNCTUATION="pun";var PR_PLAIN="pln";var PR_TAG="tag";var PR_DECLARATION="dec";var PR_SOURCE="src";var PR_ATTRIB_NAME="atn";var PR_ATTRIB_VALUE="atv";var PR_NOCODE="nocode";var REGEXP_PRECEDER_PATTERN="(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function combinePrefixPatterns(regexs){var capturedGroupIndex=0;var needToFoldCase=false;var ignoreCase=false;for(var i=0,n=regexs.length;i<n;++i){var regex=regexs[i];if(regex.ignoreCase){ignoreCase=true}else if(/[a-z]/i.test(regex.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){needToFoldCase=true;ignoreCase=false;break}}var escapeCharToCodeUnit={b:8,t:9,n:10,v:11,f:12,r:13};function decodeEscape(charsetPart){var cc0=charsetPart.charCodeAt(0);if(cc0!==92){return cc0}var c1=charsetPart.charAt(1);cc0=escapeCharToCodeUnit[c1];if(cc0){return cc0}else if("0"<=c1&&c1<="7"){return parseInt(charsetPart.substring(1),8)}else if(c1==="u"||c1==="x"){return parseInt(charsetPart.substring(2),16)}else{return charsetPart.charCodeAt(1)}}function encodeEscape(charCode){if(charCode<32){return(charCode<16?"\\x0":"\\x")+charCode.toString(16)}var ch=String.fromCharCode(charCode);return ch==="\\"||ch==="-"||ch==="]"||ch==="^"?"\\"+ch:ch}function caseFoldCharset(charSet){var charsetParts=charSet.substring(1,charSet.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}"+"|\\\\x[0-9A-Fa-f]{2}"+"|\\\\[0-3][0-7]{0,2}"+"|\\\\[0-7]{1,2}"+"|\\\\[\\s\\S]"+"|-"+"|[^-\\\\]","g"));var ranges=[];var inverse=charsetParts[0]==="^";var out=["["];if(inverse){out.push("^")}for(var i=inverse?1:0,n=charsetParts.length;i<n;++i){var p=charsetParts[i];if(/\\[bdsw]/i.test(p)){out.push(p)}else{var start=decodeEscape(p);var end;if(i+2<n&&"-"===charsetParts[i+1]){end=decodeEscape(charsetParts[i+2]);i+=2}else{end=start}ranges.push([start,end]);if(!(end<65||start>122)){if(!(end<65||start>90)){ranges.push([Math.max(65,start)|32,Math.min(end,90)|32])}if(!(end<97||start>122)){ranges.push([Math.max(97,start)&~32,Math.min(end,122)&~32])}}}}ranges.sort(function(a,b){return a[0]-b[0]||b[1]-a[1]});var consolidatedRanges=[];var lastRange=[];for(var i=0;i<ranges.length;++i){var range=ranges[i];if(range[0]<=lastRange[1]+1){lastRange[1]=Math.max(lastRange[1],range[1])}else{consolidatedRanges.push(lastRange=range)}}for(var i=0;i<consolidatedRanges.length;++i){var range=consolidatedRanges[i];out.push(encodeEscape(range[0]));if(range[1]>range[0]){if(range[1]+1>range[0]){out.push("-")}out.push(encodeEscape(range[1]))}}out.push("]");return out.join("")}function allowAnywhereFoldCaseAndRenumberGroups(regex){var parts=regex.source.match(new RegExp("(?:"+"\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]"+"|\\\\u[A-Fa-f0-9]{4}"+"|\\\\x[A-Fa-f0-9]{2}"+"|\\\\[0-9]+"+"|\\\\[^ux0-9]"+"|\\(\\?[:!=]"+"|[\\(\\)\\^]"+"|[^\\x5B\\x5C\\(\\)\\^]+"+")","g"));var n=parts.length;var capturedGroups=[];for(var i=0,groupIndex=0;i<n;++i){var p=parts[i];if(p==="("){++groupIndex}else if("\\"===p.charAt(0)){var decimalValue=+p.substring(1);if(decimalValue){if(decimalValue<=groupIndex){capturedGroups[decimalValue]=-1}else{parts[i]=encodeEscape(decimalValue)}}}}for(var i=1;i<capturedGroups.length;++i){if(-1===capturedGroups[i]){capturedGroups[i]=++capturedGroupIndex}}for(var i=0,groupIndex=0;i<n;++i){var p=parts[i];if(p==="("){++groupIndex;if(!capturedGroups[groupIndex]){parts[i]="(?:"}}else if("\\"===p.charAt(0)){var decimalValue=+p.substring(1);if(decimalValue&&decimalValue<=groupIndex){parts[i]="\\"+capturedGroups[decimalValue]}}}for(var i=0;i<n;++i){if("^"===parts[i]&&"^"!==parts[i+1]){parts[i]=""}}if(regex.ignoreCase&&needToFoldCase){for(var i=0;i<n;++i){var p=parts[i];var ch0=p.charAt(0);if(p.length>=2&&ch0==="["){parts[i]=caseFoldCharset(p)}else if(ch0!=="\\"){parts[i]=p.replace(/[a-zA-Z]/g,function(ch){var cc=ch.charCodeAt(0);return"["+String.fromCharCode(cc&~32,cc|32)+"]"})}}}return parts.join("")}var rewritten=[];for(var i=0,n=regexs.length;i<n;++i){var regex=regexs[i];if(regex.global||regex.multiline){throw new Error(""+regex)}rewritten.push("(?:"+allowAnywhereFoldCaseAndRenumberGroups(regex)+")")}return new RegExp(rewritten.join("|"),ignoreCase?"gi":"g")}function extractSourceSpans(node,isPreformatted){var nocode=/(?:^|\s)nocode(?:\s|$)/;var chunks=[];var length=0;var spans=[];var k=0;function walk(node){var type=node.nodeType;if(type==1){if(nocode.test(node.className)){return}for(var child=node.firstChild;child;child=child.nextSibling){walk(child)}var nodeName=node.nodeName.toLowerCase();if("br"===nodeName||"li"===nodeName){chunks[k]="\n";spans[k<<1]=length++;spans[k++<<1|1]=node}}else if(type==3||type==4){var text=node.nodeValue;if(text.length){if(!isPreformatted){text=text.replace(/[ \t\r\n]+/g," ")}else{text=text.replace(/\r\n?/g,"\n")}chunks[k]=text;spans[k<<1]=length;length+=text.length;spans[k++<<1|1]=node}}}walk(node);return{sourceCode:chunks.join("").replace(/\n$/,""),spans:spans}}function appendDecorations(basePos,sourceCode,langHandler,out){if(!sourceCode){return}var job={sourceCode:sourceCode,basePos:basePos};langHandler(job);out.push.apply(out,job.decorations)}var notWs=/\S/;function childContentWrapper(element){var wrapper=undefined;for(var c=element.firstChild;c;c=c.nextSibling){var type=c.nodeType;wrapper=type===1?wrapper?element:c:type===3?notWs.test(c.nodeValue)?element:wrapper:wrapper}return wrapper===element?undefined:wrapper}function createSimpleLexer(shortcutStylePatterns,fallthroughStylePatterns){var shortcuts={};var tokenizer;(function(){var allPatterns=shortcutStylePatterns.concat(fallthroughStylePatterns);var allRegexs=[];var regexKeys={};for(var i=0,n=allPatterns.length;i<n;++i){var patternParts=allPatterns[i];var shortcutChars=patternParts[3];if(shortcutChars){for(var c=shortcutChars.length;--c>=0;){shortcuts[shortcutChars.charAt(c)]=patternParts}}var regex=patternParts[1];var k=""+regex;if(!regexKeys.hasOwnProperty(k)){allRegexs.push(regex);regexKeys[k]=null}}allRegexs.push(/[\0-\uffff]/);tokenizer=combinePrefixPatterns(allRegexs)})();var nPatterns=fallthroughStylePatterns.length;var decorate=function(job){var sourceCode=job.sourceCode,basePos=job.basePos;var decorations=[basePos,PR_PLAIN];var pos=0;var tokens=sourceCode.match(tokenizer)||[];var styleCache={};for(var ti=0,nTokens=tokens.length;ti<nTokens;++ti){var token=tokens[ti];var style=styleCache[token];var match=void 0;var isEmbedded;if(typeof style==="string"){isEmbedded=false}else{var patternParts=shortcuts[token.charAt(0)];if(patternParts){match=token.match(patternParts[1]);style=patternParts[0]}else{for(var i=0;i<nPatterns;++i){patternParts=fallthroughStylePatterns[i];match=token.match(patternParts[1]);if(match){style=patternParts[0];break}}if(!match){style=PR_PLAIN}}isEmbedded=style.length>=5&&"lang-"===style.substring(0,5);if(isEmbedded&&!(match&&typeof match[1]==="string")){isEmbedded=false;style=PR_SOURCE}if(!isEmbedded){styleCache[token]=style}}var tokenStart=pos;pos+=token.length;if(!isEmbedded){decorations.push(basePos+tokenStart,style)}else{var embeddedSource=match[1];var embeddedSourceStart=token.indexOf(embeddedSource);var embeddedSourceEnd=embeddedSourceStart+embeddedSource.length;if(match[2]){embeddedSourceEnd=token.length-match[2].length;embeddedSourceStart=embeddedSourceEnd-embeddedSource.length}var lang=style.substring(5);appendDecorations(basePos+tokenStart,token.substring(0,embeddedSourceStart),decorate,decorations);appendDecorations(basePos+tokenStart+embeddedSourceStart,embeddedSource,langHandlerForExtension(lang,embeddedSource),decorations);appendDecorations(basePos+tokenStart+embeddedSourceEnd,token.substring(embeddedSourceEnd),decorate,decorations)}}job.decorations=decorations};return decorate}function sourceDecorator(options){var shortcutStylePatterns=[],fallthroughStylePatterns=[];if(options["tripleQuotedStrings"]){shortcutStylePatterns.push([PR_STRING,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else if(options["multiLineStrings"]){shortcutStylePatterns.push([PR_STRING,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{shortcutStylePatterns.push([PR_STRING,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}if(options["verbatimStrings"]){fallthroughStylePatterns.push([PR_STRING,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var hc=options["hashComments"];if(hc){if(options["cStyleComments"]){if(hc>1){shortcutStylePatterns.push([PR_COMMENT,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{shortcutStylePatterns.push([PR_COMMENT,/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}fallthroughStylePatterns.push([PR_STRING,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])}else{shortcutStylePatterns.push([PR_COMMENT,/^#[^\r\n]*/,null,"#"])}}if(options["cStyleComments"]){fallthroughStylePatterns.push([PR_COMMENT,/^\/\/[^\r\n]*/,null]);fallthroughStylePatterns.push([PR_COMMENT,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}var regexLiterals=options["regexLiterals"];if(regexLiterals){var regexExcls=regexLiterals>1?"":"\n\r";var regexAny=regexExcls?".":"[\\S\\s]";var REGEX_LITERAL="/(?=[^/*"+regexExcls+"])"+"(?:[^/\\x5B\\x5C"+regexExcls+"]"+"|\\x5C"+regexAny+"|\\x5B(?:[^\\x5C\\x5D"+regexExcls+"]"+"|\\x5C"+regexAny+")*(?:\\x5D|$))+"+"/";fallthroughStylePatterns.push(["lang-regex",RegExp("^"+REGEXP_PRECEDER_PATTERN+"("+REGEX_LITERAL+")")])}var types=options["types"];if(types){fallthroughStylePatterns.push([PR_TYPE,types])}var keywords=(""+options["keywords"]).replace(/^ | $/g,"");if(keywords.length){fallthroughStylePatterns.push([PR_KEYWORD,new RegExp("^(?:"+keywords.replace(/[\s,]+/g,"|")+")\\b"),null])}shortcutStylePatterns.push([PR_PLAIN,/^\s+/,null," \r\n  "]);var punctuation="^.[^\\s\\w.$@'\"`/\\\\]*";if(options["regexLiterals"]){punctuation+="(?!s*/)"}fallthroughStylePatterns.push([PR_LITERAL,/^@[a-z_$][a-z_$@0-9]*/i,null],[PR_TYPE,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[PR_PLAIN,/^[a-z_$][a-z_$@0-9]*/i,null],[PR_LITERAL,new RegExp("^(?:"+"0x[a-f0-9]+"+"|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)"+"(?:e[+\\-]?\\d+)?"+")"+"[a-z]*","i"),null,"0123456789"],[PR_PLAIN,/^\\[\s\S]?/,null],[PR_PUNCTUATION,new RegExp(punctuation),null]);return createSimpleLexer(shortcutStylePatterns,fallthroughStylePatterns)}var decorateSource=sourceDecorator({keywords:ALL_KEYWORDS,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function numberLines(node,opt_startLineNum,isPreformatted){var nocode=/(?:^|\s)nocode(?:\s|$)/;var lineBreak=/\r\n?|\n/;var document=node.ownerDocument;var li=document.createElement("li");while(node.firstChild){li.appendChild(node.firstChild)}var listItems=[li];function walk(node){var type=node.nodeType;if(type==1&&!nocode.test(node.className)){if("br"===node.nodeName){breakAfter(node);if(node.parentNode){node.parentNode.removeChild(node)}}else{for(var child=node.firstChild;child;child=child.nextSibling){walk(child)}}}else if((type==3||type==4)&&isPreformatted){var text=node.nodeValue;var match=text.match(lineBreak);if(match){var firstLine=text.substring(0,match.index);node.nodeValue=firstLine;var tail=text.substring(match.index+match[0].length);if(tail){var parent=node.parentNode;parent.insertBefore(document.createTextNode(tail),node.nextSibling)}breakAfter(node);if(!firstLine){node.parentNode.removeChild(node)}}}}function breakAfter(lineEndNode){while(!lineEndNode.nextSibling){lineEndNode=lineEndNode.parentNode;if(!lineEndNode){return}}function breakLeftOf(limit,copy){var rightSide=copy?limit.cloneNode(false):limit;var parent=limit.parentNode;if(parent){var parentClone=breakLeftOf(parent,1);var next=limit.nextSibling;parentClone.appendChild(rightSide);for(var sibling=next;sibling;sibling=next){next=sibling.nextSibling;parentClone.appendChild(sibling)}}return rightSide}var copiedListItem=breakLeftOf(lineEndNode.nextSibling,0);for(var parent;(parent=copiedListItem.parentNode)&&parent.nodeType===1;){copiedListItem=parent}listItems.push(copiedListItem)}for(var i=0;i<listItems.length;++i){walk(listItems[i])}if(opt_startLineNum===(opt_startLineNum|0)){listItems[0].setAttribute("value",opt_startLineNum)}var ol=document.createElement("ol");ol.className="linenums";var offset=Math.max(0,opt_startLineNum-1|0)||0;for(var i=0,n=listItems.length;i<n;++i){li=listItems[i];li.className="L"+(i+offset)%10;if(!li.firstChild){li.appendChild(document.createTextNode(" "))}ol.appendChild(li)}node.appendChild(ol)}function recombineTagsAndDecorations(job){var isIE8OrEarlier=/\bMSIE\s(\d+)/.exec(navigator.userAgent);isIE8OrEarlier=isIE8OrEarlier&&+isIE8OrEarlier[1]<=8;var newlineRe=/\n/g;var source=job.sourceCode;var sourceLength=source.length;var sourceIndex=0;var spans=job.spans;var nSpans=spans.length;var spanIndex=0;var decorations=job.decorations;var nDecorations=decorations.length;var decorationIndex=0;decorations[nDecorations]=sourceLength;var decPos,i;for(i=decPos=0;i<nDecorations;){if(decorations[i]!==decorations[i+2]){decorations[decPos++]=decorations[i++];decorations[decPos++]=decorations[i++]}else{i+=2}}nDecorations=decPos;for(i=decPos=0;i<nDecorations;){var startPos=decorations[i];var startDec=decorations[i+1];var end=i+2;while(end+2<=nDecorations&&decorations[end+1]===startDec){end+=2}decorations[decPos++]=startPos;decorations[decPos++]=startDec;i=end}nDecorations=decorations.length=decPos;var sourceNode=job.sourceNode;var oldDisplay;if(sourceNode){oldDisplay=sourceNode.style.display;sourceNode.style.display="none"}try{var decoration=null;while(spanIndex<nSpans){var spanStart=spans[spanIndex];var spanEnd=spans[spanIndex+2]||sourceLength;var decEnd=decorations[decorationIndex+2]||sourceLength;var end=Math.min(spanEnd,decEnd);var textNode=spans[spanIndex+1];var styledText;if(textNode.nodeType!==1&&(styledText=source.substring(sourceIndex,end))){if(isIE8OrEarlier){styledText=styledText.replace(newlineRe,"\r")}textNode.nodeValue=styledText;var document=textNode.ownerDocument;var span=document.createElement("span");span.className=decorations[decorationIndex+1];var parentNode=textNode.parentNode;parentNode.replaceChild(span,textNode);span.appendChild(textNode);if(sourceIndex<spanEnd){spans[spanIndex+1]=textNode=document.createTextNode(source.substring(end,spanEnd));parentNode.insertBefore(textNode,span.nextSibling)}}sourceIndex=end;if(sourceIndex>=spanEnd){spanIndex+=2}if(sourceIndex>=decEnd){decorationIndex+=2}}}finally{if(sourceNode){sourceNode.style.display=oldDisplay}}}var langHandlerRegistry={};function registerLangHandler(handler,fileExtensions){for(var i=fileExtensions.length;--i>=0;){var ext=fileExtensions[i];if(!langHandlerRegistry.hasOwnProperty(ext)){langHandlerRegistry[ext]=handler}else if(win["console"]){console["warn"]("cannot override language handler %s",ext)}}}function langHandlerForExtension(extension,source){if(!(extension&&langHandlerRegistry.hasOwnProperty(extension))){extension=/^\s*</.test(source)?"default-markup":"default-code"}return langHandlerRegistry[extension]}registerLangHandler(decorateSource,["default-code"]);registerLangHandler(createSimpleLexer([],[[PR_PLAIN,/^[^<?]+/],[PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);registerLangHandler(createSimpleLexer([[PR_PLAIN,/^[\s]+/,null," \r\n"],[PR_ATTRIB_VALUE,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[PR_TAG,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[PR_ATTRIB_NAME,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[PR_PUNCTUATION,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);registerLangHandler(createSimpleLexer([],[[PR_ATTRIB_VALUE,/^[\s\S]+/]]),["uq.val"]);registerLangHandler(sourceDecorator({keywords:CPP_KEYWORDS,hashComments:true,cStyleComments:true,types:C_TYPES}),["c","cc","cpp","cxx","cyc","m"]);registerLangHandler(sourceDecorator({keywords:"null,true,false"}),["json"]);registerLangHandler(sourceDecorator({keywords:CSHARP_KEYWORDS,hashComments:true,cStyleComments:true,verbatimStrings:true,types:C_TYPES}),["cs"]);registerLangHandler(sourceDecorator({keywords:JAVA_KEYWORDS,cStyleComments:true}),["java"]);registerLangHandler(sourceDecorator({keywords:SH_KEYWORDS,hashComments:true,multiLineStrings:true}),["bash","bsh","csh","sh"]);registerLangHandler(sourceDecorator({keywords:PYTHON_KEYWORDS,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py","python"]);registerLangHandler(sourceDecorator({keywords:PERL_KEYWORDS,hashComments:true,multiLineStrings:true,regexLiterals:2}),["perl","pl","pm"]);registerLangHandler(sourceDecorator({keywords:RUBY_KEYWORDS,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb","ruby"]);registerLangHandler(sourceDecorator({keywords:JSCRIPT_KEYWORDS,cStyleComments:true,regexLiterals:true}),["javascript","js"]);registerLangHandler(sourceDecorator({keywords:COFFEE_KEYWORDS,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);registerLangHandler(sourceDecorator({keywords:RUST_KEYWORDS,cStyleComments:true,multilineStrings:true}),["rc","rs","rust"]);registerLangHandler(createSimpleLexer([],[[PR_STRING,/^[\s\S]+/]]),["regex"]);function applyDecorator(job){var opt_langExtension=job.langExtension;try{var sourceAndSpans=extractSourceSpans(job.sourceNode,job.pre);var source=sourceAndSpans.sourceCode;job.sourceCode=source;job.spans=sourceAndSpans.spans;job.basePos=0;langHandlerForExtension(opt_langExtension,source)(job);recombineTagsAndDecorations(job)}catch(e){if(win["console"]){console["log"](e&&e["stack"]||e)}}}function $prettyPrintOne(sourceCodeHtml,opt_langExtension,opt_numberLines){var container=document.createElement("div");container.innerHTML="<pre>"+sourceCodeHtml+"</pre>";container=container.firstChild;if(opt_numberLines){numberLines(container,opt_numberLines,true)}var job={langExtension:opt_langExtension,numberLines:opt_numberLines,sourceNode:container,pre:1};applyDecorator(job);return container.innerHTML}function $prettyPrint(opt_whenDone,opt_root){var root=opt_root||document.body;var doc=root.ownerDocument||document;function byTagName(tn){return root.getElementsByTagName(tn)}var codeSegments=[byTagName("pre"),byTagName("code"),byTagName("xmp")];var elements=[];for(var i=0;i<codeSegments.length;++i){for(var j=0,n=codeSegments[i].length;j<n;++j){elements.push(codeSegments[i][j])}}codeSegments=null;var clock=Date;if(!clock["now"]){clock={now:function(){return+new Date}}}var k=0;var prettyPrintingJob;var langExtensionRe=/\blang(?:uage)?-([\w.]+)(?!\S)/;var prettyPrintRe=/\bprettyprint\b/;var prettyPrintedRe=/\bprettyprinted\b/;var preformattedTagNameRe=/pre|xmp/i;var codeRe=/^code$/i;var preCodeXmpRe=/^(?:pre|code|xmp)$/i;var EMPTY={};function doWork(){var endTime=win["PR_SHOULD_USE_CONTINUATION"]?clock["now"]()+250:Infinity;for(;k<elements.length&&clock["now"]()<endTime;k++){var cs=elements[k];var attrs=EMPTY;{for(var preceder=cs;preceder=preceder.previousSibling;){var nt=preceder.nodeType;var value=(nt===7||nt===8)&&preceder.nodeValue;if(value?!/^\??prettify\b/.test(value):nt!==3||/\S/.test(preceder.nodeValue)){break}if(value){attrs={};value.replace(/\b(\w+)=([\w:.%+-]+)/g,function(_,name,value){attrs[name]=value});break}}}var className=cs.className;if((attrs!==EMPTY||prettyPrintRe.test(className))&&!prettyPrintedRe.test(className)){var nested=false;for(var p=cs.parentNode;p;p=p.parentNode){var tn=p.tagName;if(preCodeXmpRe.test(tn)&&p.className&&prettyPrintRe.test(p.className)){nested=true;break}}if(!nested){cs.className+=" prettyprinted";var langExtension=attrs["lang"];if(!langExtension){langExtension=className.match(langExtensionRe);var wrapper;if(!langExtension&&(wrapper=childContentWrapper(cs))&&codeRe.test(wrapper.tagName)){langExtension=wrapper.className.match(langExtensionRe)}if(langExtension){langExtension=langExtension[1]}}var preformatted;if(preformattedTagNameRe.test(cs.tagName)){preformatted=1}else{var currentStyle=cs["currentStyle"];var defaultView=doc.defaultView;var whitespace=currentStyle?currentStyle["whiteSpace"]:defaultView&&defaultView.getComputedStyle?defaultView.getComputedStyle(cs,null).getPropertyValue("white-space"):0;preformatted=whitespace&&"pre"===whitespace.substring(0,3)}var lineNums=attrs["linenums"];if(!(lineNums=lineNums==="true"||+lineNums)){lineNums=className.match(/\blinenums\b(?::(\d+))?/);lineNums=lineNums?lineNums[1]&&lineNums[1].length?+lineNums[1]:true:false}if(lineNums){numberLines(cs,lineNums,preformatted)}prettyPrintingJob={langExtension:langExtension,sourceNode:cs,numberLines:lineNums,pre:preformatted};applyDecorator(prettyPrintingJob)}}}if(k<elements.length){setTimeout(doWork,250)}else if("function"===typeof opt_whenDone){opt_whenDone()}}doWork()}var PR=win["PR"]={createSimpleLexer:createSimpleLexer,registerLangHandler:registerLangHandler,sourceDecorator:sourceDecorator,PR_ATTRIB_NAME:PR_ATTRIB_NAME,PR_ATTRIB_VALUE:PR_ATTRIB_VALUE,PR_COMMENT:PR_COMMENT,PR_DECLARATION:PR_DECLARATION,PR_KEYWORD:PR_KEYWORD,PR_LITERAL:PR_LITERAL,PR_NOCODE:PR_NOCODE,PR_PLAIN:PR_PLAIN,PR_PUNCTUATION:PR_PUNCTUATION,PR_SOURCE:PR_SOURCE,PR_STRING:PR_STRING,PR_TAG:PR_TAG,PR_TYPE:PR_TYPE,prettyPrintOne:IN_GLOBAL_SCOPE?win["prettyPrintOne"]=$prettyPrintOne:prettyPrintOne=$prettyPrintOne,prettyPrint:prettyPrint=IN_GLOBAL_SCOPE?win["prettyPrint"]=$prettyPrint:prettyPrint=$prettyPrint};if(typeof define==="function"&&define["amd"]){define("google-code-prettify",[],function(){return PR})}})();</script><script>(function(scope){var ContextFreeParser={parse:function(text){var top={};var entities=[];var current=top;var subCurrent={};var scriptDocCommentClause="\\/\\*\\*([\\s\\S]*?)\\*\\/";var htmlDocCommentClause="<!--([\\s\\S]*?)-->";var docCommentRegex=new RegExp(scriptDocCommentClause+"|"+htmlDocCommentClause,"g");var docComments=text.match(docCommentRegex)||[];docComments.forEach(function(m){var lines=m.replace(/\r\n/g,"\n").replace(/^\s*\/\*\*|^\s*\*\/|^\s*\* ?|^\s*\<\!-\-|^s*\-\-\>/gm,"").split("\n");var pragmas=[];lines=lines.filter(function(l){var m=l.match(/\s*@([\w-]*) (.*)/);if(!m){return true}pragmas.push(m)});var code=lines.join("\n");pragmas.forEach(function(m){var pragma=m[1],content=m[2];switch(pragma){case"class":case"element":current={name:content,description:code};entities.push(current);break;case"attribute":case"property":case"method":case"event":subCurrent={name:content,description:code};var label=pragma=="property"?"properties":pragma+"s";makePragma(current,label,subCurrent);break;case"default":case"type":subCurrent[pragma]=content;break;case"param":var eventParmsRe=/\{(.+)\}\s+(\w+[.\w+]+)\s+(.*)$/;var params=content.match(eventParmsRe);if(params){var subEventObj={type:params[1],name:params[2],description:params[3]};makePragma(subCurrent,pragma+"s",subEventObj)}break;default:current[pragma]=content;break}});function makePragma(object,pragma,content){var p$=object;var p=p$[pragma];if(!p){p$[pragma]=p=[]}p.push(content)}});if(entities.length===0){entities.push({name:"Entity",description:"**Undocumented**"})}return entities}};if(typeof module!=="undefined"&&module.exports){module.exports=ContextFreeParser}else{scope.ContextFreeParser=ContextFreeParser}})(this);</script><polymer-element name="core-xhr" hidden assetpath="../core-ajax/"><script>Polymer("core-xhr",{request:function(options){var xhr=new XMLHttpRequest;var url=options.url;var method=options.method||"GET";var async=!options.sync;var params=this.toQueryString(options.params);if(params&&method=="GET"){url+=(url.indexOf("?")>0?"&":"?")+params}var xhrParams=this.isBodyMethod(method)?options.body||params:null;xhr.open(method,url,async);if(options.responseType){xhr.responseType=options.responseType}if(options.withCredentials){xhr.withCredentials=true}this.makeReadyStateHandler(xhr,options.callback);this.setRequestHeaders(xhr,options.headers);xhr.send(xhrParams);if(!async){xhr.onreadystatechange(xhr)}return xhr},toQueryString:function(params){var r=[];for(var n in params){var v=params[n];n=encodeURIComponent(n);r.push(v==null?n:n+"="+encodeURIComponent(v))}return r.join("&")},isBodyMethod:function(method){return this.bodyMethods[(method||"").toUpperCase()]},bodyMethods:{POST:1,PUT:1,DELETE:1},makeReadyStateHandler:function(xhr,callback){xhr.onreadystatechange=function(){if(xhr.readyState==4){callback&&callback.call(null,xhr.response,xhr)}}},setRequestHeaders:function(xhr,headers){if(headers){for(var name in headers){xhr.setRequestHeader(name,headers[name])}}}});</script></polymer-element><polymer-element name="core-ajax" hidden attributes="url handleAs auto params response method headers body contentType withCredentials" assetpath="../core-ajax/"><script>Polymer("core-ajax",{url:"",handleAs:"",auto:false,params:"",response:null,method:"",headers:null,body:null,contentType:"application/x-www-form-urlencoded",withCredentials:false,xhrArgs:null,ready:function(){this.xhr=document.createElement("core-xhr")},receive:function(response,xhr){if(this.isSuccess(xhr)){this.processResponse(xhr)}else{this.error(xhr)}this.complete(xhr)},isSuccess:function(xhr){var status=xhr.status||0;return!status||status>=200&&status<300},processResponse:function(xhr){var response=this.evalResponse(xhr);this.response=response;this.fire("core-response",{response:response,xhr:xhr})},error:function(xhr){var response=xhr.status+": "+xhr.responseText;this.fire("core-error",{response:response,xhr:xhr})},complete:function(xhr){this.fire("core-complete",{response:xhr.status,xhr:xhr})},evalResponse:function(xhr){return this[(this.handleAs||"text")+"Handler"](xhr)},xmlHandler:function(xhr){return xhr.responseXML},textHandler:function(xhr){return xhr.responseText},jsonHandler:function(xhr){var r=xhr.responseText;try{return JSON.parse(r)}catch(x){console.warn("core-ajax caught an exception trying to parse response as JSON:");console.warn("url:",this.url);console.warn(x);return r}},documentHandler:function(xhr){return xhr.response},blobHandler:function(xhr){return xhr.response},arraybufferHandler:function(xhr){return xhr.response},urlChanged:function(){if(!this.handleAs){var ext=String(this.url).split(".").pop();switch(ext){case"json":this.handleAs="json";break}}this.autoGo()},paramsChanged:function(){this.autoGo()},autoChanged:function(){this.autoGo()},autoGo:function(){if(this.auto){this.goJob=this.job(this.goJob,this.go,0)}},go:function(){var args=this.xhrArgs||{};args.body=this.body||args.body;args.params=this.params||args.params;if(args.params&&typeof args.params=="string"){args.params=JSON.parse(args.params)}args.headers=this.headers||args.headers||{};if(args.headers&&typeof args.headers=="string"){args.headers=JSON.parse(args.headers)}var hasContentType=Object.keys(args.headers).some(function(header){return header.toLowerCase()==="content-type"});if(!hasContentType&&this.contentType){args.headers["Content-Type"]=this.contentType}if(this.handleAs==="arraybuffer"||this.handleAs==="blob"||this.handleAs==="document"){args.responseType=this.handleAs}args.withCredentials=this.withCredentials;args.callback=this.receive.bind(this);args.url=this.url;args.method=this.method;return args.url&&this.xhr.request(args)}});</script></polymer-element><polymer-element name="context-free-parser" attributes="url text data" assetpath="../context-free-parser/"><template><core-ajax url="{{url}}" response="{{text}}" auto=""></core-ajax></template><script>Polymer("context-free-parser",{text:null,textChanged:function(){if(this.text){var entities=ContextFreeParser.parse(this.text);if(!entities||entities.length===0){entities=[{name:this.url.split("/").pop(),description:"**Undocumented**"}]}this.data={classes:entities}}},dataChanged:function(){this.fire("data-ready")}});</script></polymer-element><polymer-element name="core-doc-page" attributes="data" relative="" assetpath="../core-doc-viewer/elements/"><template><style>:host{display:block}.main{padding:0 72px;max-width:832px;margin:0 auto}marked-element{display:block}h1{color:#E91E63;font-size:52px;line-height:60px;font-weight:inherit}.box{margin-bottom:40px}.box:not(.top) .details{padding:16px}.box:not(.top) .details .params{margin-top:40px}.box:not(.top) h3{padding:16px;color:#fff;font-weight:inherit;font-size:20px;line-height:48px;margin:0}.box:not(.top) pre{padding:initial;background-color:transparent;margin:initial;font-size:12px}.box code{color:currentcolor;font-weight:500}.top pre{background-color:#fafafa;padding:16px}pre{max-width:832px;white-space:pre-wrap;overflow:hidden;border:none}.attribute-box .details{background-color:#ffcbbb;border-bottom:1px solid rgba(255,86,33,.5)}.attribute-box h3{background-color:#ff5621}.property-box .details{background-color:#fbe7b1;border-bottom:1px solid rgba(243,179,0,.5)}.property-box h3{background-color:#f3b300}.method-box .details{background-color:#a6ffea;border-bottom:1px solid rgba(0,190,164,.5)}.method-box h3{background-color:#00bea4}.event-box .details{background-color:#c5d9fb;border-bottom:1px solid rgba(65,132,243,.5)}.event-box h3{background-color:#4184f3}.badge{color:currentcolor}code,pre{color:#9f499b;font-family:"Source Code Pro",Monaco,Menlo,Consolas,"Courier New",monospace}pre .typ,pre .inline,.prettyprint .typ,.prettyprint .inline{color:#6b499f}pre .pun,.prettyprint .pun{color:#5c6bc0}pre .str,pre .string,.prettyprint .str,.prettyprint .string{color:#ff4081}pre .pln,.prettyprint .pln{color:#7986cb}pre .kwd,.prettyprint .kwd{color:#d61a7f}pre .atn,pre .attribute-name,.prettyprint .atn,.prettyprint .attribute-name{color:#6b499f}pre .atv,pre .attribute-value,.prettyprint .atv,.prettyprint .attribute-value{color:#7986cb}pre .com,pre .comment,.prettyprint .com,.prettyprint .comment{color:#8a8a8a}</style><core-header-panel id="panel" mode="waterfall" fit=""><div class="main" on-marked-js-highlight="{{hilight}}"><h1>{{data.name}}</h1><p><core-icon icon="home"></core-icon><a href="{{data | homepageFilter}}">Home Page</a></p><template if="{{data.extends}}"><section class="top"><h3>Extends: <a href="#{{data.extends}}">{{data.extends}}</a></h3></section></template><template if="{{data.description}}"><section class="box top"><h3>Summary</h3><marked-element text="{{data.description}}"></marked-element></section></template><template if="{{data.attributes.length}}"><section class="box attribute-box"><h3>Attributes</h3><template repeat="{{data.attributes}}"><div class="details" horizontal="" layout=""><div class="details-name" flex=""><p><code>{{name}}</code></p></div><div class="details-info" flex="" three=""><p layout="" horizontal="" center="" justified=""><code>{{type}}</code><span class="default" hidden?="{{!default}}">default: <code>{{default}}</code></span></p><marked-element text="{{description}}"></marked-element></div></div></template></section></template><template if="{{data.properties.length}}"><section class="box property-box"><h3>Properties</h3><template repeat="{{data.properties}}"><div class="details" horizontal="" layout=""><div class="details-name" flex=""><p><code>{{name}}</code></p></div><div class="details-info" flex="" three=""><p layout="" horizontal="" center="" justified=""><code>{{type}}</code><span class="default" hidden?="{{!default}}">default: <code>{{default}}</code></span></p><marked-element text="{{description}}"></marked-element></div></div></template></section></template><template if="{{data.events.length}}"><section class="box event-box"><h3>Events</h3><template repeat="{{data.events}}"><div class="details" horizontal="" layout=""><div class="details-name" flex=""><p><code>{{name}}</code></p></div><div class="details-info" flex="" three=""><marked-element text="{{description}}"></marked-element><template if="{{params.length}}"><div class="params"><p>Event details:</p><template repeat="{{params}}"><p><code>{{name}}</code><span><code>( {{type}} )</code></span></p><p><span>{{description}}</span></p></template></div></template></div></div></template></section></template><template if="{{data.methods.length}}"><section class="box method-box"><h3>Methods</h3><template repeat="{{data.methods}}"><div class="details" horizontal="" layout=""><div class="details-name" flex=""><p><code>{{name}}</code></p></div><div class="details-info" flex="" three=""><marked-element text="{{description}}"></marked-element><template if="{{params.length}}"><div class="params"><p>Method parameters:</p><template repeat="{{params}}"><p><code>{{name}}</code><span><code>( {{type}} )</code></span></p><p><span>{{description}}</span></p></template></div></template></div></div></template></section></template></div></core-header-panel></template><script>Polymer("core-doc-page",{hilight:function(event,detail,sender){detail.code=prettyPrintOne((detail.code||"").replace(/</g,"&lt;").replace(/>/g,"&gt;"))},homepageFilter:function(data){if(!data){return""}if(!data.homepage||data.homepage==="github.io"){return"//polymer.github.io/"+data.name}else{return data.homepage}}});</script></polymer-element><polymer-element name="core-selection" attributes="multi" hidden assetpath="../core-selection/"><script>Polymer("core-selection",{multi:false,ready:function(){this.clear()},clear:function(){this.selection=[]},getSelection:function(){return this.multi?this.selection:this.selection[0]},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})}},select:function(item){if(this.multi){this.toggle(item)}else if(this.getSelection()!==item){this.setItemSelected(this.getSelection(),false);this.setItemSelected(item,true)}},toggle:function(item){this.setItemSelected(item,!this.isSelected(item))}});</script></polymer-element><polymer-element name="core-selector" attributes="selected multi valueattr selectedClass selectedProperty selectedAttribute selectedItem selectedModel selectedIndex notap target itemsSelector activateEvent" assetpath="../core-selector/"><template><core-selection id="selection" multi="{{multi}}" on-core-select="{{selectionSelect}}"></core-selection><content id="items" select="*"></content></template><script>Polymer("core-selector",{selected:null,multi:false,valueattr:"name",selectedClass:"core-selected",selectedProperty:"",selectedAttribute:"active",selectedItem:null,selectedModel:null,selectedIndex:-1,target:null,itemsSelector:"",activateEvent:"tap",notap:false,ready:function(){this.activateListener=this.activateHandler.bind(this);this.observer=new MutationObserver(this.updateSelected.bind(this));if(!this.target){this.target=this}},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||[],function(n){return n&&n.localName!=="template"})},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)},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(){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){for(var i=0,items=this.items,c;c=items[i];i++){if(this.valueForNode(c)==value){return i}}return value},valueForNode:function(node){return node[this.valueattr]||node.getAttribute(this.valueattr)},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)}}},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){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}},selectPrevious:function(){this.selectIndex(this.selectedIndex-1)},selectNext:function(){this.selectIndex(this.selectedIndex+1)}});</script></polymer-element><style shim-shadowdom="">html /deep/ core-menu{display:block;margin:12px}polyfill-next-selector{content:'core-menu > core-item'}html /deep/ core-menu::shadow ::content>core-item{cursor:default}</style><polymer-element name="core-menu" extends="core-selector" assetpath="../core-menu/"><script>Polymer("core-menu");</script></polymer-element><style shim-shadowdom="">html /deep/ core-item{display:block;position:relative;min-height:40px;white-space:nowrap}html /deep/ core-item.font-scalable{min-height:2.5em}html /deep/ core-item.core-selected{font-weight:700}html /deep/ core-item::shadow core-icon{margin:0 16px 0 4px}html /deep/ core-item.font-scalable::shadow core-icon{margin:0 1em 0 .25em;height:1.5em;width:1.5em}html /deep/ core-item::shadow ::content>a{position:absolute;top:0;right:0;bottom:0;left:0;background-color:rgba(0,0,0,.000001)}</style><polymer-element name="core-item" attributes="label icon src" horizontal="" center="" layout="" assetpath="../core-item/"><template><core-icon src="{{src}}" icon="{{icon}}" hidden?="{{!src &amp;&amp; !icon}}"></core-icon><div id="label">{{label}}</div><content></content></template><script>Polymer("core-item",{});</script></polymer-element><polymer-element name="core-doc-toc" attributes="data selected" assetpath="../core-doc-viewer/elements/"><template><style>:host{display:block;position:relative;border-right:1px solid silver}core-header-panel{position:absolute;top:0;left:0;height:100%;width:100%}core-toolbar{background-color:#eee}</style><core-header-panel mode="waterfall"><core-menu selected="{{selected}}"><template repeat="{{data}}"><core-item><a href="#{{name}}">{{name}}</a></core-item></template></core-menu></core-header-panel></template><script>Polymer("core-doc-toc",{searchAction:function(){this.$.searchBar.style.opacity=1;this.$.searchBar.style.display=""},closeSearchAction:function(){this.$.searchBar.style.opacity=0;this.$.searchBar.style.display="none"}});</script></polymer-element><polymer-element name="core-doc-viewer" attributes="sources route url" horizontal="" layout="" assetpath="../core-doc-viewer/"><template><style>core-doc-toc{display:none;width:332px;overflow-x:hidden}</style><context-free-parser url="{{url}}" on-data-ready="{{parserDataReady}}"></context-free-parser><template repeat="{{sources}}"><context-free-parser url="{{}}" on-data-ready="{{parserDataReady}}"></context-free-parser></template><core-doc-toc id="toc" data="{{classes}}" selected="{{selected}}"></core-doc-toc><core-doc-page flex="" data="{{data}}"></core-doc-page></template><script>Polymer("core-doc-viewer",{classes:[],sources:[],ready:function(){window.addEventListener("hashchange",this.parseLocationHash.bind(this));this.parseLocationHash()},parseLocationHash:function(){this.route=window.location.hash.slice(1)},routeChanged:function(){this.validateRoute()},validateRoute:function(){if(this.route){this.classes.some(function(c){if(c.name===this.route){this.data=c;this.route="";return}},this)}},selectedChanged:function(){this.data=this.classes[this.selected]},parserDataReady:function(event){this.assimilateData(event.target.data)},assimilateData:function(data){this.classes=this.classes.concat(data.classes);this.classes.sort(function(a,b){var na=a&&a.name.toLowerCase(),nb=b&&b.name.toLowerCase();return na<nb?-1:na==nb?0:1});if(!this.data&&!this.route&&this.classes.length){this.data=this.classes[0]}if(this.classes.length>1){this.$.toc.style.display="block"}this.validateRoute()}});</script></polymer-element></div>
<div hidden>undefined</div>
<!--
Implements the default landing page for Polymer components.
`<core-component-page>` can render an information page for any component.
Polymer components use this component in `index.html` to provide the standard landing page.
`<core-component-page>` is _vulcanized_, which means it contains all it's dependencies baked in.
Therefore, this component is intended to be used only by itself in a page.
This *-dev package contains the raw source and the dependency manifest necessary
to reconstruct `core-component-page/core-component-page.html` via vulcanize. To vulcanize,
check out the core-component-page repo alongside this repo and run build.sh. This will
drop the vulcanize output into `core-component-page/core-component-page.html`.
Note: `<core-component-page>` sets the page title automatically.
@group Polymer Core Elements
@element core-component-page
-->
<polymer-element name="core-component-page" attributes="moduleName sources" layout="" vertical="" assetpath="../core-component-page-dev/"><template><style>:host{font-family:Arial,sans-serif;height:100vh}h2{display:inline-block;margin:8px 6px;vertical-align:middle}.choiceB,.choiceC,.choiceD{color:#fff;font-size:12px;font-weight:700;text-decoration:none;background-color:#4285F4;box-shadow:0 1px 2px 0 rgba(0,0,0,.1);box-shadow:0 0 1px 0 rgba(0,0,0,.1);border-radius:2px;cursor:pointer;display:inline-block;padding:4px 12px 5px 12px;margin:4px 0}.appbar{background-color:#E91E63;color:#fff}</style><core-toolbar class="appbar"><span>{{moduleName}}</span><a class="choiceC" target="_blank" href="../{{moduleName}}/demo.html">demo</a></core-toolbar><core-doc-viewer flex="" url="{{url}}" sources="{{sources}}"></core-doc-viewer></template><script>Polymer("core-component-page",{moduleName:"",sources:[],ready:function(){this.moduleName=this.moduleName||this.findModuleName()},moduleNameChanged:function(){document.title=this.moduleName;this.url=!this.sources.length&&this.moduleName?this.moduleName+".html":""},findModuleName:function(){var path=location.pathname.split("/");var name=path.pop()||path.pop();if(name.indexOf(".html")>=0){name=path.pop()}return name||""}});</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
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="../polymer/polymer.html">
<link rel="import" href="core-component-page.html">
</head>
<body unresolved>
<core-component-page></core-component-page>
</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-doc-viewer",
"private": true,
"dependencies": {
"core-ajax": "Polymer/core-ajax#^0.4.0",
"core-menu": "Polymer/core-menu#^0.4.0",
"core-item": "Polymer/core-item#^0.4.0",
"core-toolbar": "Polymer/core-toolbar#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-icon-button": "Polymer/core-icon-button#^0.4.0",
"core-header-panel": "Polymer/core-header-panel#^0.4.0",
"context-free-parser": "Polymer/context-free-parser#^0.4.0",
"marked-element": "PolymerLabs/marked-element#^0.4.0",
"prettify-element": "Polymer/prettify-element#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-doc-viewer",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "820d2b3334f6657fb93a9067ab77100a14784291"
},
"_source": "git://github.com/Polymer/core-doc-viewer.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-doc-viewer"
}
{
"name": "core-doc-viewer",
"private": true,
"dependencies": {
"core-ajax": "Polymer/core-ajax#^0.4.0",
"core-menu": "Polymer/core-menu#^0.4.0",
"core-item": "Polymer/core-item#^0.4.0",
"core-toolbar": "Polymer/core-toolbar#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-icon-button": "Polymer/core-icon-button#^0.4.0",
"core-header-panel": "Polymer/core-header-panel#^0.4.0",
"context-free-parser": "Polymer/context-free-parser#^0.4.0",
"marked-element": "PolymerLabs/marked-element#^0.4.0",
"prettify-element": "Polymer/prettify-element#^0.4.0"
}
}
<!--
@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
-->
<link rel="import" href="elements/core-doc-page.html">
<link rel="import" href="elements/core-doc-toc.html">
<link rel="import" href="../core-icon/core-icon.html">
<!--
Displays formatted source documentation scraped from input urls.
Documentation can be encoded into html comments (&lt;!-- ... --&gt;) or using JsDoc notation (/&#42;&#42; ... &#42;/).
When using JsDoc notation, remember that the left-margin includes an asterisk and a single space.
This is important for markdown constructs that count spaces. Code blocks for example, must be
five spaces from the first asterisk.
## Markdown
Markdown format is supported.
### Links
Arbitrary links can be encoded using [standard markdown format](http://daringfireball.net/projects/markdown/syntax).
[GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) is also supported.
Links to other topics can be made with hash-links [core-doc-viewer](#core-doc-viewer).
### Code
Example
Four space indents indicate code blocks.
<code>blocks are syntax highlighted</code>
<script>
while(true) {
javascript('is highlighted also');
}
</script>
### Blockquote
> Blockquote is supported for long text that needs to wrap with a common left side indent.
> Blockquote is supported for long text that needs to wrap with a common left side indent.
### Lists
1. enumerated
1. lists
Use - or + for bullet points:
- bullet
- lists
### Tables
| First Header | Second Header |
| ------------- | ------------- |
| Content Cell | Content Cell |
| Content Cell | Content Cell |
### HTML
Arbitrary HTML is also supported
<input><button>Button</button><hr/>
@class core-doc-viewer
@homepage github.io
-->
<polymer-element name="core-doc-viewer" attributes="sources route url" horizontal layout>
<template>
<style>
core-doc-toc {
display: none;
width: 332px;
overflow-x: hidden;
}
</style>
<context-free-parser url="{{url}}" on-data-ready="{{parserDataReady}}"></context-free-parser>
<template repeat="{{sources}}">
<context-free-parser url="{{}}" on-data-ready="{{parserDataReady}}"></context-free-parser>
</template>
<core-doc-toc id="toc" data="{{classes}}" selected="{{selected}}"></core-doc-toc>
<core-doc-page flex data="{{data}}"></core-doc-page>
</template>
<script>
Polymer('core-doc-viewer', {
/**
* A single file to parse for docs
*
* @attribute url
* @type String
* @default ''
*/
/**
* Class documentation extracted from the parser
*
* @property classes
* @type Array
* @default []
*/
classes: [],
/**
* Files to parse for docs
*
* @attribute sources
* @type Array
* @default []
*/
sources: [],
ready: function() {
window.addEventListener('hashchange', this.parseLocationHash.bind(this));
this.parseLocationHash();
},
parseLocationHash: function() {
this.route = window.location.hash.slice(1);
},
routeChanged: function() {
this.validateRoute();
},
validateRoute: function() {
if (this.route) {
this.classes.some(function(c) {
// The URL fragment might be just a class name,
// or it might be a class name followed by a '.' and then
// a section of the page.
// We want to match on class names here, so split on '.'.
// E.g.: 'core-ajax.properties.xhrArgs' -> 'core-ajax'
// 'core-xhr' -> 'core-xhr'
if (c.name === this.route.split('.')[0]) {
this.data = c;
this.route = '';
return;
}
}, this);
}
},
selectedChanged: function() {
this.data = this.classes[this.selected];
},
parserDataReady: function(event) {
this.assimilateData(event.target.data);
},
assimilateData: function(data) {
this.classes = this.classes.concat(data.classes);
this.classes.sort(function(a, b) {
var na = a && a.name.toLowerCase(), nb = b && b.name.toLowerCase();
return (na < nb) ? -1 : (na == nb) ? 0 : 1;
});
if (!this.data && !this.route && this.classes.length) {
this.data = this.classes[0];
}
if (this.classes.length > 1) {
this.$.toc.style.display = 'block';
}
this.validateRoute();
}
});
</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
-->
<!doctype html>
<html>
<head>
<title>core-doc-viewer</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-doc-viewer.html">
<style>
html, body {
font-family: Arial, sans-serif;
margin: 0;
}
core-doc-viewer {
height: 100vh;
}
</style>
</head>
<body unresolved>
<core-doc-viewer sources='[
"../core-doc-viewer/core-doc-viewer.html",
"../core-ajax/core-ajax.html",
"../core-ajax/core-xhr.html",
"../core-icon/core-icon.html"
]'></core-doc-viewer>
</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
*/
:host {
display: block;
}
.main {
padding: 0 72px;
max-width: 832px;
margin: 0 auto;
}
marked-element {
display: block;
}
h1 {
color: #E91E63;
font-size: 52px;
line-height: 60px;
font-weight: inherit;
}
.box {
margin-bottom: 40px;
}
.box:not(.top) .details {
padding: 16px;
}
.box:not(.top) .details .params {
margin-top: 40px;
}
.box:not(.top) h3 {
padding: 16px;
color: white;
font-weight: inherit;
font-size: 20px;
line-height: 48px;
margin: 0;
}
.box:not(.top) pre {
padding: initial;
background-color: transparent;
margin: initial;
font-size: 12px;
}
.box code {
color: currentcolor;
font-weight: 500;
}
.top pre {
background-color: rgb(250, 250, 250);
padding: 16px;
}
pre {
max-width: 832px;
white-space: pre-wrap;
overflow: hidden;
border: none;
}
.attribute-box .details {
background-color: #ffcbbb;
border-bottom: 1px solid rgba(255, 86, 33, 0.5);
}
.attribute-box h3 {
background-color: #ff5621;
}
.property-box .details {
background-color: #fbe7b1;
border-bottom: 1px solid rgba(243, 179, 0, 0.5);
}
.property-box h3 {
background-color: #f3b300;
}
.method-box .details {
background-color: #a6ffea;
border-bottom: 1px solid rgba(0, 190, 164, 0.5);
}
.method-box h3 {
background-color: #00bea4;
}
.event-box .details {
background-color: #c5d9fb;
border-bottom: 1px solid rgba(65, 132, 243, 0.5);
}
.event-box h3 {
background-color: #4184f3;
}
.badge {
color: currentcolor;
}
code, pre {
color: #9f499b;
font-family: "Source Code Pro",Monaco,Menlo,Consolas,"Courier New",monospace;
}
pre .typ,pre .inline,.prettyprint .typ,.prettyprint .inline {
color: #6b499f
}
pre .pun,.prettyprint .pun {
color: #5c6bc0
}
pre .str,pre .string,.prettyprint .str,.prettyprint .string {
color: #ff4081
}
pre .pln,.prettyprint .pln {
color: #7986cb
}
pre .kwd,.prettyprint .kwd {
color: #d61a7f
}
pre .atn,pre .attribute-name,.prettyprint .atn,.prettyprint .attribute-name {
color: #6b499f
}
pre .atv,pre .attribute-value,.prettyprint .atv,.prettyprint .attribute-value {
color: #7986cb
}
pre .com,pre .comment,.prettyprint .com,.prettyprint .comment {
color: #8a8a8a
}
<!--
@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
-->
<link rel="import" href="../../core-icons/core-icons.html">
<link rel="import" href="../../core-icon-button/core-icon-button.html">
<link rel="import" href="../../core-toolbar/core-toolbar.html">
<link rel="import" href="../../core-header-panel/core-header-panel.html">
<link rel="import" href="../../marked-element/marked-element.html">
<link rel="import" href="../../prettify-element/prettify-import.html">
<link rel="import" href="../../context-free-parser/context-free-parser.html">
<!--
Displays formatted source documentation scraped from input urls.
@element core-doc-page
-->
<polymer-element name="core-doc-page" attributes="data" relative>
<template>
<link rel="stylesheet" href="core-doc-page.css">
<core-header-panel id="panel" mode="waterfall" fit>
<!--<core-toolbar>
<span style="margin: 0 72px;">{{data.name}}</span>
</core-toolbar>-->
<div class="main" on-marked-js-highlight="{{hilight}}">
<h1>{{data.name}}</h1>
<p>
<core-icon icon="home"></core-icon>&nbsp;<a href="{{data | homepageFilter}}">Home Page</a>
</p>
<template if="{{data.extends}}">
<section class="top">
<h3 id="{{data.name}}.extends">Extends: <a href="#{{data.extends}}">{{data.extends}}</a></h3>
</section>
</template>
<template if="{{data.description}}">
<section class="box top">
<h3 id="{{data.name}}.summary">Summary</h3>
<marked-element text="{{data.description}}"></marked-element>
</section>
</template>
<template if="{{data.attributes.length}}">
<section class="box attribute-box">
<h3 id="{{data.name}}.attributes">Attributes</h3>
<template repeat="{{attribute in data.attributes}}">
<div class="details" horizontal layout>
<div class="details-name" flex id="{{data.name}}.attributes.{{attribute.name}}">
<p><code>{{attribute.name}}</code></p>
</div>
<div class="details-info" flex three>
<p layout horizontal center justified>
<code>&lt;<em>{{attribute.type}}</em>&gt;</code><span class="default" hidden?="{{!attribute.default}}">default: <code>{{attribute.default}}</code></span>
</p>
<marked-element text="{{attribute.description}}"></marked-element>
</div>
</div>
</template>
</section>
</template>
<template if="{{data.properties.length}}">
<section class="box property-box">
<h3 id="{{data.name}}.properties">Properties</h3>
<template repeat="{{property in data.properties}}">
<div class="details" horizontal layout>
<div class="details-name" flex id="{{data.name}}.properties.{{property.name}}">
<p><code>{{property.name}}</code></p>
</div>
<div class="details-info" flex three>
<p layout horizontal center justified>
<code>&lt;<em>{{property.type}}</em>&gt;</code><span class="default" hidden?="{{!property.default}}">default: <code>{{property.default}}</code></span>
</p>
<marked-element text="{{property.description}}"></marked-element>
</div>
</div>
</template>
</section>
</template>
<template if="{{data.events.length}}">
<section class="box event-box">
<h3 id="{{data.name}}.events">Events</h3>
<template repeat="{{event in data.events}}">
<div class="details" horizontal layout>
<div class="details-name" flex id="{{data.name}}.events.{{event.name}}">
<p><code>{{event.name}}</code></p>
</div>
<div class="details-info" flex three>
<marked-element text="{{event.description}}"></marked-element>
<template if="{{event.params.length}}">
<div class="params">
<p>Event details:</p>
<template repeat="{{param in event.params}}">
<p><code>&lt;<em>{{param.type}}</em>&gt; {{param.name}}</code></p>
<p><span>{{param.description}}</span></p>
</template>
</div>
</template>
</div>
</div>
</template>
</section>
</template>
<template if="{{data.methods.length}}">
<section class="box method-box">
<h3 id="{{data.name}}.methods">Methods</h3>
<template repeat="{{method in data.methods}}">
<div class="details" horizontal layout>
<div class="details-name" flex id="{{data.name}}.methods.{{method.name}}">
<p><code>{{method.name}}</code></p>
</div>
<div class="details-info" flex three>
<marked-element text="{{method.description}}"></marked-element>
<template if="{{method.params.length}}">
<div class="params">
<p>Method parameters:</p>
<template repeat="{{param in method.params}}">
<p><code>&lt;<em>{{param.type}}</em>&gt; {{param.name}}</code></p>
<p><span>{{param.description}}</span></p>
</template>
</div>
</template>
</div>
</div>
</template>
</section>
</template>
</div>
</core-header-panel>
</template>
<script>
Polymer('core-doc-page', {
hilight: function(event, detail, sender) {
detail.code = prettyPrintOne((detail.code || '').replace(/</g,'&lt;').replace(/>/g,'&gt;'));
},
homepageFilter: function(data) {
if (!data) {
return '';
}
if (!data.homepage || data.homepage === 'github.io') {
return '//polymer.github.io/' + data.name;
} else {
return data.homepage;
}
},
dataChanged: function() {
// Wrap in async() to delay execution until the next animation frame,
// since the <template> contents won't be stamped at the time this is executed.
this.async(function() {
var elementToFocus = this.shadowRoot.getElementById(window.location.hash.slice(1));
if (elementToFocus) {
elementToFocus.scrollIntoView();
}
});
}
});
</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
*/
:host {
display: block;
position: relative;
border-right: 1px solid silver;
}
core-header-panel {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
core-toolbar {
background-color: #eeeeee;
}
<!--
@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
-->
<link rel="import" href="../../core-toolbar/core-toolbar.html">
<link rel="import" href="../../core-header-panel/core-header-panel.html">
<link rel="import" href="../../core-icon-button/core-icon-button.html">
<link rel="import" href="../../core-menu/core-menu.html">
<link rel="import" href="../../core-item/core-item.html">
<!--
@class core-doc-toc
-->
<polymer-element name="core-doc-toc" attributes="data selected">
<template>
<link rel="stylesheet" href="core-doc-toc.css">
<core-header-panel mode="waterfall">
<!-- <core-toolbar theme="core-light-theme">
<core-icon-button icon="menu"></core-icon-button>
<span core-flex>Topics</span>
<core-icon-button icon="search" on-tap="{{searchAction}}"></core-icon-button>
</core-toolbar>
<core-toolbar id="searchBar" style="background-color: #C2185B; position: absolute; top: 0; left: 0; right: 0; opacity: 0; display: none;" class="seamed" theme="core-dark-theme">
<core-icon-button icon="search"></core-icon-button>
<core-icon-button icon="close" on-tap="{{closeSearchAction}}"></core-icon-button>
</core-toolbar>-->
<core-menu selected="{{selected}}">
<template repeat="{{data}}">
<core-item><a href="#{{name}}">{{name}}</a></core-item>
</template>
</core-menu>
</core-header-panel>
</template>
<script>
Polymer('core-doc-toc', {
searchAction: function() {
this.$.searchBar.style.opacity = 1;
this.$.searchBar.style.display = '';
},
closeSearchAction: function() {
this.$.searchBar.style.opacity = 0;
this.$.searchBar.style.display = 'none';
}
});
</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
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-docs",
"private": true,
"dependencies": {
"core-doc-viewer": "Polymer/core-doc-viewer#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-docs",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "a2bd7cef2bc3bbe8834dce14aa57b8b23d3048a2"
},
"_source": "git://github.com/Polymer/core-docs.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-docs"
}
{
"name": "core-docs",
"private": true,
"dependencies": {
"core-doc-viewer": "Polymer/core-doc-viewer#^0.4.0"
}
}
<!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>
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-doc-viewer/core-doc-viewer.html">
<style>
body {
font-family: sans-serif;
margin: 0;
}
core-doc-viewer {
height: 100vh;
}
</style>
</head>
<body unresolved>
<core-doc-viewer sources='[
"../core-ajax/core-ajax.html",
"../core-ajax/core-xhr.html",
"../core-animated-pages/core-animated-pages.html",
"../core-collapse/core-collapse.html",
"../core-component-page-dev/core-component-page.html",
"../core-doc-viewer/core-doc-viewer.html",
"../core-drawer-panel/core-drawer-panel.html",
"../core-field/core-field.html",
"../core-header-panel/core-header-panel.html",
"../core-scroll-header-panel/core-scroll-header-panel.html",
"../core-icon/core-icon.html",
"../core-icon-button/core-icon-button.html",
"../core-iconset/core-iconset.html",
"../core-iconset-svg/core-iconset-svg.html",
"../core-input/core-input.html",
"../core-item/core-item.html",
"../core-layout-trbl/core-layout-trbl.html",
"../core-list/core-list.html",
"../core-localstorage/core-localstorage.html",
"../core-media-query/core-media-query.html",
"../core-meta/core-meta.html",
"../core-menu/core-menu.html",
"../core-menu/core-submenu.html",
"../core-menu-button/core-menu-button.html",
"../core-overlay/core-overlay.html",
"../core-pages/core-pages.html",
"../core-range/core-range.html",
"../core-selection/core-selection.html",
"../core-selector/core-selector.html",
"../core-shared-lib/core-shared-lib.html",
"../core-style/core-style.html",
"../core-splitter/core-splitter.html",
"../core-toolbar/core-toolbar.html",
"../core-tooltip/core-tooltip.html"
]'></core-doc-viewer>
</body>
</html>
{
"name": "core-drag-drop",
"homepage": "https://github.com/Polymer/core-drag-drop",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "acf2c4ddef072ce44b9ed7501e2c42f3b615db56"
},
"_source": "git://github.com/Polymer/core-drag-drop.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-drag-drop"
}
<!--
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="../polymer/polymer.html">
<style>
core-drag-avatar {
position: fixed;
left: 0;
top: 0;
display: block;
pointer-events: none;
}
</style>
<!--
@group Polymer Core Elements
@element core-drag-drop
@homepage github.io
-->
<polymer-element name="core-drag-drop">
<script>
(function() {
var avatar;
Polymer('core-drag-drop', {
observe: {
'x y': 'coordinatesChanged'
},
ready: function() {
if (!avatar) {
avatar = document.createElement('core-drag-avatar');
document.body.appendChild(avatar);
}
this.avatar = avatar;
this.dragging = false;
},
draggingChanged: function() {
this.avatar.style.display = this.dragging ? '' : 'none';
},
coordinatesChanged: function() {
var x = this.x, y = this.y;
this.avatar.style.transform =
this.avatar.style.webkitTransform =
'translate(' + x + 'px, ' + y + 'px)';
},
attached: function() {
var listen = function(event, handler) {
Polymer.addEventListener(this.parentNode, event, this[handler].bind(this));
}.bind(this);
//
listen('trackstart', 'trackStart');
listen('track', 'track');
listen('trackend', 'trackEnd');
//
var host = this.parentNode.host || this.parentNode;
host.style.cssText += '; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none;';
},
trackStart: function(event) {
this.avatar.style.cssText = '';
this.dragInfo = {
event: event,
avatar: this.avatar
};
this.fire('drag-start', this.dragInfo);
// flaw #1: what if user doesn't need `drag()`?
this.dragging = Boolean(this.dragInfo.drag);
},
track: function(event) {
if (this.dragging) {
this.x = event.pageX;
this.y = event.pageY;
this.dragInfo.event = event;
this.dragInfo.p = {x : this.x, y: this.y};
this.dragInfo.drag(this.dragInfo);
}
},
trackEnd: function(event) {
if (this.dragging) {
this.dragging = false;
if (this.dragInfo.drop) {
this.dragInfo.framed = this.framed(event.relatedTarget);
this.dragInfo.event = event;
this.dragInfo.drop(this.dragInfo);
}
}
this.dragInfo = null;
},
framed: function(node) {
var local = node.getBoundingClientRect();
return {x: this.x - local.left, y: this.y - local.top};
}
});
})();
</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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>Core Drag Drop</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-drag-drop.html">
<style>
html {
font-family: 'Helvetica Neue', 'Roboto', 'Arial', sans-serif;
}
body {
height: 100vh;
margin: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
.box {
display: inline-block;
width: 100px;
height: 100px;
margin: 16px;
}
.dropped {
position: absolute;
border: 1px solid black;
width: 5px;
height: 5px;
}
</style>
</head>
<body unresolved>
<div style="border: 1px dotted silver;">
<core-drag-drop></core-drag-drop>
<div class="box" style="background-color: lightblue;" draggable="false"></div>
<div class="box" style="background-color: orange;" draggable="false"></div>
<div class="box" style="background-color: lightgreen;" draggable="false"></div>
<div id="hello">Hello World</div>
</div>
<br><br><br><br><br><br>
<div id="drop" class="box" style="border: 3px solid silver; position: relative; width: 300px; height: 300px;" draggable="false"></div>
<script>
addEventListener('drag-start', function(e) {
var dragInfo = e.detail;
// flaw #2: e vs dragInfo.event
var color = dragInfo.event.target.style.backgroundColor;
dragInfo.avatar.style.cssText = 'border: 3px solid ' + color + '; width: 32px; height: 32px; border-radius: 32px; background-color: whitesmoke';
e.detail.avatar.appendChild(document.querySelector('#hello'));
dragInfo.drag = function() {};
dragInfo.drop = drop;
});
//
function drop(dragInfo) {
var color = dragInfo.avatar.style.borderColor;
var dropTarget = dragInfo.event.relatedTarget;
if (color && dropTarget.id === 'drop') {
var f = dragInfo.framed;
var d = document.createElement('div');
d.className = 'dropped';
d.style.left = f.x - 4 + 'px';
d.style.top = f.y - 4 + 'px';
d.style.backgroundColor = color;
dropTarget.appendChild(d);
dropTarget.style.backgroundColor = color;
}
}
</script>
</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-drawer-panel",
"private": true,
"dependencies": {
"core-selector": "Polymer/core-selector#^0.4.0",
"core-media-query": "Polymer/core-media-query#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-drawer-panel",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "08c50f2a7ca9527a13987e83af8828926373801d"
},
"_source": "git://github.com/Polymer/core-drawer-panel.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-drawer-panel"
}
{
"name": "core-drawer-panel",
"private": true,
"dependencies": {
"core-selector": "Polymer/core-selector#^0.4.0",
"core-media-query": "Polymer/core-media-query#^0.4.0"
}
}
/*
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: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
::host.hide {
display: none;
}
core-selector > #drawer {
position: absolute;
top: 0;
left: 0;
height: 100%;
will-change: transform;
box-sizing: border-box;
-mox-box-sizing: border-box;
}
.transition > #drawer {
transition: -webkit-transform ease-in-out 0.3s, width ease-in-out 0.3s;
transition: transform ease-in-out 0.3s, width ease-in-out 0.3s;
}
/*
right-drawer: make drawer on the right side
*/
.right-drawer > #drawer {
left: auto;
right: 0;
}
.right-drawer.transition > #drawer {
transition: -webkit-transform ease-in-out 0.3s, width ease-in-out 0.3s;
transition: transform ease-in-out 0.3s, width ease-in-out 0.3s;
}
polyfill-next-selector { content: ':host [drawer]'; }
::content[select="[drawer]"] > * {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
core-selector > #main {
position: absolute;
top: 0;
right: 0;
bottom: 0;
}
.transition > #main {
transition: left ease-in-out 0.3s, padding ease-in-out 0.3s;
}
.right-drawer > #main {
left: 0;
}
.right-drawer.transition > #main {
transition: right ease-in-out 0.3s, padding ease-in-out 0.3s;
}
polyfill-next-selector { content: '#main > [main]'; }
::content[select="[main]"] > * {
height: 100%;
}
#scrim {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.3);
visibility: hidden;
opacity: 0;
transition: opacity ease-in-out 0.38s, visibility ease-in-out 0.38s;
}
/*
narrow layout
*/
.narrow-layout > #drawer.core-selected {
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15);
}
.right-drawer.narrow-layout > #drawer.core-selected {
box-shadow: -2px 2px 4px rgba(0, 0, 0, 0.15);
}
polyfill-next-selector { content: ':host .narrow-layout > #drawer > [drawer]'; }
.narrow-layout > #drawer > ::content[select="[drawer]"] > * {
border: 0;
}
.narrow-layout > #drawer:not(.core-selected) {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
}
.right-drawer.narrow-layout > #drawer:not(.core-selected) {
left: auto;
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
.narrow-layout > #main {
left: 0 !important;
padding: 0;
}
.right-drawer.narrow-layout > #main {
left: 0;
right: 0;
padding: 0;
}
.narrow-layout > #main:not(.core-selected) > #scrim,
.dragging #scrim {
visibility: visible;
opacity: 1;
}
polyfill-next-selector { content: ':host .narrow-layout > #main > [main]'; }
.narrow-layout > #main > ::content[select="[main]"] > * {
margin: 0;
min-height: 100%;
left: 0;
right: 0;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
<!--
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
-->
<!--
`core-drawer-panel` contains a drawer panel and a main panel. The drawer
and the main panel are side-by-side with drawer on the left. When browser
window size is smaller than the `responsiveWidth`, `core-drawer-panel`
changes to narrow layout. In narrow layout, the drawer will be stacked on top
of the main panel. The drawer will be slided in/out to hide/reveal the main
panel.
Use the attribute `drawer` to indicate the element is a drawer panel and
`main` to indicate is a main panel.
Example:
<core-drawer-panel>
<div drawer> Drawer panel... </div>
<div main> Main panel... </div>
</core-drawer-panel>
The drawer and the main panels are not scrollable. You can set CSS overflow
property on the elements to make them scrollable or use `core-header-panel`.
Example:
<core-drawer-panel>
<core-header-panel drawer>
<core-toolbar></core-toolbar>
<div> Drawer content... </div>
</core-header-panel>
<core-header-panel main>
<core-toolbar></core-toolbar>
<div> Main content... </div>
</core-header-panel>
</core-drawer-panel>
To position the drawer to the right, add `rightDrawer` attribute.
<core-drawer-panel rightDrawer>
<div drawer> Drawer panel... </div>
<div main> Main panel... </div>
</core-drawer-panel>
@group Polymer Core Elements
@element core-drawer-panel
@homepage github.io
-->
<link rel="import" href="../core-media-query/core-media-query.html">
<link rel="import" href="../core-selector/core-selector.html">
<polymer-element name="core-drawer-panel" touch-action="auto">
<template>
<link rel="stylesheet" href="core-drawer-panel.css">
<core-media-query query="max-width: {{responsiveWidth}}" queryMatches="{{queryMatches}}"></core-media-query>
<core-selector class="{{ {'narrow-layout' : queryMatches, transition : transition, dragging : dragging, 'right-drawer': rightDrawer} | tokenList }}" valueattr="id" selected="{{selected}}">
<div id="main" _style="left: {{ narrow || rightDrawer ? '0' : drawerWidth }}; right: {{ rightDrawer ? (narrow ? '' : drawerWidth) : '' }};">
<content select="[main]"></content>
<div id="scrim" on-tap="{{togglePanel}}"></div>
</div>
<div id="drawer" _style="width: {{ drawerWidth }}">
<content select="[drawer]"></content>
</div>
</core-selector>
</template>
<script>
Polymer('core-drawer-panel', {
/**
* Fired when the narrow layout changes.
*
* @event core-responsive-change
* @param {Object} detail
* @param {boolean} detail.narrow true if the panel is in narrow layout.
*/
publish: {
/**
* Width of the drawer panel.
*
* @attribute drawerWidth
* @type string
* @default '256px'
*/
drawerWidth: '256px',
/**
* Max-width when the panel changes to narrow layout.
*
* @attribute responsiveWidth
* @type string
* @default '640px'
*/
responsiveWidth: '640px',
/**
* The panel that is being selected. `drawer` for the drawer panel and
* `main` for the main panel.
*
* @attribute selected
* @type string
* @default null
*/
selected: {value: null, reflect: true},
/**
* The panel to be selected when `core-drawer-panel` changes to narrow
* layout.
*
* @attribute defaultSelected
* @type string
* @default 'main'
*/
defaultSelected: 'main',
/**
* Returns true if the panel is in narrow layout. This is useful if you
* need to show/hide elements based on the layout.
*
* @attribute narrow
* @type boolean
* @default false
*/
narrow: {value: false, reflect: true},
/**
* If true, position the drawer to the right.
*
* @attribute rightDrawer
* @type boolean
* @default false
*/
rightDrawer: false,
/**
* If true, swipe to open/close the drawer is disabled.
*
* @attribute disableSwipe
* @type boolean
* @default false
*/
disableSwipe: false
},
eventDelegates: {
trackstart: 'trackStart',
trackx: 'trackx',
trackend: 'trackEnd',
down: 'touchStart',
up: 'touchEnd'
},
// Whether the transition is enabled.
transition: false,
// How many pixels on the side of the screen are sensitive to edge swipes and peek.
edgeSwipeSensitivity: 15,
// Whether the drawer is peeking out from the edge.
peeking: false,
// Whether the user is dragging the drawer interactively.
dragging: false,
// Whether the browser has support for the transform CSS property.
hasTransform: true,
// Whether the browser has support for the will-change CSS property.
hasWillChange: true,
created: function() {
this.hasTransform = 'transform' in this.style;
this.hasWillChange = 'willChange' in this.style;
},
domReady: function() {
// to avoid transition at the beginning e.g. page loads
// NOTE: domReady is already raf delayed and delaying another frame
// ensures a layout has occurred.
this.async(function() {
this.transition = true;
});
},
/**
* Toggles the panel open and closed.
*
* @method togglePanel
*/
togglePanel: function() {
this.selected = this.selected === 'main' ? 'drawer' : 'main';
},
/**
* Opens the drawer.
*
* @method openDrawer
*/
openDrawer: function() {
this.selected = 'drawer';
},
/**
* Closes the drawer.
*
* @method closeDrawer
*/
closeDrawer: function() {
this.selected = 'main';
},
queryMatchesChanged: function() {
if (this.queryMatches) {
this.selected = this.defaultSelected;
}
this.narrow = this.queryMatches;
this.setAttribute('touch-action', this.swipeAllowed() ? 'pan-y' : '');
this.fire('core-responsive-change', {narrow: this.narrow});
},
swipeAllowed: function() {
return this.narrow && !this.disableSwipe;
},
startEdgePeek: function() {
this.width = this.$.drawer.offsetWidth;
this.moveDrawer(this.translateXForDeltaX(this.rightDrawer ?
-this.edgeSwipeSensitivity : this.edgeSwipeSensitivity));
this.peeking = true;
},
stopEdgePeak: function() {
if (this.peeking) {
this.peeking = false;
this.moveDrawer(null);
}
},
touchStart: function(e) {
if (!this.dragging && this.selected === 'main' && this.isEdgeTouch(e))
this.startEdgePeek();
},
touchEnd: function(e) {
this.stopEdgePeak();
},
isEdgeTouch: function(e) {
return this.swipeAllowed() && (this.rightDrawer ?
e.pageX >= this.offsetWidth - this.edgeSwipeSensitivity :
e.pageX <= this.edgeSwipeSensitivity);
},
// swipe support for the drawer, inspired by
// https://github.com/Polymer/core-drawer-panel/pull/6
trackStart : function(e) {
if (this.swipeAllowed()) {
this.dragging = true;
if (this.selected === 'main')
this.dragging = this.peeking || this.isEdgeTouch(e);
if (this.dragging) {
this.width = this.$.drawer.offsetWidth;
this.transition = false;
e.preventTap();
}
}
},
translateXForDeltaX: function(deltaX) {
if (this.rightDrawer) {
return Math.max(0, (this.selected === 'main') ? this.width + deltaX : deltaX);
} else {
return Math.min(0, (this.selected === 'main') ? deltaX - this.width : deltaX);
}
},
trackx : function(e) {
if (this.dragging) {
if (this.peeking) {
if (Math.abs(e.dx) <= this.edgeSwipeSensitivity)
return; // Ignore trackx until we move past the edge peek.
this.peeking = false;
}
this.moveDrawer(this.translateXForDeltaX(e.dx));
}
},
trackEnd : function(e) {
if (this.dragging) {
this.dragging = false;
this.transition = true;
this.moveDrawer(null);
if (this.rightDrawer) {
this.selected = e.xDirection > 0 ? 'main' : 'drawer';
} else {
this.selected = e.xDirection > 0 ? 'drawer' : 'main';
}
}
},
transformForTranslateX: function (translateX) {
if (translateX === null)
return '';
return this.hasWillChange ? 'translateX(' + translateX + 'px)' : 'translate3d(' + translateX + 'px, 0, 0)';
},
moveDrawer: function(translateX) {
var s = this.$.drawer.style;
if (this.hasTransform) {
s.transform = this.transformForTranslateX(translateX);
} else {
s.webkitTransform = this.transformForTranslateX(translateX);
}
},
});
</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>core-drawer-panel</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-drawer-panel.html">
<style>
html, body {
height: 100%;
}
body {
font-family: sans-serif;
color: #FFF;
margin: 0;
}
[drawer] {
background-color: #B99588;
border-right: 1px solid #ccc;
}
[main] {
height: 100%;
background-color: #4F7DC9;
}
button {
display: none;
width: 160px;
height: 40px;
font-size: 16px;
margin: 8px;
}
core-drawer-panel[narrow] button {
display: inline-block
}
</style>
</head>
<body unresolved>
<core-drawer-panel>
<div drawer></div>
<div main>
<button onclick="document.querySelector('core-drawer-panel').togglePanel();">toggle drawer</button>
</div>
</core-drawer-panel>
</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="section" label="Section" isContainer group="Core">
<template>
<section style="width: 200px; height: 300px;" layout vertical></section>
</template>
</x-meta>
<x-meta id="core-drawer-panel" label="Drawer Panel" isContainer group="Core">
<template>
<core-drawer-panel style="position: absolute; top: 0; right: 0; bottom: 0; left: 0;">
<section drawer style="background-color: #fafafa; box-shadow: rgba(0, 0, 0, 0.098) 0px 2px 4px, rgba(0, 0, 0, 0.098) 0px 0px 3px;"></section>
<section main style="height: 100%; box-sizing: border-box; background-color: #ddd"></section>
</core-drawer-panel>
</template>
<template id="imports">
<link rel="import" href="core-drawer-panel.html">
</template>
</x-meta>
{
"name": "core-dropdown-menu",
"private": false,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-dropdown": "Polymer/core-dropdown#^0.4.0",
"core-icon": "Polymer/core-icon#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-item": "Polymer/core-item#^0.4.0",
"core-menu": "Polymer/core-menu#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-dropdown-menu",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "b81d518e36a7c73c24027281cb4bdf070f6c8f80"
},
"_source": "git://github.com/Polymer/core-dropdown-menu.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-dropdown-menu"
}
{
"name": "core-dropdown-menu",
"private": false,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-dropdown": "Polymer/core-dropdown#^0.4.0",
"core-icon": "Polymer/core-icon#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-item": "Polymer/core-item#^0.4.0",
"core-menu": "Polymer/core-menu#^0.4.0"
}
}
/*
* @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
*/
:host {
position: relative;
display: inline-block;
background-color: #fff;
}
#control core-item {
margin-left: 12px;
max-width: inherit;
}
#control core-item::shadow #label {
overflow: hidden;
/* FIXME not working for some reason */
white-space: nowrap;
text-overflow: ellipsis;
}
#arrow {
margin: 0 12px;
}
#dropdown {
margin: 12px;
}
<!--
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
-->
<!--
`core-dropdown-menu` is a control where the user can choose from an array of options in a drop-down
menu. The currently selected option is displayed in the control.
Example:
<core-dropdown-menu selected="Financier" valueattr="label">
<core-item label="Croissant"></core-item>
<core-item label="Donut"></core-item>
<core-item label="Financier"></core-item>
<core-item label="Madeleine"></core-item>
</core-dropdown-menu>
This example renders a drop-down menu with 4 options, with the option `Financier` pre-selected.
Theming
-------
Style the drop-down menu with the `core-dropdown-menu::shadow #dropdown` selector.
Example:
core-dropdown-menu::shadow #dropdown {
border: 1px solid #ccc;
max-height: 12px;
}
To modify the drop-down's margins, use the same selector. The default margin is 12px.
core-dropdown-menu::shadow #dropdown {
margin: 24px;
}
@group Polymer Core Elements
@element core-dropdown-menu
@status beta
@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 href="../polymer/polymer.html" rel="import">
<link href="../core-icon/core-icon.html" rel="import">
<link href="../core-icons/core-icons.html" rel="import">
<link href="../core-item/core-item.html" rel="import">
<link href="../core-menu/core-menu.html" rel="import">
<link href="../core-dropdown/core-dropdown.html" rel="import">
<polymer-element name="core-dropdown-menu">
<template>
<link href="core-dropdown-menu.css" rel="stylesheet">
<div id="control" layout horizontal center on-tap="{{toggle}}">
<core-item flex src="{{selectedItem.src}}" icon="{{selectedItem.icon}}" label="{{selectedItem ? (selectedItem.label || selected) : label}}"></core-item>
<core-icon id="arrow" icon="{{opened ? 'arrow-drop-up' : 'arrow-drop-down'}}"></core-icon>
</div>
<core-dropdown id="dropdown" relatedTarget="{{$.control}}" opened="{{opened}}" halign="{{halign}}" valign="{{valign}}">
<core-menu selected="{{selected}}" valueattr="{{valueattr}}" selectedItem="{{selectedItem}}" on-core-activate="{{activateAction}}">
<content></content>
</core-menu>
</core-dropdown>
</template>
<script>
Polymer({
publish: {
/**
* True if the menu is open.
*
* @attribute opened
* @type boolean
* @default false
*/
opened: false,
/**
* A label for the control. The label is displayed if no item is selected.
*
* @attribute label
* @type string
* @default 'Select an item'
*/
label: 'Select an item',
/**
* The currently selected element. By default this is the index of the item element.
* If you want a specific attribute value of the element to be used instead of the
* index, set `valueattr` to that attribute name.
*
* @attribute selected
* @type Object
* @default null
*/
selected: null,
/**
* 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: 'selected',
/**
* The currently selected element.
*
* @attribute selectedItem
* @type Object
* @default null
*/
selectedItem: null,
/**
* Horizontally align the overlay with the control.
*
* @attribute halign
* @type "left" | "right"
* @default "left"
*/
halign: 'left',
/**
* Vertically align the dropdown menu with the control.
*
* @attribute valign
* @type "top" | "bottom"
* @default "bottom"
*/
valign: 'top'
},
activateAction: function() {
this.opened = false;
},
toggle: function() {
this.opened = !this.opened;
}
});
</script>
</polymer-element>
<!doctype html>
<!--
Copyright 2013 The Polymer Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>core-dropdown-menu</title>
<script src="../platform/platform.js"></script>
<link href="core-dropdown-menu.html" rel="import">
<style shim-shadowdom>
html, body {
height: 100%;
}
dropdown-demo {
display: block;
}
dropdown-demo::shadow > section {
padding: 12px;
}
body /deep/ core-dropdown-menu {
background-color: #eee;
}
body /deep/ core-dropdown-menu.narrow {
max-width: 100px;
}
body /deep/ core-dropdown-menu::shadow #dropdown {
background-color: #eee;
border: 1px solid #ccc;
}
body /deep/ core-dropdown-menu.constrained::shadow #dropdown {
max-height: 500px;
}
</style>
</head>
<body unresolved fullbleed>
<polymer-element name="dropdown-demo">
<template>
<section layout vertical fit>
<section layout horizontal>
<core-dropdown-menu>
<template repeat="{{countries}}">
<core-item label="{{name}}"></core-item>
</template>
</core-dropdown-menu>
<div style="margin:0 12px;">
narrow:
<core-dropdown-menu class="narrow">
<template repeat="{{countries}}">
<core-item label="{{name}}"></core-item>
</template>
</core-dropdown-menu>
</div>
<div flex></div>
<core-dropdown-menu halign="right">
<template repeat="{{countries}}">
<core-item label="{{name}}"></core-item>
</template>
</core-dropdown-menu>
</section>
<div flex style="overflow:auto;">
<br>
<core-dropdown-menu class="constrained">
<template repeat="{{countries}}">
<core-item label="{{name}}"></core-item>
</template>
</core-dropdown-menu>
<p>scroll me...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<section>
drop-up:
<core-dropdown-menu valign="bottom" valueattr="label" selected="Donut">
<core-item label="Croissant"></core-item>
<core-item label="Donut"></core-item>
<core-item label="Financier"></core-item>
<core-item label="Madeleine"></core-item>
</core-dropdown-menu>
</section>
</section>
</template>
<script>
Polymer('dropdown-demo', {
countries: [
{name: 'Afghanistan', code: 'AF'},
{name: 'Åland Islands', code: 'AX'},
{name: 'Albania', code: 'AL'},
{name: 'Algeria', code: 'DZ'},
{name: 'American Samoa', code: 'AS'},
{name: 'Andorra', code: 'AD'},
{name: 'Angola', code: 'AO'},
{name: 'Anguilla', code: 'AI'},
{name: 'Antarctica', code: 'AQ'},
{name: 'Antigua and Barbuda', code: 'AG'},
{name: 'Argentina', code: 'AR'},
{name: 'Armenia', code: 'AM'},
{name: 'Aruba', code: 'AW'},
{name: 'Australia', code: 'AU'},
{name: 'Austria', code: 'AT'},
{name: 'Azerbaijan', code: 'AZ'},
{name: 'Bahamas', code: 'BS'},
{name: 'Bahrain', code: 'BH'},
{name: 'Bangladesh', code: 'BD'},
{name: 'Barbados', code: 'BB'},
{name: 'Belarus', code: 'BY'},
{name: 'Belgium', code: 'BE'},
{name: 'Belize', code: 'BZ'},
{name: 'Benin', code: 'BJ'},
{name: 'Bermuda', code: 'BM'},
{name: 'Bhutan', code: 'BT'},
{name: 'Bolivia', code: 'BO'},
{name: 'Bosnia and Herzegovina', code: 'BA'},
{name: 'Botswana', code: 'BW'},
{name: 'Bouvet Island', code: 'BV'},
{name: 'Brazil', code: 'BR'},
{name: 'British Indian Ocean Territory', code: 'IO'},
{name: 'Brunei Darussalam', code: 'BN'},
{name: 'Bulgaria', code: 'BG'},
{name: 'Burkina Faso', code: 'BF'},
{name: 'Burundi', code: 'BI'},
{name: 'Cambodia', code: 'KH'},
{name: 'Cameroon', code: 'CM'},
{name: 'Canada', code: 'CA'},
{name: 'Cape Verde', code: 'CV'},
{name: 'Cayman Islands', code: 'KY'},
{name: 'Central African Republic', code: 'CF'},
{name: 'Chad', code: 'TD'},
{name: 'Chile', code: 'CL'},
{name: 'China', code: 'CN'},
{name: 'Christmas Island', code: 'CX'},
{name: 'Cocos (Keeling) Islands', code: 'CC'},
{name: 'Colombia', code: 'CO'},
{name: 'Comoros', code: 'KM'},
{name: 'Congo', code: 'CG'},
{name: 'Congo, The Democratic Republic of the', code: 'CD'},
{name: 'Cook Islands', code: 'CK'},
{name: 'Costa Rica', code: 'CR'},
{name: 'Cote D\'Ivoire', code: 'CI'},
{name: 'Croatia', code: 'HR'},
{name: 'Cuba', code: 'CU'},
{name: 'Cyprus', code: 'CY'},
{name: 'Czech Republic', code: 'CZ'},
{name: 'Denmark', code: 'DK'},
{name: 'Djibouti', code: 'DJ'},
{name: 'Dominica', code: 'DM'},
{name: 'Dominican Republic', code: 'DO'},
{name: 'Ecuador', code: 'EC'},
{name: 'Egypt', code: 'EG'},
{name: 'El Salvador', code: 'SV'},
{name: 'Equatorial Guinea', code: 'GQ'},
{name: 'Eritrea', code: 'ER'},
{name: 'Estonia', code: 'EE'},
{name: 'Ethiopia', code: 'ET'},
{name: 'Falkland Islands (Malvinas)', code: 'FK'},
{name: 'Faroe Islands', code: 'FO'},
{name: 'Fiji', code: 'FJ'},
{name: 'Finland', code: 'FI'},
{name: 'France', code: 'FR'},
{name: 'French Guiana', code: 'GF'},
{name: 'French Polynesia', code: 'PF'},
{name: 'French Southern Territories', code: 'TF'},
{name: 'Gabon', code: 'GA'},
{name: 'Gambia', code: 'GM'},
{name: 'Georgia', code: 'GE'},
{name: 'Germany', code: 'DE'},
{name: 'Ghana', code: 'GH'},
{name: 'Gibraltar', code: 'GI'},
{name: 'Greece', code: 'GR'},
{name: 'Greenland', code: 'GL'},
{name: 'Grenada', code: 'GD'},
{name: 'Guadeloupe', code: 'GP'},
{name: 'Guam', code: 'GU'},
{name: 'Guatemala', code: 'GT'},
{name: 'Guernsey', code: 'GG'},
{name: 'Guinea', code: 'GN'},
{name: 'Guinea-Bissau', code: 'GW'},
{name: 'Guyana', code: 'GY'},
{name: 'Haiti', code: 'HT'},
{name: 'Heard Island and Mcdonald Islands', code: 'HM'},
{name: 'Holy See (Vatican City State)', code: 'VA'},
{name: 'Honduras', code: 'HN'},
{name: 'Hong Kong', code: 'HK'},
{name: 'Hungary', code: 'HU'},
{name: 'Iceland', code: 'IS'},
{name: 'India', code: 'IN'},
{name: 'Indonesia', code: 'ID'},
{name: 'Iran, Islamic Republic Of', code: 'IR'},
{name: 'Iraq', code: 'IQ'},
{name: 'Ireland', code: 'IE'},
{name: 'Isle of Man', code: 'IM'},
{name: 'Israel', code: 'IL'},
{name: 'Italy', code: 'IT'},
{name: 'Jamaica', code: 'JM'},
{name: 'Japan', code: 'JP'},
{name: 'Jersey', code: 'JE'},
{name: 'Jordan', code: 'JO'},
{name: 'Kazakhstan', code: 'KZ'},
{name: 'Kenya', code: 'KE'},
{name: 'Kiribati', code: 'KI'},
{name: 'Korea, Democratic People\'S Republic of', code: 'KP'},
{name: 'Korea, Republic of', code: 'KR'},
{name: 'Kuwait', code: 'KW'},
{name: 'Kyrgyzstan', code: 'KG'},
{name: 'Lao People\'S Democratic Republic', code: 'LA'},
{name: 'Latvia', code: 'LV'},
{name: 'Lebanon', code: 'LB'},
{name: 'Lesotho', code: 'LS'},
{name: 'Liberia', code: 'LR'},
{name: 'Libyan Arab Jamahiriya', code: 'LY'},
{name: 'Liechtenstein', code: 'LI'},
{name: 'Lithuania', code: 'LT'},
{name: 'Luxembourg', code: 'LU'},
{name: 'Macao', code: 'MO'},
{name: 'Macedonia, The Former Yugoslav Republic of', code: 'MK'},
{name: 'Madagascar', code: 'MG'},
{name: 'Malawi', code: 'MW'},
{name: 'Malaysia', code: 'MY'},
{name: 'Maldives', code: 'MV'},
{name: 'Mali', code: 'ML'},
{name: 'Malta', code: 'MT'},
{name: 'Marshall Islands', code: 'MH'},
{name: 'Martinique', code: 'MQ'},
{name: 'Mauritania', code: 'MR'},
{name: 'Mauritius', code: 'MU'},
{name: 'Mayotte', code: 'YT'},
{name: 'Mexico', code: 'MX'},
{name: 'Micronesia, Federated States of', code: 'FM'},
{name: 'Moldova, Republic of', code: 'MD'},
{name: 'Monaco', code: 'MC'},
{name: 'Mongolia', code: 'MN'},
{name: 'Montserrat', code: 'MS'},
{name: 'Morocco', code: 'MA'},
{name: 'Mozambique', code: 'MZ'},
{name: 'Myanmar', code: 'MM'},
{name: 'Namibia', code: 'NA'},
{name: 'Nauru', code: 'NR'},
{name: 'Nepal', code: 'NP'},
{name: 'Netherlands', code: 'NL'},
{name: 'Netherlands Antilles', code: 'AN'},
{name: 'New Caledonia', code: 'NC'},
{name: 'New Zealand', code: 'NZ'},
{name: 'Nicaragua', code: 'NI'},
{name: 'Niger', code: 'NE'},
{name: 'Nigeria', code: 'NG'},
{name: 'Niue', code: 'NU'},
{name: 'Norfolk Island', code: 'NF'},
{name: 'Northern Mariana Islands', code: 'MP'},
{name: 'Norway', code: 'NO'},
{name: 'Oman', code: 'OM'},
{name: 'Pakistan', code: 'PK'},
{name: 'Palau', code: 'PW'},
{name: 'Palestinian Territory, Occupied', code: 'PS'},
{name: 'Panama', code: 'PA'},
{name: 'Papua New Guinea', code: 'PG'},
{name: 'Paraguay', code: 'PY'},
{name: 'Peru', code: 'PE'},
{name: 'Philippines', code: 'PH'},
{name: 'Pitcairn', code: 'PN'},
{name: 'Poland', code: 'PL'},
{name: 'Portugal', code: 'PT'},
{name: 'Puerto Rico', code: 'PR'},
{name: 'Qatar', code: 'QA'},
{name: 'Reunion', code: 'RE'},
{name: 'Romania', code: 'RO'},
{name: 'Russian Federation', code: 'RU'},
{name: 'RWANDA', code: 'RW'},
{name: 'Saint Helena', code: 'SH'},
{name: 'Saint Kitts and Nevis', code: 'KN'},
{name: 'Saint Lucia', code: 'LC'},
{name: 'Saint Pierre and Miquelon', code: 'PM'},
{name: 'Saint Vincent and the Grenadines', code: 'VC'},
{name: 'Samoa', code: 'WS'},
{name: 'San Marino', code: 'SM'},
{name: 'Sao Tome and Principe', code: 'ST'},
{name: 'Saudi Arabia', code: 'SA'},
{name: 'Senegal', code: 'SN'},
{name: 'Serbia and Montenegro', code: 'CS'},
{name: 'Seychelles', code: 'SC'},
{name: 'Sierra Leone', code: 'SL'},
{name: 'Singapore', code: 'SG'},
{name: 'Slovakia', code: 'SK'},
{name: 'Slovenia', code: 'SI'},
{name: 'Solomon Islands', code: 'SB'},
{name: 'Somalia', code: 'SO'},
{name: 'South Africa', code: 'ZA'},
{name: 'South Georgia and the South Sandwich Islands', code: 'GS'},
{name: 'Spain', code: 'ES'},
{name: 'Sri Lanka', code: 'LK'},
{name: 'Sudan', code: 'SD'},
{name: 'Suriname', code: 'SR'},
{name: 'Svalbard and Jan Mayen', code: 'SJ'},
{name: 'Swaziland', code: 'SZ'},
{name: 'Sweden', code: 'SE'},
{name: 'Switzerland', code: 'CH'},
{name: 'Syrian Arab Republic', code: 'SY'},
{name: 'Taiwan, Province of China', code: 'TW'},
{name: 'Tajikistan', code: 'TJ'},
{name: 'Tanzania, United Republic of', code: 'TZ'},
{name: 'Thailand', code: 'TH'},
{name: 'Timor-Leste', code: 'TL'},
{name: 'Togo', code: 'TG'},
{name: 'Tokelau', code: 'TK'},
{name: 'Tonga', code: 'TO'},
{name: 'Trinidad and Tobago', code: 'TT'},
{name: 'Tunisia', code: 'TN'},
{name: 'Turkey', code: 'TR'},
{name: 'Turkmenistan', code: 'TM'},
{name: 'Turks and Caicos Islands', code: 'TC'},
{name: 'Tuvalu', code: 'TV'},
{name: 'Uganda', code: 'UG'},
{name: 'Ukraine', code: 'UA'},
{name: 'United Arab Emirates', code: 'AE'},
{name: 'United Kingdom', code: 'GB'},
{name: 'United States', code: 'US'},
{name: 'United States Minor Outlying Islands', code: 'UM'},
{name: 'Uruguay', code: 'UY'},
{name: 'Uzbekistan', code: 'UZ'},
{name: 'Vanuatu', code: 'VU'},
{name: 'Venezuela', code: 'VE'},
{name: 'Viet Nam', code: 'VN'},
{name: 'Virgin Islands, British', code: 'VG'},
{name: 'Virgin Islands, U.S.', code: 'VI'},
{name: 'Wallis and Futuna', code: 'WF'},
{name: 'Western Sahara', code: 'EH'},
{name: 'Yemen', code: 'YE'},
{name: 'Zambia', code: 'ZM'},
{name: 'Zimbabwe', code: 'ZW'}
]
});
</script>
</polymer-element>
<dropdown-demo fit></dropdown-demo>
</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>

core-dropdown-menu

owner: @morethanreal

See the component page for more information.

{
"name": "core-dropdown",
"private": false,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-icon": "Polymer/core-icon#^0.4.0",
"core-icon-button": "Polymer/core-icon-button#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-overlay": "Polymer/core-overlay#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-dropdown",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "d88054ba68d73ee4c6a62c67a43ce74b87982eb6"
},
"_source": "git://github.com/Polymer/core-dropdown.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-dropdown"
}
{
"name": "core-dropdown",
"private": false,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-icon": "Polymer/core-icon#^0.4.0",
"core-icon-button": "Polymer/core-icon-button#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-overlay": "Polymer/core-overlay#^0.4.0"
}
}
<!--
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="../polymer/polymer.html">
<link rel="import" href="../core-overlay/core-overlay.html">
<!--
`core-dropdown-overlay` is a helper class to position an overlay relative to another
element within the same offsetParent.
@group Polymer Core Elements
@element core-dropdown-overlay
@extends core-overlay
@homepage github.io
-->
<polymer-element name="core-dropdown-overlay" extends="core-overlay">
<script>
Polymer({
publish: {
/**
* The `relatedTarget` is an element used to position the overlay. It should have
* the same offsetParent as the target.
*
* @attribute relatedTarget
* @type Node
*/
relatedTarget: null,
/**
* The horizontal alignment of the overlay relative to the `relatedTarget`.
* `left` means the left edges are aligned together and `right` means the right
* edges are aligned together.
*
* @attribute halign
* @type 'left' | 'right'
* @default 'auto'
*/
halign: 'left',
/**
* The vertical alignment of the overlay relative to the `relatedTarget`. `top`
* means the top edges are aligned together and `bottom` means the bottom edges
* are aligned together.
*
* @attribute valign
* @type 'top' | 'bottom'
* @default 'top'
*/
valign: 'top'
},
measure: function() {
var target = this.target;
// remember position, because core-overlay may have set the property
var pos = target.style.position;
// get the size of the target as if it's positioned in the top left
// corner of the screen
target.style.position = 'fixed';
target.style.left = '0px';
target.style.top = '0px';
var rect = target.getBoundingClientRect();
target.style.position = pos;
target.style.left = null;
target.style.top = null;
return rect;
},
resetTargetDimensions: function() {
var dims = this.dimensions;
var style = this.target.style;
if (dims.position.h_by === this.localName) {
style[dims.position.h] = null;
}
if (dims.position.v_by === this.localName) {
style[dims.position.v] = null;
}
this.super();
},
positionTarget: function() {
if (!this.relatedTarget) {
this.super();
return;
}
var target = this.target;
var related = this.relatedTarget;
// explicitly set width/height, because we don't want it constrained
// to the offsetParent
var rect = this.measure();
target.style.width = rect.width + 'px';
target.style.height = rect.height + 'px';
var t_op = target.offsetParent;
var r_op = related.offsetParent;
if (window.ShadowDOMPolyfill) {
t_op = wrap(t_op);
r_op = wrap(r_op);
}
if (t_op !== r_op && t_op !== related) {
console.warn('core-dropdown-overlay: dropdown\'s offsetParent must be the relatedTarget or the relatedTarget\'s offsetParent!');
}
// Don't use CSS to handle halign/valign so we can use
// dimensions.position to detect custom positioning
var dims = this.dimensions;
var margin = dims.margin;
var inside = t_op === related;
if (!dims.position.h) {
if (this.halign === 'right') {
target.style.right = ((inside ? 0 : t_op.offsetWidth - related.offsetLeft - related.offsetWidth) - margin.right) + 'px';
dims.position.h = 'right';
} else {
target.style.left = ((inside ? 0 : related.offsetLeft) - margin.left) + 'px';
dims.position.h = 'left';
}
dims.position.h_by = this.localName;
}
if (!dims.position.v) {
if (this.valign === 'bottom') {
target.style.bottom = ((inside ? 0 : t_op.offsetHeight - related.offsetTop - related.offsetHeight) - margin.bottom) + 'px';
dims.position.v = 'bottom';
} else {
target.style.top = ((inside ? 0 : related.offsetTop) - margin.top) + 'px';
dims.position.v = 'top';
}
dims.position.v_by = this.localName;
}
}
});
</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 {
position: absolute;
overflow: auto;
background-color: #fff;
}
<!--
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
-->
<!--
`core-dropdown` is an element that is initially hidden and is positioned relatively to another
element, usually the element that triggers the dropdown. The dropdown and the triggering element
should be children of the same offsetParent, e.g. the same `<div>` with `position: relative`.
It can be used to implement dropdown menus, menu buttons, etc..
Example:
<template is="auto-binding">
<div relative>
<core-icon-button id="trigger" icon="menu"></core-icon-button>
<core-dropdown relatedTarget="{{$.trigger}}">
<core-menu>
<core-item>Cut</core-item>
<core-item>Copy</core-item>
<core-item>Paste</core-item>
</core-menu>
</core-dropdown>
</div>
</template>
Positioning
-----------
By default, the dropdown is absolutely positioned on top of the `relatedTarget` with the top and
left edges aligned. The `halign` and `valign` properties controls the various alignments. The size
of the dropdown is automatically restrained such that it is entirely visible on the screen. Use the
`margin`
If you need more control over the dropdown's position, use CSS. The `halign` and `valign` properties are
ignored if the dropdown is positioned with CSS.
Example:
<style>
/* manually position the dropdown below the trigger */
core-dropdown {
position: absolute;
top: 38px;
left: 0;
}
</style>
<template is="auto-binding">
<div relative>
<core-icon-button id="trigger" icon="menu"></core-icon-button>
<core-dropdown relatedTarget="{{$.trigger}}">
<core-menu>
<core-item>Cut</core-item>
<core-item>Copy</core-item>
<core-item>Paste</core-item>
</core-menu>
</core-dropdown>
</div>
</template>
@group Polymer Core Elements
@element core-dropdown
@homepage github.io
-->
<link href="../polymer/polymer.html" rel="import">
<link href="core-dropdown-overlay.html" rel="import">
<polymer-element name="core-dropdown">
<template>
<link href="core-dropdown.css" rel="stylesheet">
<core-dropdown-overlay id="overlay" target="{{}}" relatedTarget="{{relatedTarget}}" opened="{{opened}}" halign="{{halign}}" valign="{{valign}}" margin="{{margin}}" transition="{{transition}}" autoFocusDisabled="{{autoFocusDisabled}}"></core-dropdown-overlay>
<content></content>
</template>
<script>
Polymer({
publish: {
/**
* The element associated with this dropdown, usually the element that triggers
* the menu.
*
* @attribute relatedTarget
* @type Node
*/
relatedTarget: null,
/**
* If true, the menu is currently visible.
*
* @attribute opened
* @type boolean
* @default false
*/
opened: false,
/**
* The horizontal alignment of the popup relative to `relatedTarget`. `left`
* means the left edges are aligned together. `right` means the right edges
* are aligned together.
*
* @attribute halign
* @type 'left' | 'right'
* @default 'left'
*/
halign: 'left',
/**
* The vertical alignment of the popup relative to `relatedTarget`. `top` means
* the top edges are aligned together. `bottom` means the bottom edges are
* aligned together.
*
* @attribute valign
* @type 'top' | 'bottom'
* @default 'top'
*/
valign: 'top',
/**
* By default an overlay will focus its target or an element inside
* it with the `autoFocus` attribute. Disable this
* behavior by setting the `autoFocusDisabled` property to true.
*
* @attribute autoFocusDisabled
* @type boolean
* @default false
*/
autoFocusDisabled: false,
/**
* The transition property specifies a string which identifies a
* <a href="../core-transition/">`core-transition`</a> element that
* will be used to help the overlay open and close. The default
* `core-transition-fade` will cause the overlay to fade in and out.
*
* @attribute transition
* @type string
* @default null
*/
transition: null
}
});
</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
-->
<!--
Issues:
* what to do on window resize?
* reposition
* what to do when window scrolls?
* tbd
* positioning
* convenience - halign, valign
* possible to use custom CSS
Approaches:
* uses default core-overlay behavior
* possible to be always on top
* doesn't scroll with
* core-dropdown is independent of the triggering element
* uses position: absolute
* scrolls with
* might not be always on top
* core-dropdown needs to know about both the triggering element and the dropdown
* core-dropdown contains both the triggering element and the dropdown, uses distribution
* how do I position the dropdown?
* if the dropdown is the distributed node, it's hard to style the dropdown from the outside because of specificity
* if the dropdown is the container of the distributed node, it's hard to style the dropdown from the outside
because of shadow dom - maybe ok?
Related elements:
core-dropdown - a control that triggers a dropdown
core-dropdown-menu - a control that triggers a dropdown menu, similar to select
core-menu-button - a icon button that triggers a dropdown menu
-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>core-dropdown</title>
<script src="../platform/platform.js"></script>
<link href="../core-icon/core-icon.html" rel="import">
<link href="../core-icons/core-icons.html" rel="import">
<link href="../core-icons/social-icons.html" rel="import">
<link href="../core-icon-button/core-icon-button.html" rel="import">
<link href="core-dropdown.html" rel="import">
<style shim-shadowdom>
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 16px;
}
html, body {
height: 100%;
margin: 0;
}
html /deep/ core-dropdown {
background-color: #eee;
color: #000;
border: 1px solid #ccc;
border-radius: 3px;
}
drop-down.margin::shadow core-dropdown {
margin: 12px;
}
drop-down.open-below::shadow core-dropdown {
position: absolute;
top: 38px;
left: 0px;
}
drop-down.constrained::shadow core-dropdown {
max-height: 500px;
}
.dropdown {
padding: 12px;
}
.toolbar {
color: #fff;
font-size: 16px;
}
.toolbar-1 {
background-color: #3b78e7;
}
.toolbar-2 {
background-color: #4285f4;
}
.toolbar-3 {
background-color: #5e97f6;
}
.bottom-toolbar-1 {
background-color: #0d904f;
}
.bottom-toolbar-2 {
background-color: #0f9d58;
}
.bottom-toolbar-3 {
background-color: #33ac71;
}
.toolbar > * {
padding: 12px;
}
.toolbar-label {
width: 100px;
}
.middle {
overflow: auto;
}
.middle > * {
padding: 12px;
}
</style>
</head>
<body>
<polymer-element name="drop-down" attributes="opened halign valign">
<template>
<style>
:host {
display: inline-block;
position: relative;
}
</style>
<div id="trigger" on-tap="{{toggle}}">
<content select=".core-dropdown-trigger"></content>
</div>
<core-dropdown relatedTarget="{{$.trigger}}" halign="{{halign}}" valign="{{valign}}" opened="{{opened}}" margin="12">
<content></content>
</core-dropdown>
</template>
<script>
Polymer({
toggle: function() {
this.opened = !this.opened;
}
});
</script>
</polymer-element>
<polymer-element name="drop-down-2" attributes="opened halign valign">
<template>
<style>
:host {
display: inline-block;
}
#trigger {
position: relative;
}
</style>
<div id="trigger" on-tap="{{toggle}}">
<content select=".core-dropdown-trigger"></content>
<core-dropdown relatedTarget="{{$.trigger}}" halign="{{halign}}" valign="{{valign}}" opened="{{opened}}" margin="12">
<content></content>
</core-dropdown>
</div>
</template>
<script>
Polymer({
toggle: function() {
this.opened = !this.opened;
}
});
</script>
</polymer-element>
<template is="auto-binding">
<div layout vertical fit>
<div class="toolbar toolbar-1" layout horizontal center>
<div class="toolbar-label">
halign=left valign=top
</div>
<drop-down halign="left">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>Hello World!</h2>
</div>
</drop-down>
<drop-down-2 halign="left">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>I'm a child of the button</h2>
</div>
</drop-down-2>
<drop-down halign="left">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>scrollable-vertical</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<drop-down class="margin" halign="left">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>margins</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<div flex>
</div>
</div>
<div class="toolbar toolbar-2" layout horizontal center>
<div class="toolbar-label">
halign=right valign=top
</div>
<div flex></div>
<drop-down class="margin" halign="right">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>margin</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<drop-down halign="right">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>scrollable-vertical</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<drop-down-2 halign="right">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>I'm a child of the button</h2>
</div>
</drop-down-2>
<drop-down halign="right">
<core-icon-button class="core-dropdown-trigger" icon="more-vert"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>Hello World!</h2>
</div>
</drop-down>
</div>
<div flex class="middle">
<div>
<drop-down>
<core-icon-button class="core-dropdown-trigger" icon="social:notifications"></core-icon-button>
<div class="dropdown">
<h2>Hello World!</h2>
</div>
</drop-down>
<drop-down class="open-below">
<core-icon-button class="core-dropdown-trigger" icon="social:notifications"></core-icon-button>
<div class="dropdown">
<h2>Custom positioning</h2>
</div>
</drop-down>
<drop-down class="open-below constrained">
<core-icon-button class="core-dropdown-trigger" icon="social:notifications"></core-icon-button>
<div class="dropdown">
<h2>Scrollable + custom size + custom positioning</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
</div>
<p>scroll me...</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, 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. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div class="toolbar bottom-toolbar-2" layout horizontal center>
<div class="toolbar-label">
halign=left valign=bottom
</div>
<drop-down halign="left" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>Hello World!</h2>
</div>
</drop-down>
<drop-down-2 halign="left" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>I'm a child of the button</h2>
</div>
</drop-down-2>
<drop-down halign="left" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>scrollable-vertical</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<drop-down class="margin" halign="left" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>margin</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<div flex>
</div>
</div>
<div class="toolbar bottom-toolbar-1" layout horizontal center>
<div class="toolbar-label">
halign=right valign=bottom
</div>
<div flex></div>
<drop-down class="margin" halign="right" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>margin</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<drop-down halign="right" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown">
<h2>scrollable-vertical</h2>
<template repeat="{{countries}}">
<p>{{name}}</p>
</template>
</div>
</drop-down>
<drop-down-2 halign="right" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="menu"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>I'm a child of the button</h2>
</div>
</drop-down-2>
<drop-down halign="right" valign="bottom">
<core-icon-button class="core-dropdown-trigger" icon="more-vert"></core-icon-button>
<div class="dropdown" layout horizontal center-center>
<h2>Hello World!</h2>
</div>
</drop-down>
</div>
</div>
</template>
<script>
scope = document.querySelector('template[is=auto-binding]');
scope.countries = [
{name: 'Afghanistan', code: 'AF'},
{name: 'Åland Islands', code: 'AX'},
{name: 'Albania', code: 'AL'},
{name: 'Algeria', code: 'DZ'},
{name: 'American Samoa', code: 'AS'},
{name: 'Andorra', code: 'AD'},
{name: 'Angola', code: 'AO'},
{name: 'Anguilla', code: 'AI'},
{name: 'Antarctica', code: 'AQ'},
{name: 'Antigua and Barbuda', code: 'AG'},
{name: 'Argentina', code: 'AR'},
{name: 'Armenia', code: 'AM'},
{name: 'Aruba', code: 'AW'},
{name: 'Australia', code: 'AU'},
{name: 'Austria', code: 'AT'},
{name: 'Azerbaijan', code: 'AZ'},
{name: 'Bahamas', code: 'BS'},
{name: 'Bahrain', code: 'BH'},
{name: 'Bangladesh', code: 'BD'},
{name: 'Barbados', code: 'BB'},
{name: 'Belarus', code: 'BY'},
{name: 'Belgium', code: 'BE'},
{name: 'Belize', code: 'BZ'},
{name: 'Benin', code: 'BJ'},
{name: 'Bermuda', code: 'BM'},
{name: 'Bhutan', code: 'BT'},
{name: 'Bolivia', code: 'BO'},
{name: 'Bosnia and Herzegovina', code: 'BA'},
{name: 'Botswana', code: 'BW'},
{name: 'Bouvet Island', code: 'BV'},
{name: 'Brazil', code: 'BR'},
{name: 'British Indian Ocean Territory', code: 'IO'},
{name: 'Brunei Darussalam', code: 'BN'},
{name: 'Bulgaria', code: 'BG'},
{name: 'Burkina Faso', code: 'BF'},
{name: 'Burundi', code: 'BI'},
{name: 'Cambodia', code: 'KH'},
{name: 'Cameroon', code: 'CM'},
{name: 'Canada', code: 'CA'},
{name: 'Cape Verde', code: 'CV'},
{name: 'Cayman Islands', code: 'KY'},
{name: 'Central African Republic', code: 'CF'},
{name: 'Chad', code: 'TD'},
{name: 'Chile', code: 'CL'},
{name: 'China', code: 'CN'},
{name: 'Christmas Island', code: 'CX'},
{name: 'Cocos (Keeling) Islands', code: 'CC'},
{name: 'Colombia', code: 'CO'},
{name: 'Comoros', code: 'KM'},
{name: 'Congo', code: 'CG'},
{name: 'Congo, The Democratic Republic of the', code: 'CD'},
{name: 'Cook Islands', code: 'CK'},
{name: 'Costa Rica', code: 'CR'},
{name: 'Cote D\'Ivoire', code: 'CI'},
{name: 'Croatia', code: 'HR'},
{name: 'Cuba', code: 'CU'},
{name: 'Cyprus', code: 'CY'},
{name: 'Czech Republic', code: 'CZ'},
{name: 'Denmark', code: 'DK'},
{name: 'Djibouti', code: 'DJ'},
{name: 'Dominica', code: 'DM'},
{name: 'Dominican Republic', code: 'DO'},
{name: 'Ecuador', code: 'EC'},
{name: 'Egypt', code: 'EG'},
{name: 'El Salvador', code: 'SV'},
{name: 'Equatorial Guinea', code: 'GQ'},
{name: 'Eritrea', code: 'ER'},
{name: 'Estonia', code: 'EE'},
{name: 'Ethiopia', code: 'ET'},
{name: 'Falkland Islands (Malvinas)', code: 'FK'},
{name: 'Faroe Islands', code: 'FO'},
{name: 'Fiji', code: 'FJ'},
{name: 'Finland', code: 'FI'},
{name: 'France', code: 'FR'},
{name: 'French Guiana', code: 'GF'},
{name: 'French Polynesia', code: 'PF'},
{name: 'French Southern Territories', code: 'TF'},
{name: 'Gabon', code: 'GA'},
{name: 'Gambia', code: 'GM'},
{name: 'Georgia', code: 'GE'},
{name: 'Germany', code: 'DE'},
{name: 'Ghana', code: 'GH'},
{name: 'Gibraltar', code: 'GI'},
{name: 'Greece', code: 'GR'},
{name: 'Greenland', code: 'GL'},
{name: 'Grenada', code: 'GD'},
{name: 'Guadeloupe', code: 'GP'},
{name: 'Guam', code: 'GU'},
{name: 'Guatemala', code: 'GT'},
{name: 'Guernsey', code: 'GG'},
{name: 'Guinea', code: 'GN'},
{name: 'Guinea-Bissau', code: 'GW'},
{name: 'Guyana', code: 'GY'},
{name: 'Haiti', code: 'HT'},
{name: 'Heard Island and Mcdonald Islands', code: 'HM'},
{name: 'Holy See (Vatican City State)', code: 'VA'},
{name: 'Honduras', code: 'HN'},
{name: 'Hong Kong', code: 'HK'},
{name: 'Hungary', code: 'HU'},
{name: 'Iceland', code: 'IS'},
{name: 'India', code: 'IN'},
{name: 'Indonesia', code: 'ID'},
{name: 'Iran, Islamic Republic Of', code: 'IR'},
{name: 'Iraq', code: 'IQ'},
{name: 'Ireland', code: 'IE'},
{name: 'Isle of Man', code: 'IM'},
{name: 'Israel', code: 'IL'},
{name: 'Italy', code: 'IT'},
{name: 'Jamaica', code: 'JM'},
{name: 'Japan', code: 'JP'},
{name: 'Jersey', code: 'JE'},
{name: 'Jordan', code: 'JO'},
{name: 'Kazakhstan', code: 'KZ'},
{name: 'Kenya', code: 'KE'},
{name: 'Kiribati', code: 'KI'},
{name: 'Korea, Democratic People\'S Republic of', code: 'KP'},
{name: 'Korea, Republic of', code: 'KR'},
{name: 'Kuwait', code: 'KW'},
{name: 'Kyrgyzstan', code: 'KG'},
{name: 'Lao People\'S Democratic Republic', code: 'LA'},
{name: 'Latvia', code: 'LV'},
{name: 'Lebanon', code: 'LB'},
{name: 'Lesotho', code: 'LS'},
{name: 'Liberia', code: 'LR'},
{name: 'Libyan Arab Jamahiriya', code: 'LY'},
{name: 'Liechtenstein', code: 'LI'},
{name: 'Lithuania', code: 'LT'},
{name: 'Luxembourg', code: 'LU'},
{name: 'Macao', code: 'MO'},
{name: 'Macedonia, The Former Yugoslav Republic of', code: 'MK'},
{name: 'Madagascar', code: 'MG'},
{name: 'Malawi', code: 'MW'},
{name: 'Malaysia', code: 'MY'},
{name: 'Maldives', code: 'MV'},
{name: 'Mali', code: 'ML'},
{name: 'Malta', code: 'MT'},
{name: 'Marshall Islands', code: 'MH'},
{name: 'Martinique', code: 'MQ'},
{name: 'Mauritania', code: 'MR'},
{name: 'Mauritius', code: 'MU'},
{name: 'Mayotte', code: 'YT'},
{name: 'Mexico', code: 'MX'},
{name: 'Micronesia, Federated States of', code: 'FM'},
{name: 'Moldova, Republic of', code: 'MD'},
{name: 'Monaco', code: 'MC'},
{name: 'Mongolia', code: 'MN'},
{name: 'Montserrat', code: 'MS'},
{name: 'Morocco', code: 'MA'},
{name: 'Mozambique', code: 'MZ'},
{name: 'Myanmar', code: 'MM'},
{name: 'Namibia', code: 'NA'},
{name: 'Nauru', code: 'NR'},
{name: 'Nepal', code: 'NP'},
{name: 'Netherlands', code: 'NL'},
{name: 'Netherlands Antilles', code: 'AN'},
{name: 'New Caledonia', code: 'NC'},
{name: 'New Zealand', code: 'NZ'},
{name: 'Nicaragua', code: 'NI'},
{name: 'Niger', code: 'NE'},
{name: 'Nigeria', code: 'NG'},
{name: 'Niue', code: 'NU'},
{name: 'Norfolk Island', code: 'NF'},
{name: 'Northern Mariana Islands', code: 'MP'},
{name: 'Norway', code: 'NO'},
{name: 'Oman', code: 'OM'},
{name: 'Pakistan', code: 'PK'},
{name: 'Palau', code: 'PW'},
{name: 'Palestinian Territory, Occupied', code: 'PS'},
{name: 'Panama', code: 'PA'},
{name: 'Papua New Guinea', code: 'PG'},
{name: 'Paraguay', code: 'PY'},
{name: 'Peru', code: 'PE'},
{name: 'Philippines', code: 'PH'},
{name: 'Pitcairn', code: 'PN'},
{name: 'Poland', code: 'PL'},
{name: 'Portugal', code: 'PT'},
{name: 'Puerto Rico', code: 'PR'},
{name: 'Qatar', code: 'QA'},
{name: 'Reunion', code: 'RE'},
{name: 'Romania', code: 'RO'},
{name: 'Russian Federation', code: 'RU'},
{name: 'RWANDA', code: 'RW'},
{name: 'Saint Helena', code: 'SH'},
{name: 'Saint Kitts and Nevis', code: 'KN'},
{name: 'Saint Lucia', code: 'LC'},
{name: 'Saint Pierre and Miquelon', code: 'PM'},
{name: 'Saint Vincent and the Grenadines', code: 'VC'},
{name: 'Samoa', code: 'WS'},
{name: 'San Marino', code: 'SM'},
{name: 'Sao Tome and Principe', code: 'ST'},
{name: 'Saudi Arabia', code: 'SA'},
{name: 'Senegal', code: 'SN'},
{name: 'Serbia and Montenegro', code: 'CS'},
{name: 'Seychelles', code: 'SC'},
{name: 'Sierra Leone', code: 'SL'},
{name: 'Singapore', code: 'SG'},
{name: 'Slovakia', code: 'SK'},
{name: 'Slovenia', code: 'SI'},
{name: 'Solomon Islands', code: 'SB'},
{name: 'Somalia', code: 'SO'},
{name: 'South Africa', code: 'ZA'},
{name: 'South Georgia and the South Sandwich Islands', code: 'GS'},
{name: 'Spain', code: 'ES'},
{name: 'Sri Lanka', code: 'LK'},
{name: 'Sudan', code: 'SD'},
{name: 'Suriname', code: 'SR'},
{name: 'Svalbard and Jan Mayen', code: 'SJ'},
{name: 'Swaziland', code: 'SZ'},
{name: 'Sweden', code: 'SE'},
{name: 'Switzerland', code: 'CH'},
{name: 'Syrian Arab Republic', code: 'SY'},
{name: 'Taiwan, Province of China', code: 'TW'},
{name: 'Tajikistan', code: 'TJ'},
{name: 'Tanzania, United Republic of', code: 'TZ'},
{name: 'Thailand', code: 'TH'},
{name: 'Timor-Leste', code: 'TL'},
{name: 'Togo', code: 'TG'},
{name: 'Tokelau', code: 'TK'},
{name: 'Tonga', code: 'TO'},
{name: 'Trinidad and Tobago', code: 'TT'},
{name: 'Tunisia', code: 'TN'},
{name: 'Turkey', code: 'TR'},
{name: 'Turkmenistan', code: 'TM'},
{name: 'Turks and Caicos Islands', code: 'TC'},
{name: 'Tuvalu', code: 'TV'},
{name: 'Uganda', code: 'UG'},
{name: 'Ukraine', code: 'UA'},
{name: 'United Arab Emirates', code: 'AE'},
{name: 'United Kingdom', code: 'GB'},
{name: 'United States', code: 'US'},
{name: 'United States Minor Outlying Islands', code: 'UM'},
{name: 'Uruguay', code: 'UY'},
{name: 'Uzbekistan', code: 'UZ'},
{name: 'Vanuatu', code: 'VU'},
{name: 'Venezuela', code: 'VE'},
{name: 'Viet Nam', code: 'VN'},
{name: 'Virgin Islands, British', code: 'VG'},
{name: 'Virgin Islands, U.S.', code: 'VI'},
{name: 'Wallis and Futuna', code: 'WF'},
{name: 'Western Sahara', code: 'EH'},
{name: 'Yemen', code: 'YE'},
{name: 'Zambia', code: 'ZM'},
{name: 'Zimbabwe', code: 'ZW'}
];
scope.pastries = [
'Apple fritter',
'Croissant',
'Donut',
'Financier',
'Jello',
'Madeleine',
'Pound cake',
'Pretzel',
'Sfogliatelle'
];
</script>
</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='["core-dropdown.html","core-dropdown-overlay.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="core-menu" label="Menu" group="Core" isContainer>
<template>
<core-menu selected="0" style="font-size: 16px;">
<core-submenu icon="settings" label="Topics">
<core-item label="Topic 1"></core-item>
<core-item label="Topic 2"></core-item>
</core-submenu>
<core-submenu icon="settings" label="Favorites">
<core-item label="Favorite 1"></core-item>
<core-item label="Favorite 2"></core-item>
<core-item label="Favorite 3"></core-item>
</core-submenu>
</core-menu>
</template>
<template id="imports">
<link rel="import" href="core-submenu.html">
</template>
</x-meta>
<x-meta id="core-submenu" label="Sub Menu" group="Core" isContainer>
<template>
<core-submenu icon="settings" label="Topics">
<core-item label="Topic 1"></core-item>
<core-item label="Topic 2"></core-item>
</core-submenu>
</template>
<template id="imports">
<link rel="import" href="core-submenu.html">
</template>
</x-meta>
{
"name": "core-elements",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-ajax": "Polymer/core-ajax#^0.4.0",
"core-animated-pages": "Polymer/core-animated-pages#^0.4.0",
"core-animation": "Polymer/core-animation#^0.4.0",
"core-collapse": "Polymer/core-collapse#^0.4.0",
"core-doc-viewer": "Polymer/core-doc-viewer#^0.4.0",
"core-docs": "Polymer/core-docs#^0.4.0",
"core-drag-drop": "Polymer/core-drag-drop#^0.4.0",
"core-drawer-panel": "Polymer/core-drawer-panel#^0.4.0",
"core-dropdown": "Polymer/core-dropdown#^0.4.0",
"core-dropdown-menu": "Polymer/core-dropdown-menu#^0.4.0",
"core-field": "Polymer/core-field#^0.4.0",
"core-header-panel": "Polymer/core-header-panel#^0.4.0",
"core-icon-button": "Polymer/core-icon-button#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-input": "Polymer/core-input#^0.4.0",
"core-item": "Polymer/core-item#^0.4.0",
"core-layout-grid": "Polymer/core-layout-grid#^0.4.0",
"core-layout-trbl": "Polymer/core-layout-trbl#^0.4.0",
"core-list": "Polymer/core-list#^0.4.0",
"core-localstorage": "Polymer/core-localstorage#^0.4.0",
"core-media-query": "Polymer/core-media-query#^0.4.0",
"core-menu": "Polymer/core-menu#^0.4.0",
"core-menu-button": "Polymer/core-menu-button#^0.4.0",
"core-meta": "Polymer/core-meta#^0.4.0",
"core-overlay": "Polymer/core-overlay#^0.4.0",
"core-pages": "Polymer/core-pages#^0.4.0",
"core-range": "Polymer/core-range#^0.4.0",
"core-scaffold": "Polymer/core-scaffold#^0.4.0",
"core-scroll-header-panel": "Polymer/core-scroll-header-panel#^0.4.0",
"core-selection": "Polymer/core-selection#^0.4.0",
"core-selector": "Polymer/core-selector#^0.4.0",
"core-shared-lib": "Polymer/core-shared-lib#^0.4.0",
"core-signals": "Polymer/core-signals#^0.4.0",
"core-splitter": "Polymer/core-splitter#^0.4.0",
"core-style": "Polymer/core-style#^0.4.0",
"core-tests": "Polymer/core-tests#^0.4.0",
"core-toolbar": "Polymer/core-toolbar#^0.4.0",
"core-tooltip": "Polymer/core-tooltip#^0.4.0",
"core-transition": "Polymer/core-transition#^0.4.0",
"sampler-scaffold": "Polymer/sampler-scaffold#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-elements",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "0f887b10bf958bd35d637aed1ce0c4fcd7467413"
},
"_source": "git://github.com/Polymer/core-elements.git",
"_target": "~0.4.2",
"_originalSource": "Polymer/core-elements",
"_direct": true
}
{
"name": "core-elements",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0",
"core-ajax": "Polymer/core-ajax#^0.4.0",
"core-animated-pages": "Polymer/core-animated-pages#^0.4.0",
"core-animation": "Polymer/core-animation#^0.4.0",
"core-collapse": "Polymer/core-collapse#^0.4.0",
"core-doc-viewer": "Polymer/core-doc-viewer#^0.4.0",
"core-docs": "Polymer/core-docs#^0.4.0",
"core-drag-drop": "Polymer/core-drag-drop#^0.4.0",
"core-drawer-panel": "Polymer/core-drawer-panel#^0.4.0",
"core-dropdown": "Polymer/core-dropdown#^0.4.0",
"core-dropdown-menu": "Polymer/core-dropdown-menu#^0.4.0",
"core-field": "Polymer/core-field#^0.4.0",
"core-header-panel": "Polymer/core-header-panel#^0.4.0",
"core-icon-button": "Polymer/core-icon-button#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0",
"core-input": "Polymer/core-input#^0.4.0",
"core-item": "Polymer/core-item#^0.4.0",
"core-layout-grid": "Polymer/core-layout-grid#^0.4.0",
"core-layout-trbl": "Polymer/core-layout-trbl#^0.4.0",
"core-list": "Polymer/core-list#^0.4.0",
"core-localstorage": "Polymer/core-localstorage#^0.4.0",
"core-media-query": "Polymer/core-media-query#^0.4.0",
"core-menu": "Polymer/core-menu#^0.4.0",
"core-menu-button": "Polymer/core-menu-button#^0.4.0",
"core-meta": "Polymer/core-meta#^0.4.0",
"core-overlay": "Polymer/core-overlay#^0.4.0",
"core-pages": "Polymer/core-pages#^0.4.0",
"core-range": "Polymer/core-range#^0.4.0",
"core-scaffold": "Polymer/core-scaffold#^0.4.0",
"core-scroll-header-panel": "Polymer/core-scroll-header-panel#^0.4.0",
"core-selection": "Polymer/core-selection#^0.4.0",
"core-selector": "Polymer/core-selector#^0.4.0",
"core-shared-lib": "Polymer/core-shared-lib#^0.4.0",
"core-signals": "Polymer/core-signals#^0.4.0",
"core-splitter": "Polymer/core-splitter#^0.4.0",
"core-style": "Polymer/core-style#^0.4.0",
"core-tests": "Polymer/core-tests#^0.4.0",
"core-toolbar": "Polymer/core-toolbar#^0.4.0",
"core-tooltip": "Polymer/core-tooltip#^0.4.0",
"core-transition": "Polymer/core-transition#^0.4.0",
"sampler-scaffold": "Polymer/sampler-scaffold#^0.4.0"
}
}
<!--
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
-->
<!--
The `core-elements` component aggregates numerous `core-*` components
into one package (by depending on them).
See `bower.json` for the complete list of components.
@element core-elements
@group Polymer Core Elements
@homepage github.io
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../core-ajax/core-ajax.html">
<link rel="import" href="../core-animated-pages/core-animated-pages.html">
<link rel="import" href="../core-collapse/core-collapse.html">
<link rel="import" href="../core-doc-viewer/core-doc-viewer.html">
<link rel="import" href="../core-drag-drop/core-drag-drop.html">
<link rel="import" href="../core-drawer-panel/core-drawer-panel.html">
<link rel="import" href="../core-dropdown/core-dropdown.html">
<link rel="import" href="../core-dropdown-menu/core-dropdown-menu.html">
<link rel="import" href="../core-field/core-field.html">
<link rel="import" href="../core-header-panel/core-header-panel.html">
<link rel="import" href="../core-icon-button/core-icon-button.html">
<link rel="import" href="../core-icons/core-icons.html">
<link rel="import" href="../core-input/core-input.html">
<link rel="import" href="../core-item/core-item.html">
<link rel="import" href="../core-layout-grid/core-layout-grid.html">
<link rel="import" href="../core-layout-trbl/core-layout-trbl.html">
<link rel="import" href="../core-list/core-list.html">
<link rel="import" href="../core-localstorage/core-localstorage.html">
<link rel="import" href="../core-media-query/core-media-query.html">
<link rel="import" href="../core-menu/core-menu.html">
<link rel="import" href="../core-menu/core-submenu.html">
<link rel="import" href="../core-menu-button/core-menu-button.html">
<link rel="import" href="../core-meta/core-meta.html">
<link rel="import" href="../core-overlay/core-overlay.html">
<link rel="import" href="../core-pages/core-pages.html">
<link rel="import" href="../core-range/core-range.html">
<link rel="import" href="../core-scaffold/core-scaffold.html">
<link rel="import" href="../core-scroll-header-panel/core-scroll-header-panel.html">
<link rel="import" href="../core-selection/core-selection.html">
<link rel="import" href="../core-selector/core-selector.html">
<link rel="import" href="../core-shared-lib/core-shared-lib.html">
<link rel="import" href="../core-signals/core-signals.html">
<link rel="import" href="../core-splitter/core-splitter.html">
<link rel="import" href="../core-style/core-style.html">
<link rel="import" href="../core-toolbar/core-toolbar.html">
<link rel="import" href="../core-tooltip/core-tooltip.html">
<link rel="import" href="../core-transition/core-transition.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>
<title>Core Elements Sampler</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="../sampler-scaffold/sampler-scaffold.html">
<link rel="import" href="../core-item/core-item.html">
<link rel="import" href="../core-menu/core-submenu.html">
<style>
body {
font-family: sans-serif;
color: #333;
margin: 0;
-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;
}
</style>
</head>
<body unresolved>
<sampler-scaffold label="Core Elements">
<core-item label="Animation" tag="core-animation" url="../core-animation/demo.html"></core-item>
<core-item label="Collapse" tag="core-collapse" url="../core-collapse/demo.html"></core-item>
<core-item label="Drag and Drop" tag="core-drag-drop" url="../core-drag-drop/demo.html"></core-item>
<core-item label="Drawer Panel" tag="core-drawer-panel" url="../core-drawer-panel/demo.html"></core-item>
<core-item label="Dropdown" tag="core-dropdown" url="../core-dropdown/demo.html"></core-item>
<core-item label="Dropdown Menu" tag="core-dropdown-menu" url="../core-dropdown-menu/demo.html"></core-item>
<core-item label="Field" tag="core-field" url="../core-field/demo.html"></core-item>
<core-item label="Icon" tag="core-icon" url="../core-icon/demo.html"></core-item>
<core-item label="Icon Button" tag="core-icon-button" url="../core-icon-button/demo.html"></core-item>
<core-item label="Item" tag="core-item" url="../core-item/demo.html"></core-item>
<core-item label="Input" tag="core-input" url="../core-input/demo.html"></core-item>
<core-item label="List" tag="core-list" url="../core-list/demo.html"></core-item>
<core-item label="Menu" tag="core-menu" url="../core-menu/demo.html"></core-item>
<core-item label="Menu Button" tag="core-menu-button" url="../core-menu-button/demo.html"></core-item>
<core-item label="Overlay" tag="core-overlay" url="../core-overlay/demo.html"></core-item>
<core-item label="Pages" tag="core-pages" url="../core-pages/demo.html"></core-item>
<core-item label="Range" tag="core-range" url="../core-range/demo.html"></core-item>
<core-item label="Scaffold" tag="core-scaffold" url="../core-scaffold/demo.html"></core-item>
<core-item label="Scroll Header Panel" tag="core-scroll-header-panel" url="../core-scroll-header-panel/demo.html"></core-item>
<core-item label="Selector" tag="core-selector" url="../core-selector/demo.html"></core-item>
<core-item label="Splitter" tag="core-splitter" url="../core-splitter/demo.html"></core-item>
<core-item label="Style" tag="core-style" url="../core-style/demo.html"></core-item>
<core-item label="Toolbar" tag="core-toolbar" url="../core-toolbar/demo.html"></core-item>
<core-item label="Tooltip" tag="core-tooltip" url="../core-tooltip/demo.html"></core-item>
</sampler-scaffold>
<script>
// Analytics for pp.org
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-39334307-1', 'auto');
ga('send', 'pageview');
</script>
</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
-->
<!-- <link rel="import" href="../core-layout/metadata.html"> -->
<!-- <link rel="import" href="../core-layout-trbl/metadata.html"> -->
<!-- <link rel="import" href="../core-ajax/metadata.html"> -->
<link rel="import" href="../core-drawer-panel/metadata.html">
<link rel="import" href="../core-field/metadata.html">
<link rel="import" href="../core-header-panel/metadata.html">
<link rel="import" href="../core-icon/metadata.html">
<link rel="import" href="../core-icon-button/metadata.html">
<link rel="import" href="../core-input/metadata.html">
<link rel="import" href="../core-item/metadata.html">
<link rel="import" href="../core-menu/metadata.html">
<link rel="import" href="../core-menu-button/metadata.html">
<link rel="import" href="../core-pages/metadata.html">
<link rel="import" href="../core-scaffold/metadata.html">
<link rel="import" href="../core-selector/metadata.html">
<link rel="import" href="../core-animated-pages/metadata.html">
<link rel="import" href="../core-toolbar/metadata.html">
<link rel="import" href="../core-tooltip/metadata.html">
<link rel="import" href="../core-animated-pages/metadata.html">
<link rel="import" href="../core-scroll-header-panel/metadata.html">
<link rel="import" href="../core-ajax/metadata.html">
{
"name": "core-field",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-field",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "273b31ec5b3fcb5a52b731002220662c7f1278db"
},
"_source": "git://github.com/Polymer/core-field.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-field"
}
{
"name": "core-field",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
}
}
/* 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;
color: #333;
font-size: 14px;
}
polyfill-next-selector { content: ':host > core-icon'; }
::content > core-icon {
margin: 8px;
}
polyfill-next-selector { content: ':host input'; }
::content input {
background: transparent;
border: 0;
padding: 0;
margin: 0 4px;
color: #333;
font-size: 14px;
}
polyfill-next-selector { content: ':host input:focus'; }
::content input:focus {
outline: none;
}
polyfill-next-selector { content: ':host input::placeholder'; }
::content input::placeholder {
color: #b3b3b3;
}
<!--
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="../polymer/polymer.html">
<!--
The `core-field` supplies a horizontal layout, anticipating an input.
Example:
<core-field>
<core-icon icon="menu"></core-icon>
<label>I'm a label!</label>
<input placeholder="I have a label" flex>
</core-field>
@group Polymer Core Elements
@element core-field
@homepage github.io
-->
<polymer-element name="core-field" noscript center horizontal layout>
<template>
<link rel="stylesheet" href="core-field.css">
<content select="*"></content>
</template>
</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
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Core Field</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-field.html">
<style>
html {
font-family: 'Helvetica Neue', 'Roboto', 'Arial', sans-serif;
font-size: 14px;
}
core-field {
border: 1px solid #ddd;
margin: 10px;
height: 40px;
}
div.icon {
display: inline-block;
width: 32px;
height: 32px;
background-repeat: no-repeat;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAmdJREFUeNrsV7FqFFEUPfe8FSFYJSSbLcQ+oE3EzsrCNqTITwg2/omFVb5ARWxsDHZWlhqCdoJFCGSnEFZWMu8ei70Lbye72R12IYV5cFmYmffuuWfOPXPXJOE6F3HN6wbADYBO84KZAQB6vd6+pL1VJDGz96enp+8AoNl1UxnY2tq6I2kfQF5FxFlciAEA5u5G0gAw53zJKEjCzAggxaUsyd390mEpJYvkFqG5AM7Pz4fdbrczYmySs0jekfQ15/wpkjwxswdmVjdBSLIAykg+FwACKYtNE5VL+nZ2dvaquPej2+0+M7P7JJtMlAy07gJrhpmlnPMRgBrARUSdcz4yszRtT6sumJK8SSkBDALAuFSamc/YcyUItql+LKKU0l4kHyvdST4NvVgbFlox4O4g6SR3t7e3X0j6AOCPmR0A2HX32t1bMTATgCSzsSs1lrtnM3sI4FGo3CXlGYksnmkPIDZPOORY0ZLKg1n0uJeO13iu1SuYsGeSDLH9cvfP7v6z3++fAMDGxsYOyXskH5O8OyLJfZFhZ64Gxskl/c05v6yq6qSoVAAQQL4D+Li+vr6TUnpO8nYYwkq6ILn7YVVVx0X/1424AFBXVXXs7ofhfst3AUmTxH6//yUS5bL6KY6XhsPh8draGuO1YVU+UFabmz4QvzWAejAY/F6ZD7i7SGpzc/NtyxnAwzeWAyAJ7u4kW83voybQ8gzE97z9rDeqHPM00LmCwjeSDlY0kr2eea9pFsWkcysALju4etGmWZLPY0CFqrEiALNadyYAFd97WxJA6ZpaVAM+bYBcEoQW0sB/98/o3wDaEFXSD7l9+QAAAABJRU5ErkJggg==);
}
</style>
</head>
<body theme="core-light-theme" unresolved>
<core-field>
<div class="icon"></div>
<input placeholder="hi!" flex>
</core-field>
<core-field>
<div class="icon"></div>
<input placeholder="Search" flex>
<icon></icon>
</core-field>
<core-field>
<div class="icon"></div>
<label>I'm a label!</label>
<input placeholder="I have a label" flex>
</core-field>
<core-field>
<input placeholder="I have no icon" flex>
</core-field>
</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.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>
<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-field" label="Field" group="Core" isContainer>
<template>
<core-field icon="search" theme="core-light-theme">
<core-icon icon="search"></core-icon>
<core-input placeholder="text input" flex></core-input>
</core-field>
</template>
<template id="imports">
<link rel="import" href="core-field.html">
<link rel="import" href="../core-icon/core-icon.html">
<link rel="import" href="../core-input/core-input.html">
</template>
</x-meta>
{
"name": "core-header-panel",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-header-panel",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "820d6e6eaff252fc5cde0c7e6b8f095c6fb65719"
},
"_source": "git://github.com/Polymer/core-header-panel.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-header-panel"
}
{
"name": "core-header-panel",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.4.0"
}
}
/*
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;
}
#outerContainer {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
#mainPanel {
position: relative;
}
#mainContainer {
position: relative;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
#dropShadow {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 6px;
box-shadow: inset 0px 5px 6px -3px rgba(0, 0, 0, 0.4);
}
#dropShadow.hidden {
display: none;
}
/*
mode: scroll
*/
:host([mode=scroll]) #mainContainer {
overflow: visible;
}
:host([mode=scroll]) #outerContainer {
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
/*
mode: cover
*/
:host([mode=cover]) #mainPanel {
position: static;
}
:host([mode=cover]) #mainContainer {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
:host([mode=cover]) #dropShadow {
position: static;
width: 100%;
}
<!--
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
-->
<!--
`core-header-panel` contains a header section and a content panel section.
__Important:__ The `core-header-panel` will not display if its parent does not have a height.
Using [layout attributes](http://www.polymer-project.org/docs/polymer/layout-attrs.html), you can easily make the `core-header-panel` fill the screen
<body fullbleed layout vertical>
<core-header-panel flex>
<core-toolbar>
<div>Hello World!</div>
</core-toolbar>
</core-header-panel>
</body>
or, if you would prefer to do it in CSS, just give `html`, `body`, and `core-header-panel` a height of 100%:
html, body {
height: 100%;
margin: 0;
}
core-header-panel {
height: 100%;
}
Special support is provided for scrolling modes when one uses a core-toolbar or equivalent
for the header section.
Example:
<core-header-panel>
<core-toolbar>Header</core-toolbar>
<div>Content goes here...</div>
</core-header-panel>
If you want to use other than `core-toolbar` for the header, add
`core-header` class to that element.
Example:
<core-header-panel>
<div class="core-header">Header</div>
<div>Content goes here...</div>
</core-header-panel>
To have the content fits to the main area, use `fit` attribute.
<core-header-panel>
<div class="core-header">standard</div>
<div class="content" fit>content fits 100% below the header</div>
</core-header-panel>
Use `mode` to control the header and scrolling behavior.
@group Polymer Core Elements
@element core-header-panel
@homepage github.io
-->
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="core-header-panel">
<template>
<link rel="stylesheet" href="core-header-panel.css">
<div id="outerContainer" vertical layout>
<content id="headerContent" select="core-toolbar, .core-header"></content>
<div id="mainPanel" flex vertical layout>
<div id="mainContainer" flex?="{{mode !== 'cover'}}">
<content id="mainContent" select="*"></content>
</div>
<div id="dropShadow"></div>
</div>
</div>
</template>
<script>
Polymer('core-header-panel', {
/**
* Fired when the content has been scrolled. `event.detail.target` returns
* the scrollable element which you can use to access scroll info such as
* `scrollTop`.
*
* <core-header-panel on-scroll="{{scrollHandler}}">
* ...
* </core-header-panel>
*
*
* scrollHandler: function(event) {
* var scroller = event.detail.target;
* console.log(scroller.scrollTop);
* }
*
* @event scroll
*/
publish: {
/**
* Controls header and scrolling behavior. Options are
* `standard`, `seamed`, `waterfall`, `waterfall-tall`, `scroll` and
* `cover`. Default is `standard`.
*
* `standard`: The header is a step above the panel. The header will consume the
* panel at the point of entry, preventing it from passing through to the
* opposite side.
*
* `seamed`: The header is presented as seamed with the panel.
*
* `waterfall`: Similar to standard mode, but header is initially presented as
* seamed with panel, but then separates to form the step.
*
* `waterfall-tall`: The header is initially taller (`tall` class is added to
* the header). As the user scrolls, the header separates (forming an edge)
* while condensing (`tall` class is removed from the header).
*
* `scroll`: The header keeps its seam with the panel, and is pushed off screen.
*
* `cover`: The panel covers the whole `core-header-panel` including the
* header. This allows user to style the panel in such a way that the panel is
* partially covering the header.
*
* <style>
* core-header-panel[mode=cover]::shadow #mainContainer {
* left: 80px;
* }
* .content {
* margin: 60px 60px 60px 0;
* }
* </style>
*
* <core-header-panel mode="cover">
* <core-appbar class="tall">
* <core-icon-button icon="menu"></core-icon-button>
* </core-appbar>
* <div class="content"></div>
* </core-header-panel>
*
* @attribute mode
* @type string
* @default ''
*/
mode: {value: '', reflect: true},
/**
* The class used in waterfall-tall mode. Change this if the header
* accepts a different class for toggling height, e.g. "medium-tall"
*
* @attribute tallClass
* @type string
* @default 'tall'
*/
tallClass: 'tall',
/**
* If true, the drop-shadow is always shown no matter what mode is set to.
*
* @attribute shadow
* @type boolean
* @default false
*/
shadow: false
},
animateDuration: 200,
modeConfigs: {
shadowMode: {'waterfall': 1, 'waterfall-tall': 1},
noShadow: {'seamed': 1, 'cover': 1, 'scroll': 1},
tallMode: {'waterfall-tall': 1},
outerScroll: {'scroll': 1}
},
ready: function() {
this.scrollHandler = this.scroll.bind(this);
this.addListener();
},
detached: function() {
this.removeListener(this.mode);
},
addListener: function() {
this.scroller.addEventListener('scroll', this.scrollHandler);
},
removeListener: function(mode) {
var s = this.getScrollerForMode(mode);
s.removeEventListener('scroll', this.scrollHandler);
},
domReady: function() {
this.async('scroll');
},
modeChanged: function(old) {
var header = this.header;
if (header) {
var configs = this.modeConfigs;
// in tallMode it may add tallClass to the header; so do the cleanup
// when mode is changed from tallMode to not tallMode
if (configs.tallMode[old] && !configs.tallMode[this.mode]) {
header.classList.remove(this.tallClass);
this.async(function() {
header.classList.remove('animate');
}, null, this.animateDuration);
} else {
header.classList.toggle('animate', configs.tallMode[this.mode]);
}
}
if (configs.outerScroll[this.mode] || configs.outerScroll[old]) {
this.removeListener(old);
this.addListener();
}
this.scroll();
},
get header() {
return this.$.headerContent.getDistributedNodes()[0];
},
getScrollerForMode: function(mode) {
return this.modeConfigs.outerScroll[mode] ?
this.$.outerContainer : this.$.mainContainer;
},
/**
* Returns the scrollable element.
*
* @property scroller
* @type Object
*/
get scroller() {
return this.getScrollerForMode(this.mode);
},
scroll: function() {
var configs = this.modeConfigs;
var main = this.$.mainContainer;
var header = this.header;
var sTop = main.scrollTop;
var atTop = sTop === 0;
this.$.dropShadow.classList.toggle('hidden', !this.shadow &&
(atTop && configs.shadowMode[this.mode] || configs.noShadow[this.mode]));
if (header && configs.tallMode[this.mode]) {
header.classList.toggle(this.tallClass, atTop ||
header.classList.contains(this.tallClass) &&
main.scrollHeight < this.$.outerContainer.offsetHeight);
}
this.fire('scroll', {target: this.scroller}, this, false);
}
});
</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>core-header-panel</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-header-panel.html">
<style shim-shadowdom>
body {
font-family: sans-serif;
}
core-header-panel {
float: left;
width: 360px;
height: 400px;
margin: 5px;
}
core-header-panel[mode=cover]::shadow #mainContainer {
left: 70px;
}
.core-header {
height: 60px;
line-height: 60px;
font-size: 18px;
padding: 0 10px;
background-color: #4F7DC9;
color: #FFF;
transition: height 0.2s;
}
.core-header.tall {
height: 180px;
}
.core-header.medium-tall {
height: 120px;
}
.content {
height: 2000px;
background: linear-gradient(rgb(214, 227, 231), lightblue);
}
</style>
</head>
<body unresolved>
<core-header-panel>
<div class="core-header">standard</div>
<div class="content"></div>
</core-header-panel>
<core-header-panel mode="seamed">
<div class="core-header">seamed</div>
<div class="content"></div>
</core-header-panel>
<core-header-panel mode="waterfall">
<div class="core-header">waterfall</div>
<div class="content"></div>
</core-header-panel>
<core-header-panel mode="waterfall-tall">
<div class="core-header">waterfall-tall</div>
<div class="content"></div>
</core-header-panel>
<core-header-panel mode="waterfall-tall" tallClass="medium-tall">
<div class="core-header">waterfall-tall (tallClass: medium-tall)</div>
<div class="content"></div>
</core-header-panel>
<core-header-panel mode="scroll">
<div class="core-header">scroll</div>
<div class="content"></div>
</core-header-panel>
<core-header-panel mode="cover">
<div class="core-header tall">cover</div>
<div class="content" style="margin: 60px 60px 60px 0;"></div>
</core-header-panel>
</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="../polymer/polymer.html">
<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-header-panel" label="Header Panel" isContainer group="Core">
<property name="mode" kind="select" options="standard, waterfall, waterfall-tall, scroll, cover"></property>
<template>
<core-header-panel mode="standard" style="width: 300px; height: 400px;">
<core-toolbar style="background-color: #4F7DC9; color: #FFF;">
<core-icon-button icon="menu"></core-icon-button>
<div>Header</div>
</core-toolbar>
<section style="height: 1000px; background: linear-gradient(rgb(214, 227, 231), lightblue);"></section>
</core-header-panel>
</template>
<template id="imports">
<link rel="import" href="../core-icon-button/core-icon-button.html">
<link rel="import" href="../core-toolbar/core-toolbar.html">
<link rel="import" href="core-header-panel.html">
</template>
</x-meta>
{
"name": "core-icon-button",
"private": true,
"dependencies": {
"core-icons": "Polymer/core-icons#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-icon-button",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "6c1e3a7e61cc63d010d145fa72200c23dc64d65c"
},
"_source": "git://github.com/Polymer/core-icon-button.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-icon-button"
}
{
"name": "core-icon-button",
"private": true,
"dependencies": {
"core-icons": "Polymer/core-icons#^0.4.0"
}
}
/*
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
*/
:host {
display: inline-block;
box-sizing: border-box;
-moz-box-sizing: border-box;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
border-radius: 2px;
padding: 7px;
margin: 2px;
vertical-align: middle;
font-size: 1rem;
cursor: pointer;
}
:host([disabled]) {
opacity: 0.6;
pointer-events: none;
}
:host(.outline) {
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
}
:host(:hover:not([disabled])) {
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.1);
}
:host(.selected:not([disabled])) {
background-color: rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.12);
}
:host(:active:not([disabled]), .selected:active:not([disabled])) {
background-color: rgba(0, 0, 0, 0.05);
box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.12);
}
:host(.core-dark-theme.outline) {
background-color: rgba(200, 200, 200, 0.05);
box-shadow: 0 0 0 1px rgba(200, 200, 200, 0.1);
}
:host(.core-dark-theme:hover) {
background-color: rgba(200, 200, 200, 0.05);
box-shadow: 0 1px 0 0 rgba(200, 200, 200, 0.12), 0 0 0 1px rgba(200, 200, 200, 0.1);
}
:host(.core-dark-theme.selected) {
background-color: rgba(220, 220, 220, 0.05);
box-shadow: inset 0 1px 0 0 rgba(200, 200, 200, 0.05), 0 0 0 1px rgba(200, 200, 200, 0.12);
}
:host(.core-dark-theme:active, .core-dark-theme.selected:active) {
background-color: rgba(200, 200, 200, 0.05);
box-shadow: inset 0 1px 0 0 rgba(200, 200, 200, 0.1), 0 0 0 1px rgba(200, 200, 200, 0.12);
}
core-icon {
pointer-events: none;
}
/* note: this is a polyfill aware selector */
:host ::content > :not(core-icon) {
margin-left: 4px;
}
<!--
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
-->
<!--
`core-icon-button` is an icon with button behaviors.
<core-icon-button src="star.png"></core-icon-button>
`core-icon-button` includes a default icon set. Use `icon` to specify
which icon from the icon set to use.
<core-icon-button icon="menu"></core-icon-button>
See [`core-iconset`](#core-iconset) for more information about
how to use a custom icon set.
@group Polymer Core Elements
@element core-icon-button
@homepage github.io
-->
<link rel="import" href="../core-icon/core-icon.html">
<link rel="import" href="../core-icons/core-icons.html">
<polymer-element name="core-icon-button" attributes="src icon active">
<template>
<link rel="stylesheet" href="core-icon-button.css">
<core-icon src="{{src}}" icon="{{icon}}"></core-icon><content></content>
</template>
<script>
Polymer('core-icon-button', {
/**
* The URL of an image for the icon. Should not use `icon` property
* if you are using this property.
*
* @attribute src
* @type string
* @default ''
*/
src: '',
/**
* If true, border is placed around the button to indicate it's
* active state.
*
* @attribute active
* @type boolean
* @default false
*/
active: false,
/**
* Specifies the icon name or index in the set of icons available in
* the icon set. Should not use `src` property if you are using this
* property.
*
* @attribute icon
* @type string
* @default ''
*/
icon: '',
activeChanged: function() {
this.classList.toggle('selected', this.active);
}
});
</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
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>
<title>core-icon-button</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="core-icon-button.html">
<style>
</style>
</head>
<body unresolved>
<template is="auto-binding">
<template repeat="{{icon in $.meta.metaData.icons.iconNames}}">
<core-icon-button icon="{{icon}}" title="{{icon}}"></core-icon-button>
</template>
<core-icon-button icon="menu"><span>label</span></core-icon-button>
</div>
<core-iconset id="meta"></core-iconset>
</template>
</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-icon-button" label="Icon Button" group="Core">
<template>
<core-icon-button icon="menu" theme="core-light-theme"></core-icon-button>
</template>
<template id="imports">
<link rel="import" href="core-icon-button.html">
</template>
</x-meta>
{
"name": "core-icon",
"private": true,
"dependencies": {
"core-iconset": "Polymer/core-iconset#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-icon",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "3dab73d7aa085b76cdac91bc527c83bcd2ba4577"
},
"_source": "git://github.com/Polymer/core-icon.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-icon"
}
{
"name": "core-icon",
"private": true,
"dependencies": {
"core-iconset": "Polymer/core-iconset#^0.4.0",
"core-icons": "Polymer/core-icons#^0.4.0"
}
}
/* 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 /deep/ core-icon {
display: inline-block;
vertical-align: middle;
background-repeat: no-repeat;
fill: currentcolor;
position: relative;
height: 24px;
width: 24px;
}
<!--
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
-->
<!--
The `core-icon` element displays an icon. By default an icon renders as a 24px square.
Example using src:
<core-icon src="star.png"></core-icon>
Example setting size to 32px x 32px:
<core-icon class="big" src="big_star.png"></core-icon>
<style>
.big {
height: 32px;
width: 32px;
}
</style>
The core elements include several sets of icons.
To use the default set of icons, import `core-icons.html` and use the `icon` attribute to specify an icon:
&lt;!-- import default iconset and core-icon --&gt;
<link rel="import" href="/components/core-icons/core-icons.html">
<core-icon icon="menu"></core-icon>
To use a different built-in set of icons, import `core-icons/<iconset>-icons.html`, and
specify the icon as `<iconset>:<icon>`. For example:
&lt;!-- import communication iconset and core-icon --&gt;
<link rel="import" href="/components/core-icons/communication-icons.html">
<core-icon icon="communication:email"></core-icon>
You can also create custom icon sets of bitmap or SVG icons.
Example of using an icon named `cherry` from a custom iconset with the ID `fruit`:
<core-icon icon="fruit:cherry"></core-icon>
See [core-iconset](#core-iconset) and [core-iconset-svg](#core-iconset-svg) for more information about
how to create a custom iconset.
See [core-icons](http://www.polymer-project.org/components/core-icons/demo.html) for the default set of icons.
@group Polymer Core Elements
@element core-icon
@homepage polymer.github.io
-->
<link rel="import" href="../core-iconset/core-iconset.html">
<link rel="stylesheet" href="core-icon.css" shim-shadowdom>
<polymer-element name="core-icon" attributes="src icon alt">
<script>
(function() {
// mono-state
var meta;
Polymer('core-icon', {
/**
* The URL of an image for the icon. If the src property is specified,
* the icon property should not be.
*
* @attribute src
* @type string
* @default ''
*/
src: '',
/**
* Specifies the icon name or index in the set of icons available in
* the icon's icon set. If the icon property is specified,
* the src property should not be.
*
* @attribute icon
* @type string
* @default ''
*/
icon: '',
/**
* Alternative text content for accessibility support.
* If alt is present and not empty, it will set the element's role to img and add an aria-label whose content matches alt.
* If alt is present and is an empty string, '', it will hide the element from the accessibility layer
* If alt is not present, it will set the element's role to img and the element will fallback to using the icon attribute for its aria-label.
*
* @attribute alt
* @type string
* @default ''
*/
alt: null,
observe: {
'icon': 'updateIcon',
'alt': 'updateAlt'
},
defaultIconset: 'icons',
ready: function() {
if (!meta) {
meta = document.createElement('core-iconset');
}
// Allow user-provided `aria-label` in preference to any other text alternative.
if (this.hasAttribute('aria-label')) {
// Set `role` if it has not been overridden.
if (!this.hasAttribute('role')) {
this.setAttribute('role', 'img');
}
return;
}
this.updateAlt();
},
srcChanged: function() {
var icon = this._icon || document.createElement('div');
icon.textContent = '';
icon.setAttribute('fit', '');
icon.style.backgroundImage = 'url(' + this.src + ')';
icon.style.backgroundPosition = 'center';
icon.style.backgroundSize = '100%';
if (!icon.parentNode) {
this.appendChild(icon);
}
this._icon = icon;
},
getIconset: function(name) {
return meta.byId(name || this.defaultIconset);
},
updateIcon: function(oldVal, newVal) {
if (!this.icon) {
this.updateAlt();
return;
}
var parts = String(this.icon).split(':');
var icon = parts.pop();
if (icon) {
var set = this.getIconset(parts.pop());
if (set) {
this._icon = set.applyIcon(this, icon);
if (this._icon) {
this._icon.setAttribute('fit', '');
}
}
}
// Check to see if we're using the old icon's name for our a11y fallback
if (oldVal) {
if (oldVal.split(':').pop() == this.getAttribute('aria-label')) {
this.updateAlt();
}
}
},
updateAlt: function() {
// Respect the user's decision to remove this element from
// the a11y tree
if (this.getAttribute('aria-hidden')) {
return;
}
// Remove element from a11y tree if `alt` is empty, otherwise
// use `alt` as `aria-label`.
if (this.alt === '') {
this.setAttribute('aria-hidden', 'true');
if (this.hasAttribute('role')) {
this.removeAttribute('role');
}
if (this.hasAttribute('aria-label')) {
this.removeAttribute('aria-label');
}
} else {
this.setAttribute('aria-label', this.alt ||
this.icon.split(':').pop());
if (!this.hasAttribute('role')) {
this.setAttribute('role', 'img');
}
if (this.hasAttribute('aria-hidden')) {
this.removeAttribute('aria-hidden');
}
}
}
});
})();
</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>core-icon</title>
<script src="../platform/platform.js"></script>
<link rel="import" href="../core-icons/core-icons.html">
<link rel="import" href="core-icon.html">
<style>
segment {
min-width: 200px;
}
core-icon.big {
height: 128px;
width: 128px;
}
</style>
</head>
<body unresolved>
<template is="auto-binding">
<div wrap horizontal layout>
<template repeat="{{icon in $.meta.metaData.icons.iconNames}}">
<segment><core-icon icon="{{icon}}"></core-icon> {{icon}}</segment>
</template>
</div>
<core-iconset id="meta"></core-iconset>
<div hidden?="{{!$.meta.metaData.icons.iconNames}}">
Sized icon:
<core-icon class="big" icon="accessibility"></core-icon>
</div>
</template>
</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-icon" label="Icon" group="Core" hideSubtree>
<template>
<core-icon icon="search"></core-icon>
</template>
<template id="imports">
<link rel="import" href="../core-icons/core-icons.html">
<link rel="import" href="core-icon.html">
</template>
</x-meta>
{
"name": "core-icons",
"private": true,
"dependencies": {
"core-icon": "Polymer/core-icon#^0.4.0",
"core-iconset-svg": "Polymer/core-iconset-svg#^0.4.0",
"polymer": "Polymer/polymer#^0.4.0"
},
"homepage": "https://github.com/Polymer/core-icons",
"version": "0.4.2",
"_release": "0.4.2",
"_resolution": {
"type": "version",
"tag": "0.4.2",
"commit": "5dda465d04eb1b0d595f6b59a401506bf90dc257"
},
"_source": "git://github.com/Polymer/core-icons.git",
"_target": "^0.4.0",
"_originalSource": "Polymer/core-icons"
}
<!--
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="../core-icon/core-icon.html">
<link rel="import" href="../core-iconset-svg/core-iconset-svg.html">
<core-iconset-svg id="av" iconSize="24">
<svg><defs>
<g id="closed-caption"><path d="M19,4H5C3.9,4,3,4.9,3,6v12c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M11,11H9.5v-0.5h-2v3h2V13H11v1c0,0.6-0.4,1-1,1H7c-0.6,0-1-0.4-1-1v-4c0-0.6,0.4-1,1-1h3c0.6,0,1,0.4,1,1V11z M18,11h-1.5v-0.5h-2v3h2V13H18v1c0,0.6-0.4,1-1,1h-3c-0.6,0-1-0.4-1-1v-4c0-0.6,0.4-1,1-1h3c0.6,0,1,0.4,1,1V11z"/></g>
<g id="fast-forward"><path d="M4,18l8.5-6L4,6V18z M13,6v12l8.5-6L13,6z"/></g>
<g id="fast-rewind"><path d="M11,18V6l-8.5,6L11,18z M11.5,12l8.5,6V6L11.5,12z"/></g>
<g id="games"><path d="M15,7.5V2H9v5.5l3,3L15,7.5z M7.5,9H2v6h5.5l3-3L7.5,9z M9,16.5V22h6v-5.5l-3-3L9,16.5z M16.5,9l-3,3l3,3H22V9H16.5z"/></g>
<g id="high-quality"><path d="M19,4H5C3.9,4,3,4.9,3,6v12c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6C21,4.9,20.1,4,19,4z M11,15H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11V15z M18,14c0,0.6-0.4,1-1,1h-0.8v1.5h-1.5V15H14c-0.6,0-1-0.4-1-1v-4c0-0.6,0.4-1,1-1h3c0.6,0,1,0.4,1,1V14z M14.5,13.5h2v-3h-2V13.5z"/></g>
<g id="loop"><path d="M12,4V1L8,5l4,4V6c3.3,0,6,2.7,6,6c0,1-0.3,2-0.7,2.8l1.5,1.5C19.5,15,20,13.6,20,12C20,7.6,16.4,4,12,4z M12,18c-3.3,0-6-2.7-6-6c0-1,0.3-2,0.7-2.8L5.2,7.7C4.5,9,4,10.4,4,12c0,4.4,3.6,8,8,8v3l4-4l-4-4V18z"/></g>
<g id="mic"><path d="M12,14c1.7,0,3-1.3,3-3l0-6c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v6C9,12.7,10.3,14,12,14z M17.3,11c0,3-2.5,5.1-5.3,5.1c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V21h2v-3.3c3.3-0.5,6-3.3,6-6.7H17.3z"/></g>
<g id="mic-none"><path d="M12,14c1.7,0,3-1.3,3-3l0-6c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v6C9,12.7,10.3,14,12,14z M10.8,4.9c0-0.7,0.5-1.2,1.2-1.2c0.7,0,1.2,0.5,1.2,1.2l0,6.2c0,0.7-0.5,1.2-1.2,1.2c-0.7,0-1.2-0.5-1.2-1.2V4.9z M17.3,11c0,3-2.5,5.1-5.3,5.1c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V21h2v-3.3c3.3-0.5,6-3.3,6-6.7H17.3z"/></g>
<g id="mic-off"><path d="M19,11h-1.7c0,0.7-0.2,1.4-0.4,2l1.2,1.2C18.7,13.3,19,12.2,19,11z"/><path d="M15,11.2c0-0.1,0-0.1,0-0.2V5c0-1.7-1.3-3-3-3c-1.7,0-3,1.3-3,3v0.2L15,11.2z"/><path d="M4.3,3L3,4.3l6,6L9,11c0,1.7,1.3,3,3,3c0.2,0,0.4,0,0.7-0.1l1.7,1.7c-0.7,0.3-1.5,0.5-2.3,0.5c-2.8,0-5.3-2.1-5.3-5.1H5c0,3.4,2.7,6.2,6,6.7V21h2v-3.3c0.9-0.1,1.8-0.5,2.5-0.9l4.2,4.2l1.3-1.3L4.3,3z"/></g>
<g id="movie"><path d="M18,4l2,4h-3l-2-4h-2l2,4h-3l-2-4H8l2,4H7L5,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4H18z"/></g>
<g id="news"><path d="M20.3,4.7L18.7,3L17,4.7L15.3,3l-1.7,1.7L12,3l-1.7,1.7L8.7,3L7,4.7L5.3,3L3.7,4.7L2,3v16c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2l0-16L20.3,4.7z M12,19H4v-7h8V19z M20,19h-7v-1h7V19z M20,17h-7v-1h7V17z M20,15h-7v-1h7V15z M20,13h-7v-1h7V13z M20,11H4V8h16V11z"/></g>
<g id="pause"><path d="M6,19h4V5H6V19z M14,5v14h4V5H14z"/></g>
<g id="pause-circle-fill"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M11,16H9V8h2V16z M15,16h-2V8h2V16z"/></g>
<g id="pause-circle-outline"><path d="M9,16h2V8H9V16z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z M13,16h2V8h-2V16z"/></g>
<g id="play-arrow"><polygon points="8,5 8,19 19,12 "/></g>
<g id="play-circle-fill"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M10,16.5v-9l6,4.5L10,16.5z"/></g>
<g id="play-circle-outline"><path d="M10,16.5l6-4.5l-6-4.5V16.5z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g>
<g id="queue"><path d="M4,6H2v14c0,1.1,0.9,2,2,2h14v-2H4V6z M20,2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M19,11h-4v4h-2v-4H9V9h4V5h2v4h4V11z"/></g>
<g id="replay"><path d="M12,5V1L7,6l5,5V7c3.3,0,6,2.7,6,6s-2.7,6-6,6c-3.3,0-6-2.7-6-6H4c0,4.4,3.6,8,8,8c4.4,0,8-3.6,8-8S16.4,5,12,5z"/></g>
<g id="shuffle"><path d="M10.6,9.2L5.4,4L4,5.4l5.2,5.2L10.6,9.2z M14.5,4l2,2L4,18.6L5.4,20L18,7.5l2,2V4H14.5z M14.8,13.4l-1.4,1.4l3.1,3.1l-2,2H20v-5.5l-2,2L14.8,13.4z"/></g>
<g id="skip-next"><path d="M6,18l8.5-6L6,6V18z M16,6v12h2V6H16z"/></g>
<g id="skip-previous"><rect x="6" y="6" width="2" height="12"/><polygon points="9.5,12 18,18 18,6 "/></g>
<g id="stop"><rect x="6" y="6" width="12" height="12"/></g>
<g id="videocam"><path d="M17,10.5V7c0-0.6-0.4-1-1-1H4C3.4,6,3,6.4,3,7v10c0,0.6,0.4,1,1,1h12c0.6,0,1-0.4,1-1v-3.5l4,4v-11L17,10.5z"/></g>
<g id="videocam-off"><path d="M21,6.5l-4,4V7c0-0.6-0.4-1-1-1H9.8L21,17.2V6.5z M3.3,2L2,3.3L4.7,6H4C3.4,6,3,6.4,3,7v10c0,0.6,0.4,1,1,1h12c0.2,0,0.4-0.1,0.5-0.2l3.2,3.2l1.3-1.3L3.3,2z"/></g>
<g id="video-youtube"><path d="M20,4.4C19.4,4.2,15.7,4,12,4C8.3,4,4.6,4.2,4,4.4c-1.6,0.5-2,4-2,7.6s0.4,7.1,2,7.6c0.6,0.2,4.3,0.4,8,0.4c3.7,0,7.4-0.2,8-0.4c1.6-0.5,2-4,2-7.6S21.6,4.9,20,4.4z M10,16.5v-9l6,4.5L10,16.5z"/></g>
<g id="volume-down"><path d="M18.5,12c0-1.8-1-3.3-2.5-4V16C17.5,15.3,18.5,13.8,18.5,12z M5,9c0,0,0,6,0,6h4l5,5V4L9,9H5z"/></g>
<g id="volume-mute"><path d="M7,9c0,0,0,6,0,6h4l5,5V4l-5,5H7z"/></g>
<g id="volume-off"><path d="M16.5,12c0-1.8-1-3.3-2.5-4v2.2l2.5,2.5C16.5,12.4,16.5,12.2,16.5,12z M19,12c0,0.9-0.2,1.8-0.5,2.6l1.5,1.5c0.7-1.2,1-2.7,1-4.2c0-4.3-3-7.9-7-8.8v2.1C16.9,6.2,19,8.8,19,12z M4.3,3L3,4.3L7.7,9H3c0,0,0,6,0,6h4l5,5v-6.7l4.3,4.3c-0.7,0.5-1.4,0.9-2.3,1.2v2.1c1.4-0.3,2.6-0.9,3.7-1.8l2,2l1.3-1.3l-9-9L4.3,3z M12,4L9.9,6.1L12,8.2V4z"/></g>
<g id="volume-up"><path d="M3,9c0,0,0,6,0,6h4l5,5V4L7,9H3z M16.5,12c0-1.8-1-3.3-2.5-4V16C15.5,15.3,16.5,13.8,16.5,12z M14,3.2v2.1c2.9,0.9,5,3.5,5,6.7s-2.1,5.8-5,6.7v2.1c4-0.9,7-4.5,7-8.8S18,4.1,14,3.2z"/></g>
<g id="web"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M15,18H4v-4h11V18z M15,13H4V9h11V13z M20,18h-4V9h4V18z"/></g>
</defs></svg>
</core-iconset-svg>
{
"name": "core-icons",
"private": true,
"dependencies": {
"core-icon": "Polymer/core-icon#^0.4.0",
"core-iconset-svg": "Polymer/core-iconset-svg#^0.4.0",
"polymer": "Polymer/polymer#^0.4.0"
}
}
<!--
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="../core-icon/core-icon.html">
<link rel="import" href="../core-iconset-svg/core-iconset-svg.html">
<core-iconset-svg id="communication" iconSize="24">
<svg><defs>
<g id="business"><path d="M12,7V3H2v18h20V7H12z M6,19H4v-2h2V19z M6,15H4v-2h2V15z M6,11H4V9h2V11z M6,7H4V5h2V7z M10,19H8v-2h2V19z M10,15H8v-2h2V15z M10,11H8V9h2V11z M10,7H8V5h2V7z M20,19h-8v-2h2v-2h-2v-2h2v-2h-2V9h8V19z M18,11h-2v2h2V11z M18,15h-2v2h2V15z"/></g>
<g id="call"><path d="M6.6,10.8c1.4,2.8,3.8,5.1,6.6,6.6l2.2-2.2c0.3-0.3,0.7-0.4,1-0.2c1.1,0.4,2.3,0.6,3.6,0.6c0.6,0,1,0.4,1,1V20c0,0.6-0.4,1-1,1C10.6,21,3,13.4,3,4c0-0.6,0.4-1,1-1h3.5c0.6,0,1,0.4,1,1c0,1.2,0.2,2.4,0.6,3.6c0.1,0.3,0,0.7-0.2,1L6.6,10.8z"/></g>
<g id="call-end"><path d="M12,9c-1.6,0-3.1,0.3-4.6,0.7l0,3.1c0,0.4-0.2,0.7-0.6,0.9c-1,0.5-1.9,1.1-2.7,1.9c-0.2,0.2-0.4,0.3-0.7,0.3c-0.3,0-0.5-0.1-0.7-0.3l-2.5-2.5C0.1,12.9,0,12.7,0,12.4c0-0.3,0.1-0.5,0.3-0.7C3.3,8.8,7.5,7,12,7s8.7,1.8,11.7,4.7c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-2.5,2.5c-0.2,0.2-0.4,0.3-0.7,0.3c-0.3,0-0.5-0.1-0.7-0.3c-0.8-0.7-1.7-1.4-2.7-1.9c-0.3-0.2-0.6-0.5-0.6-0.9l0-3.1C15.1,9.3,13.6,9,12,9z"/></g>
<g id="call-made"><polygon points="9,5 9,7 15.6,7 3,19.6 4.4,21 17,8.4 17,15 19,15 19,5 "/></g>
<g id="call-merge"><path d="M17,20.4l1.4-1.4L15,15.6L13.6,17L17,20.4z M7.5,8H11v5.6L5.6,19L7,20.4l6-6V8h3.5L12,3.5L7.5,8z"/></g>
<g id="call-missed"><polygon points="19.6,7 12,14.6 6.4,9 11,9 11,7 3,7 3,15 5,15 5,10.4 12,17.4 21,8.4 "/></g>
<g id="call-received"><polygon points="21,4.4 19.6,3 7,15.6 7,9 5,9 5,19 15,19 15,17 8.4,17 "/></g>
<g id="call-split"><polygon points="14,4 16.3,6.3 13.4,9.2 14.8,10.6 17.7,7.7 20,10 20,4 "/><polygon points="10,4 4,4 4,10 6.3,7.7 11,12.4 11,20 13,20 13,11.6 7.7,6.3 "/></g>
<g id="chat"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M6,9h12v2H6V9z M14,14H6v-2h8V14z M18,8H6V6h12V8z"/></g>
<g id="clear-all"><path d="M5,13h14v-2H5V13z M3,17h14v-2H3V17z M7,7v2h14V7H7z"/></g>
<g id="comment"><path d="M22,4c0-1.1-0.9-2-2-2H4C2.9,2,2,2.9,2,4v12c0,1.1,0.9,2,2,2h14l4,4L22,4z M18,14H6v-2h12V14z M18,11H6V9h12V11z M18,8H6V6h12V8z"/></g>
<g id="contacts"><path d="M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M12,6.8c1.2,0,2.2,1,2.2,2.2s-1,2.2-2.2,2.2s-2.2-1-2.2-2.2S10.8,6.8,12,6.8z M17,17H7v-1.5c0-1.7,3.3-2.5,5-2.5s5,0.8,5,2.5V17z M4,2h16V0H4V2z M4,24h16v-2H4V24z"/></g>
<g id="dialer-sip"><path d="M17,3h-1v5h1V3z M15,5h-2V4h2V3h-3v3h2v1h-2v1h3V5z M18,3v5h1V6h2V3H18z M20,5h-1V4h1V5z M20,15.5c-1.2,0-2.4-0.2-3.6-0.6c-0.3-0.1-0.7,0-1,0.2l-2.2,2.2c-2.8-1.4-5.1-3.8-6.6-6.6l2.2-2.2c0.3-0.3,0.4-0.7,0.2-1C8.7,6.4,8.5,5.2,8.5,4c0-0.6-0.4-1-1-1H4C3.4,3,3,3.4,3,4c0,9.4,7.6,17,17,17c0.6,0,1-0.4,1-1v-3.5C21,15.9,20.6,15.5,20,15.5z"/></g>
<g id="dialpad"><path d="M12,19c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C14,19.9,13.1,19,12,19z M6,1C4.9,1,4,1.9,4,3c0,1.1,0.9,2,2,2s2-0.9,2-2C8,1.9,7.1,1,6,1z M6,7C4.9,7,4,7.9,4,9c0,1.1,0.9,2,2,2s2-0.9,2-2C8,7.9,7.1,7,6,7z M6,13c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C8,13.9,7.1,13,6,13z M18,5c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C16,4.1,16.9,5,18,5z M12,13c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C14,13.9,13.1,13,12,13z M18,13c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C20,13.9,19.1,13,18,13z M18,7c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C20,7.9,19.1,7,18,7z M12,7c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C14,7.9,13.1,7,12,7z M12,1c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2s2-0.9,2-2C14,1.9,13.1,1,12,1z"/></g>
<g id="dnd-on"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8c0-1.8,0.6-3.5,1.7-4.9l11.2,11.2C15.5,19.4,13.8,20,12,20z M18.3,16.9L7.1,5.7C8.5,4.6,10.2,4,12,4c4.4,0,8,3.6,8,8C20,13.8,19.4,15.5,18.3,16.9z"/></g>
<g id="email"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,8l-8,5L4,8V6l8,5l8-5V8z"/></g>
<g id="forum"><path d="M21,6h-2v9H6v2c0,0.6,0.4,1,1,1h11l4,4V7C22,6.4,21.6,6,21,6z M17,12V3c0-0.6-0.4-1-1-1H3C2.4,2,2,2.4,2,3v14l4-4h10C16.6,13,17,12.6,17,12z"/></g>
<g id="gmail"><path d="M20,4H4C2.9,4,2,4.9,2,6l0,12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M20,18h-2V9.2L12,13L6,9.2V18H4V6h1.2l6.8,4.2L18.8,6H20V18z"/></g>
<g id="hangout"><path d="M11.5,2C6.8,2,3,5.8,3,10.5S6.8,19,11.5,19H12v3.5c4.9-2.3,8-7.5,8-12C20,5.8,16.2,2,11.5,2z M11,11l-1,2H8.5l1-2H8V8h3V11z M15,11l-1,2h-1.5l1-2H12V8h3V11z"/></g>
<g id="hangout-video"><path d="M20,4H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V6C22,4.9,21.1,4,20,4z M18,16l-4-3.2V16H6V8h8v3.2L18,8V16z"/></g>
<g id="hangout-video-off"><path d="M20,4H7.8l4,4H14v2.2l0.6,0.6L18,8v6.2l4,4c0-0.1,0-0.1,0-0.2V6C22,4.9,21.1,4,20,4z M2.3,1L1,2.3l2,2C2.4,4.6,2,5.3,2,6v12c0,1.1,0.9,2,2,2h14.7l2,2l1.3-1.3L2.3,1z M6,8h0.7l7.3,7.3V16H6V8z"/></g>
<g id="import-export"><path d="M9,3L5,7h3v7h2V7h3L9,3z M16,17v-7h-2v7h-3l4,4l4-4H16z"/></g>
<g id="invert-colors-off"><path d="M20.6,20.9l-2.4-2.4L12,12.2L8.4,8.7L7,7.2L4.3,4.5L3,5.8l2.8,2.8c-2.5,3.1-2.4,7.8,0.6,10.7c1.6,1.6,3.6,2.3,5.7,2.3c1.8,0,3.6-0.6,5-1.8l2.7,2.7l1.3-1.3L20.6,20.9z M12,19.6c-1.6,0-3.1-0.6-4.2-1.8C6.6,16.7,6,15.2,6,13.6C6,12.3,6.4,11,7.2,10l4.8,4.8V19.6z M12,5.1v4.6l7.3,7.3c1.4-3,0.8-6.6-1.6-9L12,2.3l0,0v0L8.3,6l1.4,1.4L12,5.1z"/></g>
<g id="invert-colors-on"><path d="M17.7,7.9L12,2.3l0,0v0L6.3,7.9c-3.1,3.1-3.1,8.2,0,11.3c1.6,1.6,3.6,2.3,5.7,2.3s4.1-0.8,5.7-2.3C20.8,16.1,20.8,11.1,17.7,7.9z M12,19.6L12,19.6c-1.6,0-3.1-0.6-4.2-1.8C6.6,16.7,6,15.2,6,13.6s0.6-3.1,1.8-4.2L12,5.1L12,19.6z"/></g>
<g id="live-help"><path d="M19,2H5C3.9,2,3,2.9,3,4v14c0,1.1,0.9,2,2,2h4l3,3l3-3h4c1.1,0,2-0.9,2-2V4C21,2.9,20.1,2,19,2z M13,18h-2v-2h2V18z M15.1,10.3l-0.9,0.9C13.4,11.9,13,12.5,13,14h-2v-0.5c0-1.1,0.4-2.1,1.2-2.8l1.2-1.3C13.8,9.1,14,8.6,14,8c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2H8c0-2.2,1.8-4,4-4s4,1.8,4,4C16,8.9,15.6,9.7,15.1,10.3z"/></g>
<g id="location-off"><polygon points="11.7,11.5 11.7,11.5 11.6,11.4 "/><path d="M12,6.5c1.4,0,2.5,1.1,2.5,2.5c0,0.7-0.3,1.4-0.8,1.9l3.6,3.6c1-1.9,1.7-3.8,1.7-5.5c0-3.9-3.1-7-7-7c-2,0-3.8,0.8-5,2.1l3.2,3.2C10.6,6.8,11.3,6.5,12,6.5z M16.4,16.1l-4.6-4.6l-0.1-0.1L3.3,3L2,4.3l3.2,3.2C5.1,8,5,8.5,5,9c0,5.2,7,13,7,13s1.7-1.9,3.4-4.4l3.4,3.4l1.3-1.3L16.4,16.1z"/></g>
<g id="location-on"><path d="M12,2C8.1,2,5,5.1,5,9c0,5.2,7,13,7,13s7-7.8,7-13C19,5.1,15.9,2,12,2z M12,11.5c-1.4,0-2.5-1.1-2.5-2.5s1.1-2.5,2.5-2.5c1.4,0,2.5,1.1,2.5,2.5S13.4,11.5,12,11.5z"/></g>
<g id="message"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M18,14H6v-2h12V14z M18,11H6V9h12V11z M18,8H6V6h12V8z"/></g>
<g id="messenger"><path d="M20,2H4C2.9,2,2,2.9,2,4v18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z"/></g>
<g id="no-sim"><path d="M19,5c0-1.1-0.9-2-2-2h-7L7.7,5.3L19,16.7L19,5z M3.7,3.9L2.4,5.2L5,7.8V19c0,1.1,0.9,2,2,2h10c0.4,0,0.7-0.1,1-0.3l1.9,1.9l1.3-1.3L3.7,3.9z"/></g>
<g id="phone"><path d="M6.6,10.8c1.4,2.8,3.8,5.1,6.6,6.6l2.2-2.2c0.3-0.3,0.7-0.4,1-0.2c1.1,0.4,2.3,0.6,3.6,0.6c0.6,0,1,0.4,1,1V20c0,0.6-0.4,1-1,1C10.6,21,3,13.4,3,4c0-0.6,0.4-1,1-1h3.5c0.6,0,1,0.4,1,1c0,1.2,0.2,2.4,0.6,3.6c0.1,0.3,0,0.7-0.2,1L6.6,10.8z"/></g>
<g id="portable-wifi-off"><path d="M17.6,14.2c0.3-0.7,0.4-1.4,0.4-2.2c0-3.3-2.7-6-6-6c-0.8,0-1.5,0.2-2.2,0.4l1.6,1.6C11.6,8,11.8,8,12,8c2.2,0,4,1.8,4,4c0,0.2,0,0.4-0.1,0.6L17.6,14.2z M12,4c4.4,0,8,3.6,8,8c0,1.4-0.4,2.6-0.9,3.7l1.5,1.5c0.9-1.5,1.5-3.3,1.5-5.2c0-5.5-4.5-10-10-10c-1.9,0-3.7,0.5-5.2,1.5l1.5,1.5C9.4,4.3,10.6,4,12,4z M3.3,2.5L2,3.8l2.1,2.1C2.8,7.6,2,9.7,2,12c0,3.7,2,6.9,5,8.6l1-1.7c-2.4-1.4-4-4-4-6.9c0-1.8,0.6-3.4,1.5-4.7L7,8.7C6.4,9.7,6,10.8,6,12c0,2.2,1.2,4.1,3,5.2l1-1.7c-1.2-0.7-2-2-2-3.4c0-0.6,0.2-1.2,0.4-1.8l1.6,1.6c0,0.1,0,0.1,0,0.2c0,1.1,0.9,2,2,2c0.1,0,0.1,0,0.2,0l0,0v0l7.5,7.5l1.3-1.3L4.3,3.5L3.3,2.5z"/></g>
<g id="quick-contacts-dialer"><path d="M22,3H2C0.9,3,0,3.9,0,5v14c0,1.1,0.9,2,2,2h20c1.1,0,2-0.9,2-2l0-14C24,3.9,23.1,3,22,3z M8,6c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C5,7.3,6.3,6,8,6z M14,18H2v-1c0-2,4-3.1,6-3.1s6,1.1,6,3.1V18z M17.8,14h1.6l1.5,2l-2,2c-1.3-1-2.3-2.4-2.7-4c-0.2-0.6-0.3-1.3-0.3-2s0.1-1.4,0.3-2c0.4-1.6,1.4-3,2.7-4l2,2l-1.5,2h-1.6c-0.2,0.6-0.3,1.3-0.3,2S17.6,13.4,17.8,14z"/></g>
<g id="quick-contacts-mail"><path d="M21,8V7l-3,2l-3-2v1l3,2L21,8z M22,3H2C0.9,3,0,3.9,0,5v14c0,1.1,0.9,2,2,2h20c1.1,0,2-0.9,2-2l0-14C24,3.9,23.1,3,22,3z M8,6c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C5,7.3,6.3,6,8,6z M14,18H2v-1c0-2,4-3.1,6-3.1s6,1.1,6,3.1V18z M22,12h-8V6h8V12z"/></g>
<g id="ring-volume"><path d="M23.7,16.7c-3-2.9-7.2-4.7-11.7-4.7c-4.5,0-8.7,1.8-11.7,4.7C0.1,16.9,0,17.1,0,17.4c0,0.3,0.1,0.5,0.3,0.7l2.5,2.5c0.2,0.2,0.4,0.3,0.7,0.3c0.3,0,0.5-0.1,0.7-0.3c0.8-0.7,1.7-1.4,2.7-1.9c0.3-0.2,0.6-0.5,0.6-0.9l0-3.1c1.4-0.5,3-0.7,4.6-0.7s3.1,0.3,4.6,0.7l0,3.1c0,0.4,0.2,0.7,0.6,0.9c1,0.5,1.9,1.1,2.7,1.9c0.2,0.2,0.4,0.3,0.7,0.3c0.3,0,0.5-0.1,0.7-0.3l2.5-2.5c0.2-0.2,0.3-0.4,0.3-0.7C24,17.1,23.9,16.9,23.7,16.7z M21.2,6.3l-1.4-1.4l-3.6,3.6l1.4,1.4C17.6,9.8,21,6.3,21.2,6.3z M13,2h-2v5h2V2z M6.4,9.8l1.4-1.4L4.3,4.8L2.8,6.3C3,6.3,6.4,9.8,6.4,9.8z"/></g>
<g id="search-hands-free"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10S17.5,2,12,2z M11,19.9c-3.6-0.5-6.5-3.3-6.9-6.9h3c0.4,2,1.9,3.5,3.9,3.9V19.9z M10,8l-3,3H4.1C4.6,7.1,7.9,4,12,4s7.4,3.1,7.9,7H17l-3-3H10z M13,19.9v-3c2-0.4,3.5-1.9,3.9-3.9h3C19.5,16.6,16.6,19.5,13,19.9z"/></g>
<g id="stay-current-landscape"><path d="M1,7l0,10c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V7c0-1.1-0.9-2-2-2H3C1.9,5,1,5.9,1,7z M19,7v10H5V7H19z"/></g>
<g id="stay-current-portrait"><path d="M17,1L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g>
<g id="stay-primary-landscape"><path d="M1,7l0,10c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V7c0-1.1-0.9-2-2-2H3C1.9,5,1,5.9,1,7z M19,7v10H5V7H19z"/></g>
<g id="stay-primary-portrait"><path d="M17,1L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1,17,1z M17,19H7V5h10V19z"/></g>
<g id="swap-calls"><path d="M18,4l-4,4h3v7c0,1.1-0.9,2-2,2s-2-0.9-2-2V8c0-2.2-1.8-4-4-4S5,5.8,5,8v7H2l4,4l4-4H7V8c0-1.1,0.9-2,2-2s2,0.9,2,2v7c0,2.2,1.8,4,4,4s4-1.8,4-4V8h3L18,4z"/></g>
<g id="textsms"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M9,11H7V9h2V11z M13,11h-2V9h2V11z M17,11h-2V9h2V11z"/></g>
<g id="voicemail"><path d="M18.5,6c-3,0-5.5,2.5-5.5,5.5c0,1.3,0.5,2.5,1.3,3.5H9.7c0.8-1,1.3-2.2,1.3-3.5C11,8.5,8.5,6,5.5,6S0,8.5,0,11.5S2.5,17,5.5,17h13c3,0,5.5-2.5,5.5-5.5S21.5,6,18.5,6z M5.5,15C3.6,15,2,13.4,2,11.5C2,9.6,3.6,8,5.5,8C7.4,8,9,9.6,9,11.5C9,13.4,7.4,15,5.5,15z M18.5,15c-1.9,0-3.5-1.6-3.5-3.5C15,9.6,16.6,8,18.5,8c1.9,0,3.5,1.6,3.5,3.5C22,13.4,20.4,15,18.5,15z"/></g>
<g id="vpn-key"><path d="M12.7,10c-0.8-2.3-3-4-5.7-4c-3.3,0-6,2.7-6,6s2.7,6,6,6c2.6,0,4.8-1.7,5.7-4H17v4h4v-4h2v-4H12.7z M7,14c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2s2,0.9,2,2C9,13.1,8.1,14,7,14z"/></g>
</defs></svg>
</core-iconset-svg>
This file has been truncated, but you can view the full 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="../core-icon/core-icon.html">
<link rel="import" href="../core-iconset-svg/core-iconset-svg.html">
<core-iconset-svg id="icons" iconSize="24">
<svg><defs>
<g id="accessibility"><path d="M12,2c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,2,12,2z M21,9h-6v13h-2v-6h-2v6H9V9H3V7h18V9z"/></g>
<g id="account-balance"><path d="M4,10v7h3v-7H4z M10,10v7h3v-7H10z M2,22h19v-3H2V22z M16,10v7h3v-7H16z M11.5,1L2,6v2h19V6L11.5,1z"/></g>
<g id="account-box"><path d="M3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5z M15,9c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3c0-1.7,1.3-3,3-3C13.7,6,15,7.3,15,9z M6,17c0-2,4-3.1,6-3.1s6,1.1,6,3.1v1H6V17z"/></g>
<g id="account-child"><path d="M16.5,12c1.4,0,2.5-1.1,2.5-2.5C19,8.1,17.9,7,16.5,7C15.1,7,14,8.1,14,9.5C14,10.9,15.1,12,16.5,12z M9,11c1.7,0,3-1.3,3-3s-1.3-3-3-3C7.3,5,6,6.3,6,8S7.3,11,9,11z M16.5,14c-1.8,0-5.5,0.9-5.5,2.7V19h11v-2.2C22,14.9,18.3,14,16.5,14z M9,13c-2.3,0-7,1.2-7,3.5V19h7v-2.2c0-0.8,0.3-2.3,2.4-3.5C10.5,13.1,9.7,13,9,13z"/></g>
<g id="account-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,5c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,6.3,10.3,5,12,5z M12,19.2c-2.5,0-4.7-1.3-6-3.2c0-2,4-3.1,6-3.1c2,0,6,1.1,6,3.1C16.7,17.9,14.5,19.2,12,19.2z"/></g>
<g id="add"><path d="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6V13z"/></g>
<g id="add-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g>
<g id="add-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"/></g>
<g id="add-circle-outline"><path d="M13,7h-2v4H7v2h4v4h2v-4h4v-2h-4V7z M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g>
<g id="add-shopping-cart"><polygon points="18.3,6 18.3,6 15.6,11 "/><path d="M11,9h2V6h3V4h-3V1h-2v3H8v2h3V9z M7,18c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S8.1,18,7,18z M17,18c-1.1,0-2,0.9-2,2s0.9,2,2,2s2-0.9,2-2S18.1,18,17,18z M7.2,14.8c0,0,0-0.1,0-0.1L8.1,13h7.4c0.8,0,1.4-0.4,1.7-1l3.9-7l-1.7-1h0l-1.1,2l-2.8,5h-7l-0.1-0.3L6.2,6L5.2,4L4.3,2H1v2h2l3.6,7.6L5.2,14C5.1,14.3,5,14.7,5,15c0,1.1,0.9,2,2,2h12v-2H7.4C7.3,15,7.2,14.9,7.2,14.8z"/></g>
<g id="alarm"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12.5,8H11v6l4.7,2.9l0.8-1.2l-4-2.4V8z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z"/></g>
<g id="alarm-add"><path d="M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7c3.9,0,7,3.1,7,7C19,16.9,15.9,20,12,20z M13,9h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g>
<g id="alarm-off"><path d="M12,6c3.9,0,7,3.1,7,7c0,0.8-0.2,1.6-0.4,2.4l1.5,1.5c0.6-1.2,0.9-2.5,0.9-3.9c0-5-4-9-9-9c-1.4,0-2.7,0.3-3.9,0.9l1.5,1.5C10.4,6.2,11.2,6,12,6z M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M2.9,2.3L1.6,3.6L3,4.9L1.9,5.8l1.4,1.4l1.1-0.9l0.8,0.8C3.8,8.7,3,10.7,3,13c0,5,4,9,9,9c2.3,0,4.3-0.8,5.9-2.2l2.2,2.2l1.3-1.3L3.9,3.3L2.9,2.3z M16.5,18.4c-1.2,1-2.8,1.6-4.5,1.6c-3.9,0-7-3.1-7-7c0-1.7,0.6-3.3,1.6-4.5L16.5,18.4z M8,3.3L6.6,1.9L5.7,2.6L7.2,4L8,3.3z"/></g>
<g id="alarm-on"><path d="M22,5.7l-4.6-3.9l-1.3,1.5l4.6,3.9L22,5.7z M7.9,3.4L6.6,1.9L2,5.7l1.3,1.5L7.9,3.4z M12,4c-5,0-9,4-9,9c0,5,4,9,9,9c5,0,9-4,9-9C21,8,17,4,12,4z M12,20c-3.9,0-7-3.1-7-7c0-3.9,3.1-7,7-7s7,3.1,7,7C19,16.9,15.9,20,12,20z M10.5,14.5l-2.1-2.1l-1.1,1.1l3.2,3.2l6-6l-1.1-1.1L10.5,14.5z"/></g>
<g id="android"><path d="M6,18c0,0.6,0.4,1,1,1h1v3.5C8,23.3,8.7,24,9.5,24c0.8,0,1.5-0.7,1.5-1.5V19h2v3.5c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5V19h1c0.6,0,1-0.4,1-1V8H6V18z M3.5,8C2.7,8,2,8.7,2,9.5v7C2,17.3,2.7,18,3.5,18C4.3,18,5,17.3,5,16.5v-7C5,8.7,4.3,8,3.5,8z M20.5,8C19.7,8,19,8.7,19,9.5v7c0,0.8,0.7,1.5,1.5,1.5c0.8,0,1.5-0.7,1.5-1.5v-7C22,8.7,21.3,8,20.5,8z M15.5,2.2l1.3-1.3c0.2-0.2,0.2-0.5,0-0.7c-0.2-0.2-0.5-0.2-0.7,0l-1.5,1.5C13.9,1.2,13,1,12,1c-1,0-1.9,0.2-2.7,0.6L7.9,0.1C7.7,0,7.3,0,7.1,0.1C7,0.3,7,0.7,7.1,0.9l1.3,1.3C7,3.3,6,5,6,7h12C18,5,17,3.2,15.5,2.2z M10,5H9V4h1V5z M15,5h-1V4h1V5z"/></g>
<g id="announcement"><path d="M20,2H4C2.9,2,2,2.9,2,4l0,18l4-4h14c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2z M13,11h-2V5h2V11z M13,15h-2v-2h2V15z"/></g>
<g id="apps"><path d="M4,8h4V4H4V8z M10,20h4v-4h-4V20z M4,20h4v-4H4V20z M4,14h4v-4H4V14z M10,14h4v-4h-4V14z M16,4v4h4V4H16z M10,8h4V4h-4V8z M16,14h4v-4h-4V14z M16,20h4v-4h-4V20z"/></g>
<g id="archive"><path d="M20.5,5.2l-1.4-1.7C18.9,3.2,18.5,3,18,3H6C5.5,3,5.1,3.2,4.8,3.5L3.5,5.2C3.2,5.6,3,6,3,6.5V19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V6.5C21,6,20.8,5.6,20.5,5.2z M12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5z M5.1,5l0.8-1h12l0.9,1H5.1z"/></g>
<g id="arrow-back"><path d="M20,11H7.8l5.6-5.6L12,4l-8,8l8,8l1.4-1.4L7.8,13H20V11z"/></g>
<g id="arrow-drop-down"><polygon points="7,10 12,15 17,10 "/></g>
<g id="arrow-drop-down-circle"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,14l-4-4h8L12,14z"/></g>
<g id="arrow-drop-up"><polygon points="7,14 12,9 17,14 "/></g>
<g id="arrow-forward"><polygon points="12,4 10.6,5.4 16.2,11 4,11 4,13 16.2,13 10.6,18.6 12,20 20,12 "/></g>
<g id="aspect-ratio"><path d="M19,12h-2v3h-3v2h5V12z M7,9h3V7H5v5h2V9z M21,3H3C1.9,3,1,3.9,1,5v14c0,1.1,0.9,2,2,2h18c1.1,0,2-0.9,2-2V5C23,3.9,22.1,3,21,3z M21,19H3V5h18V19z"/></g>
<g id="assessment"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M9,17H7v-7h2V17z M13,17h-2V7h2V17z M17,17h-2v-4h2V17z"/></g>
<g id="assignment"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M14,17H7v-2h7V17z M17,13H7v-2h10V13z M17,9H7V7h10V9z"/></g>
<g id="assignment-ind"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,7c1.7,0,3,1.3,3,3c0,1.7-1.3,3-3,3c-1.7,0-3-1.3-3-3C9,8.3,10.3,7,12,7z M18,19H6v-1.4c0-2,4-3.1,6-3.1s6,1.1,6,3.1V19z"/></g>
<g id="assignment-late"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g>
<g id="assignment-return"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1c-0.6,0-1-0.4-1-1S11.4,3,12,3z M16,15h-4v3l-5-5l5-5v3h4V15z"/></g>
<g id="assignment-returned"><path d="M19,3h-4.2c-0.4-1.2-1.5-2-2.8-2c-1.3,0-2.4,0.8-2.8,2H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,3c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.4,3,12,3z M12,18l-5-5h3V9h4v4h3L12,18z"/></g>
<g id="attachment"><path d="M7.5,18c-3,0-5.5-2.5-5.5-5.5S4.5,7,7.5,7H18c2.2,0,4,1.8,4,4s-1.8,4-4,4H9.5C8.1,15,7,13.9,7,12.5S8.1,10,9.5,10H17v1.5H9.5c-0.6,0-1,0.4-1,1s0.4,1,1,1H18c1.4,0,2.5-1.1,2.5-2.5S19.4,8.5,18,8.5H7.5c-2.2,0-4,1.8-4,4s1.8,4,4,4H17V18H7.5z"/></g>
<g id="backspace"><path d="M22,3H7C6.3,3,5.8,3.3,5.4,3.9L0,12l5.4,8.1C5.8,20.6,6.3,21,7,21h15c1.1,0,2-0.9,2-2V5C24,3.9,23.1,3,22,3z M19,15.6L17.6,17L14,13.4L10.4,17L9,15.6l3.6-3.6L9,8.4L10.4,7l3.6,3.6L17.6,7L19,8.4L15.4,12L19,15.6z"/></g>
<g id="backup"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M14,13v4h-4v-4H7l5-5l5,5H14z"/></g>
<g id="block"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M4,12c0-4.4,3.6-8,8-8c1.8,0,3.5,0.6,4.9,1.7L5.7,16.9C4.6,15.5,4,13.8,4,12z M12,20c-1.8,0-3.5-0.6-4.9-1.7L18.3,7.1C19.4,8.5,20,10.2,20,12C20,16.4,16.4,20,12,20z"/></g>
<g id="book"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g>
<g id="bookmark"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z"/></g>
<g id="bookmark-outline"><path d="M17,3H7C5.9,3,5,3.9,5,5l0,16l7-3l7,3V5C19,3.9,18.1,3,17,3z M17,18l-5-2.2L7,18V5h10V18z"/></g>
<g id="bug-report"><path d="M20,8h-2.8c-0.5-0.8-1.1-1.5-1.8-2L17,4.4L15.6,3l-2.2,2.2C13,5.1,12.5,5,12,5s-1,0.1-1.4,0.2L8.4,3L7,4.4L8.6,6C7.9,6.5,7.3,7.2,6.8,8H4v2h2.1C6,10.3,6,10.7,6,11v1H4v2h2v1c0,0.3,0,0.7,0.1,1H4v2h2.8c1,1.8,3,3,5.2,3s4.2-1.2,5.2-3H20v-2h-2.1c0.1-0.3,0.1-0.7,0.1-1v-1h2v-2h-2v-1c0-0.3,0-0.7-0.1-1H20V8z M14,16h-4v-2h4V16z M14,12h-4v-2h4V12z"/></g>
<g id="cached"><path d="M19,8l-4,4h3c0,3.3-2.7,6-6,6c-1,0-2-0.3-2.8-0.7l-1.5,1.5C9,19.5,10.4,20,12,20c4.4,0,8-3.6,8-8h3L19,8z M6,12c0-3.3,2.7-6,6-6c1,0,2,0.3,2.8,0.7l1.5-1.5C15,4.5,13.6,4,12,4c-4.4,0-8,3.6-8,8H1l4,4l4-4H6z"/></g>
<g id="cancel"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M17,15.6L15.6,17L12,13.4L8.4,17L7,15.6l3.6-3.6L7,8.4L8.4,7l3.6,3.6L15.6,7L17,8.4L13.4,12L17,15.6z"/></g>
<g id="check"><polygon points="9,16.2 4.8,12 3.4,13.4 9,19 21,7 19.6,5.6 "/></g>
<g id="check-box"><path d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g>
<g id="check-box-blank"><path d="M19,3H5C3.9,3,3,3.9,3,5l0,14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z"/></g>
<g id="check-box-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M19,19L5,19V5h10V3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-8h-2V19z"/></g>
<g id="check-box-outline-blank"><path d="M19,5v14L5,19V5H19 M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3L19,3z"/></g>
<g id="check-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M10,17l-5-5l1.4-1.4l3.6,3.6l7.6-7.6L19,8L10,17z"/></g>
<g id="check-circle-blank"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z"/></g>
<g id="check-circle-outline"><path d="M7.9,10.1l-1.4,1.4L11,16L21,6l-1.4-1.4L11,13.2L7.9,10.1z M20,12c0,4.4-3.6,8-8,8s-8-3.6-8-8s3.6-8,8-8c0.8,0,1.5,0.1,2.2,0.3l1.6-1.6C14.6,2.3,13.3,2,12,2C6.5,2,2,6.5,2,12s4.5,10,10,10s10-4.5,10-10H20z"/></g>
<g id="check-circle-outline-blank"><path d="M12,2C6.5,2,2,6.5,2,12s4.5,10,10,10c5.5,0,10-4.5,10-10S17.5,2,12,2z M12,20c-4.4,0-8-3.6-8-8s3.6-8,8-8c4.4,0,8,3.6,8,8S16.4,20,12,20z"/></g>
<g id="chevron-left"><polygon points="15.4,7.4 14,6 8,12 14,18 15.4,16.6 10.8,12 "/></g>
<g id="chevron-right"><polygon points="10,6 8.6,7.4 13.2,12 8.6,16.6 10,18 16,12 "/></g>
<g id="class"><path d="M18,2H6C4.9,2,4,2.9,4,4v16c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2z M6,4h5v8l-2.5-1.5L6,12V4z"/></g>
<g id="clear"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "/></g>
<g id="close"><polygon points="19,6.4 17.6,5 12,10.6 6.4,5 5,6.4 10.6,12 5,17.6 6.4,19 12,13.4 17.6,19 19,17.6 13.4,12 "/></g>
<g id="cloud"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z"/></g>
<g id="cloud-circle"><path d="M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10c5.5,0,10-4.5,10-10C22,6.5,17.5,2,12,2z M16.5,16c0,0-8.5,0-8.5,0c-1.7,0-3-1.3-3-3s1.3-3,3-3c0,0,0.1,0,0.1,0c0.4-1.7,2-3,3.9-3c2.2,0,4,1.8,4,4h0.5c1.4,0,2.5,1.1,2.5,2.5C19,14.9,17.9,16,16.5,16z"/></g>
<g id="cloud-done"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M10,17l-3.5-3.5l1.4-1.4l2.1,2.1L15.2,9l1.4,1.4L10,17z"/></g>
<g id="cloud-download"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6C9.1,4,6.6,5.6,5.4,8C2.3,8.4,0,10.9,0,14c0,3.3,2.7,6,6,6h13c2.8,0,5-2.2,5-5C24,12.4,21.9,10.2,19.4,10z M17,13l-5,5l-5-5h3V9h4v4H17z"/></g>
<g id="cloud-off"><path d="M19.4,10c-0.7-3.4-3.7-6-7.4-6c-1.5,0-2.9,0.4-4,1.2l1.5,1.5C10.2,6.2,11.1,6,12,6c3,0,5.5,2.5,5.5,5.5V12H19c1.7,0,3,1.3,3,3c0,1.1-0.6,2.1-1.6,2.6l1.5,1.5c1.3-0.9
View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

View raw

(Sorry about that, but we can’t show files that are this big right now.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment