Merge branch 'Polymer-UI'

This commit is contained in:
Thaum
2014-11-30 08:33:12 +00:00
1230 changed files with 395376 additions and 335 deletions

2
.codio
View File

@@ -3,7 +3,7 @@
// Run button configuration
"commands": {
"Run Meteor": "cd rpg-docs \n meteor"
"Run Meteor": "cd rpg-docs \n METEOR_OFFLINE_CATALOG=1 meteor run"
},
// Preview button configuration

View File

@@ -37,3 +37,8 @@ Packages used
* aldeed:autoform
* Automatically generates bootstrap forms for collection2 Schemas.
* [github](https://github.com/aldeed/meteor-autoform)
************
To Speed up builds when you know you wont need online package checking use
METEOR_OFFLINE_CATALOG=1

View File

@@ -1 +1,5 @@
local
local
local

View File

@@ -4,7 +4,6 @@
# but you can also edit it by hand.
meteor-platform
autopublish
insecure
iron:router
accounts-password
@@ -16,5 +15,5 @@ cw4gn3r:jquery-event-drag
underscore
aldeed:collection2
aldeed:autoform
mike:mocha
multiply:iron-router-progress

View File

@@ -5,9 +5,7 @@ accounts-ui@1.1.3
aldeed:autoform@3.2.0
aldeed:collection2@2.2.0
aldeed:simple-schema@1.0.3
amplify@1.0.0
application-configuration@1.0.3
autopublish@1.0.1
autoupdate@1.1.3
base64@1.0.1
binary-heap@1.0.1
@@ -16,6 +14,7 @@ blaze@2.0.3
boilerplate-generator@1.0.1
callback-hook@1.0.1
check@1.0.2
coffeescript@1.0.4
ctl-helper@1.0.4
ctl@1.0.2
cw4gn3r:jquery-event-drag@2.2.0
@@ -49,13 +48,13 @@ localstorage@1.0.1
logging@1.0.5
meteor-platform@1.2.0
meteor@1.1.3
mike:mocha@0.4.4
minifiers@1.1.2
minimongo@1.0.5
mobile-status-bar@1.0.1
mongo-livedata@1.0.6
mongo@1.0.8
mrt:moment@2.6.0
multiply:iron-router-progress@1.0.0
npm-bcrypt@0.7.7
observe-sequence@1.0.3
ordered-dict@1.0.1
@@ -76,8 +75,5 @@ tracker@1.0.3
ui@1.0.4
underscore@1.0.1
url@1.0.2
velocity:core@1.0.0-rc.1
velocity:html-reporter@0.3.0-rc.3
velocity:shim@0.0.1
webapp-hashing@1.0.1
webapp@1.1.4

View File

@@ -3,43 +3,48 @@ Characters = new Meteor.Collection("characters");
Schemas.Character = new SimpleSchema({
//strings
name: { type: String, defaultValue: "", trim: false},
alignment: { type: String, defaultValue: "", trim: false},
gender: { type: String, defaultValue: "", trim: false},
race: { type: String, defaultValue: "", trim: false},
name: { type: String, defaultValue: "", trim: false},
alignment: { type: String, defaultValue: "", trim: false},
gender: { type: String, defaultValue: "", trim: false},
race: { type: String, defaultValue: "", trim: false},
description:{ type: String, defaultValue: "", trim: false},
personality:{ type: String, defaultValue: "", trim: false},
ideals: { type: String, defaultValue: "", trim: false},
bonds: { type: String, defaultValue: "", trim: false},
flaws: { type: String, defaultValue: "", trim: false},
backstory: { type: String, defaultValue: "", trim: false},
notes: { type: String, defaultValue: "", trim: false},
ideals: { type: String, defaultValue: "", trim: false},
bonds: { type: String, defaultValue: "", trim: false},
flaws: { type: String, defaultValue: "", trim: false},
backstory: { type: String, defaultValue: "", trim: false},
notes: { type: String, defaultValue: "", trim: false},
//attributes
//ability scores
strength: {type: Schemas.Attribute},
dexterity: {type: Schemas.Attribute},
constitution: {type: Schemas.Attribute},
intelligence: {type: Schemas.Attribute},
wisdom: {type: Schemas.Attribute},
charisma: {type: Schemas.Attribute},
strength: {type: Schemas.Attribute},
dexterity: {type: Schemas.Attribute},
constitution: {type: Schemas.Attribute},
intelligence: {type: Schemas.Attribute},
wisdom: {type: Schemas.Attribute},
charisma: {type: Schemas.Attribute},
//stats
hitPoints: {type: Schemas.Attribute},
hitPoints: {type: Schemas.Attribute},
"hitPoints.add": {
type: [Schemas.Effect],
defaultValue: [
{name: "Constitution modifier for each level", calculation: "level * constitutionMod"}
]
},
experience: {type: Schemas.Attribute},
experience: {type: Schemas.Attribute},
proficiencyBonus: {type: Schemas.Attribute},
speed: {type: Schemas.Attribute},
weight: {type: Schemas.Attribute},
weightCarried: {type: Schemas.Attribute},
age: {type: Schemas.Attribute},
ageRate: {type: Schemas.Attribute},
armor: {type: Schemas.Attribute},
"proficiencyBonus.add": {
type: [Schemas.Effect],
defaultValue: [
{name: "Proficiency bonus by level", calculation: "floor(level / 4.1) + 2"}
]
},
speed: {type: Schemas.Attribute},
weight: {type: Schemas.Attribute},
age: {type: Schemas.Attribute},
ageRate: {type: Schemas.Attribute},
armor: {type: Schemas.Attribute},
"armor.add": {
type: [Schemas.Effect],
defaultValue: [
@@ -48,63 +53,63 @@ Schemas.Character = new SimpleSchema({
},
//resources
level1SpellSlots: {type: Schemas.Attribute},
level2SpellSlots: {type: Schemas.Attribute},
level3SpellSlots: {type: Schemas.Attribute},
level4SpellSlots: {type: Schemas.Attribute},
level5SpellSlots: {type: Schemas.Attribute},
level6SpellSlots: {type: Schemas.Attribute},
level7SpellSlots: {type: Schemas.Attribute},
level8SpellSlots: {type: Schemas.Attribute},
level9SpellSlots: {type: Schemas.Attribute},
ki: {type: Schemas.Attribute},
sorceryPoints: {type: Schemas.Attribute},
rages: {type: Schemas.Attribute},
superiorityDice: {type: Schemas.Attribute},
expertiseDice: {type: Schemas.Attribute},
level1SpellSlots: {type: Schemas.Attribute},
level2SpellSlots: {type: Schemas.Attribute},
level3SpellSlots: {type: Schemas.Attribute},
level4SpellSlots: {type: Schemas.Attribute},
level5SpellSlots: {type: Schemas.Attribute},
level6SpellSlots: {type: Schemas.Attribute},
level7SpellSlots: {type: Schemas.Attribute},
level8SpellSlots: {type: Schemas.Attribute},
level9SpellSlots: {type: Schemas.Attribute},
ki: {type: Schemas.Attribute},
sorceryPoints: {type: Schemas.Attribute},
rages: {type: Schemas.Attribute},
superiorityDice: {type: Schemas.Attribute},
expertiseDice: {type: Schemas.Attribute},
//hit dice
d6HitDice: {type: Schemas.Attribute},
d8HitDice: {type: Schemas.Attribute},
d10HitDice: {type: Schemas.Attribute},
d12HitDice: {type: Schemas.Attribute},
d6HitDice: {type: Schemas.Attribute},
d8HitDice: {type: Schemas.Attribute},
d10HitDice: {type: Schemas.Attribute},
d12HitDice: {type: Schemas.Attribute},
//vulnerabilities
acidMultiplier: {type: Schemas.Vulnerability},
bludgeoningMultiplier: {type: Schemas.Vulnerability},
coldMultiplier: {type: Schemas.Vulnerability},
fireMultiplier: {type: Schemas.Vulnerability},
forceMultiplier: {type: Schemas.Vulnerability},
lightningMultiplier: {type: Schemas.Vulnerability},
necroticMultiplier: {type: Schemas.Vulnerability},
piercingMultiplier: {type: Schemas.Vulnerability},
poisonMultiplier: {type: Schemas.Vulnerability},
psychicMultiplier: {type: Schemas.Vulnerability},
radiantMultiplier: {type: Schemas.Vulnerability},
slashingMultiplier: {type: Schemas.Vulnerability},
thunderMultiplier: {type: Schemas.Vulnerability},
acidMultiplier: {type: Schemas.Vulnerability},
bludgeoningMultiplier: {type: Schemas.Vulnerability},
coldMultiplier: {type: Schemas.Vulnerability},
fireMultiplier: {type: Schemas.Vulnerability},
forceMultiplier: {type: Schemas.Vulnerability},
lightningMultiplier: {type: Schemas.Vulnerability},
necroticMultiplier: {type: Schemas.Vulnerability},
piercingMultiplier: {type: Schemas.Vulnerability},
poisonMultiplier: {type: Schemas.Vulnerability},
psychicMultiplier: {type: Schemas.Vulnerability},
radiantMultiplier: {type: Schemas.Vulnerability},
slashingMultiplier: {type: Schemas.Vulnerability},
thunderMultiplier: {type: Schemas.Vulnerability},
//skills
//saves
strengthSave: {type: Schemas.Skill},
"strengthSave.ability": { type: String, defaultValue: "strength" },
strengthSave: {type: Schemas.Skill},
"strengthSave.ability": { type: String, defaultValue: "strength" },
dexteritySave: {type: Schemas.Skill},
"dexteritySave.ability": { type: String, defaultValue: "dexterity" },
dexteritySave: {type: Schemas.Skill},
"dexteritySave.ability": { type: String, defaultValue: "dexterity" },
constitutionSave:{type: Schemas.Skill},
"constitutionSave.ability": { type: String, defaultValue: "constitution" },
"constitutionSave.ability": { type: String, defaultValue: "constitution" },
intelligenceSave:{type: Schemas.Skill},
"intelligenceSave.ability": { type: String, defaultValue: "intelligence" },
wisdomSave: {type: Schemas.Skill},
"wisdomSave.ability": { type: String, defaultValue: "wisdom" },
wisdomSave: {type: Schemas.Skill},
"wisdomSave.ability": { type: String, defaultValue: "wisdom" },
charismaSave: {type: Schemas.Skill},
"charismaSave.ability": { type: String, defaultValue: "charisma" },
charismaSave: {type: Schemas.Skill},
"charismaSave.ability": { type: String, defaultValue: "charisma" },
//skill skills
@@ -221,7 +226,7 @@ Schemas.Character = new SimpleSchema({
//proficiencies
weaponsProficiencies: {
type: [Schemas.Proficiency],
type: [Schemas.Proficiency],
defaultValue: []
},
toolsProficiencies: {
@@ -229,7 +234,7 @@ Schemas.Character = new SimpleSchema({
defaultValue: []
},
languages: {
type: [Schemas.Proficiency],
type: [Schemas.Proficiency],
defaultValue: []
},
@@ -247,19 +252,30 @@ Characters.attachSchema(Schemas.Character);
//reactively remove expired effects
//this can be optimised a lot once clients can do projections
Characters.find({},{fields: {time: 1, expirations: 1}}).observe({
changed: function(character, oldCharacter){
Characters.find({},{fields: {time: 1, expirations: 1, features: 1}}).observe({
changed: function(character){
var currentTime = character.time;
_.each(character.expirations, function(expiration){
if(expiration.expiry <= currentTime){
pullEffect(character._id, expiration.stat, expiration.effectId);
pullExpiry(character._id, expiration._id);
var charId = character._id;
var stat = expiration.stat;
//remove expired effects
_.each(expiration.effectIds, function(effectId){
pullEffect(charId, stat, effectId);
});
//disable expired features
_.each(expiration.featureIds, function(featureId){
var feature = Characters.findOne({_id: charId, "features._id": featureId}, {fields: {features: 1}}).features[0];
feature.enabled = false;
Characters.update({_id: charId, "features._id": featureId}, {$set: {"features.$": feature}});
});
pullExpiry(charId, expiration._id);
}
})
});
}
});
var attributeBase = function(attribute){
var attributeBase = function(charId, attribute){
var value = 0;
//add all values in add array
_.each(attribute.add, function(effect){
@@ -285,10 +301,10 @@ var attributeBase = function(attribute){
return value;
}
//functions and calculated values.
//These functions can only rely on this._id since no other
//functions and calculated values.
//These functions can only rely on this._id since no other
//field is likely to be attached to all returned characters
Characters.helpers({
Characters.helpers({
//returns the value stored in the field requested
//will set up dependencies on just that field
getField : function(fieldName){
@@ -296,16 +312,16 @@ Characters.helpers({
fieldSelector[fieldName] = 1;
var char = Characters.findOne(this._id, {fields: fieldSelector});
var field = char[fieldName];
if(field === undefined){
console.log("no field ", fieldName, " exists for character ", char)
if(!field){
throw new Meteor.Error("getField failed",
"getField could not find field " + fieldName + " in character "+ char._id);
}
return field;
},
//returns the value of a field
fieldValue : function(fieldName){
if(!Schemas.Character.schema(fieldName)){
console.log("Character's schema does not contain a field called: " + fieldName);
return;
throw new Meteor.Error("Field not found", "Character's schema does not contain a field called: " + fieldName);
}
//duck typing to get the right value function
//.proficiency implies skill
@@ -320,7 +336,7 @@ Characters.helpers({
return this.getField(fieldName);
},
attributeValue: (function(){
attributeValue: (function(){
//store a private array of attributes we've visited without returning
//if we try to visit the same attribute twice before resolving its value
//we are in a dependency loop and need to GTFO
@@ -336,19 +352,21 @@ Characters.helpers({
//we can't visit it again unless it returns first
visitedAttributes.push(attributeName);
var charId = this._id;
var attribute = this.getField(attributeName);
//base value
var value = attributeBase(attribute);
value += attribute.adjustment;
//this attribute returns, pull it from the array, we may visit it again safely
visitedAttributes = _.without(visitedAttributes, attributeName);
try{
var charId = this._id;
var attribute = this.getField(attributeName);
//base value
var value = attributeBase(charId, attribute);
value += attribute.adjustment;
}finally{
//this attribute returns or fails, pull it from the array, we may visit it again safely
visitedAttributes = _.without(visitedAttributes, attributeName);
}
return value;
}
})(),
attributeBase: (function(){
attributeBase: (function(){
//store a private array of attributes we've visited without returning
//if we try to visit the same attribute twice before resolving its value
//we are in a dependency loop and need to GTFO
@@ -363,14 +381,15 @@ Characters.helpers({
//push this attribute to the list of visited attributes
//we can't visit it again unless it returns first
visitedAttributes.push(attributeName);
var charId = this._id;
var attribute = this.getField(attributeName);
//base value
var value = attributeBase(attribute);
//this attribute returns, pull it from the array, we may visit it again safely
visitedAttributes = _.without(visitedAttributes, attributeName);
try{
var charId = this._id;
var attribute = this.getField(attributeName);
//base value
var value = attributeBase(charId, attribute);
}finally{
//this attribute returns or fails, pull it from the array, we may visit it again safely
visitedAttributes = _.without(visitedAttributes, attributeName);
}
return value;
}
})(),
@@ -390,45 +409,46 @@ Characters.helpers({
//push this skill to the list of visited skills
//we can't visit it again unless it returns first
visitedSkills.push(skillName);
try{
var charId = this._id;
skill = this.getField(skillName);
//get the final value of the ability score
var ability = this.attributeValue(skill.ability);
var charId = this._id;
skill = this.getField(skillName);
//get the final value of the ability score
var ability = this.attributeValue(skill.ability);
//base modifier
var mod = +getMod(ability)
//base modifier
var mod = +getMod(ability)
//multiply proficiency bonus by largest value in proficiency array
var prof = this.proficiency(skill);
//multiply proficiency bonus by largest value in proficiency array
var prof = this.proficiency(skill);
//add multiplied proficiency bonus to modifier
mod += prof * this.attributeValue("proficiencyBonus");
//add multiplied proficiency bonus to modifier
mod += prof * this.attributeValue("proficiencyBonus");
//add all values in add array
_.each(skill.add, function(effect){
mod += evaluateEffect(charId, effect);
});
//add all values in add array
_.each(skill.add, function(effect){
mod += evaluateEffect(charId, effect);
});
//multiply all values in mul array
_.each(skill.mul, function(effect){
mod *= evaluateEffect(charId, effect);
});
//multiply all values in mul array
_.each(skill.mul, function(effect){
mod *= evaluateEffect(charId, effect);
});
//largest min
_.each(skill.min, function(effect){
var min = evaluateEffect(charId, effect);
mod = mod > min? mod : min;
});
//largest min
_.each(skill.min, function(effect){
var min = evaluateEffect(charId, effect);
mod = mod > min? mod : min;
});
//smallest max
_.each(skill.max, function(effect){
var max = evaluateEffect(charId, effect);
mod = mod < max? mod : max;
});
//done traversing the tree, this skill returns, pull it from the array
visitedSkills = _.without(visitedSkills, skillName);
//smallest max
_.each(skill.max, function(effect){
var max = evaluateEffect(charId, effect);
mod = mod < max? mod : max;
});
} finally{
//this skill returns or fails, pull it from the array
visitedSkills = _.without(visitedSkills, skillName);
}
return signedString(mod);
}
})(),
@@ -449,12 +469,12 @@ Characters.helpers({
return prof;
},
passiveSkill: function(skill){
if (_.isString(skill)){
skill = this.getField(skill);
passiveSkill: function(skillName){
if (_.isString(skillName)){
var skill = this.getField(skillName);
}
var charId = this._id
var mod = +this.skillMod(skill);
var mod = +this.skillMod(skillName);
var value = 10 + mod;
_.each(skill.passiveAdd, function(effect){
value += evaluateEffect(charId, effect);
@@ -485,4 +505,4 @@ Characters.helpers({
if(xp > 355000) return 20;
return 0;
}
});
});

View File

@@ -1,6 +1,6 @@
Schemas.Attribute = new SimpleSchema({
//the temporary shift of the attribute
//should be zero for most attributes after a long rest
//should be zero after reset
adjustment: {
type: Number,
defaultValue: 0
@@ -10,7 +10,12 @@ Schemas.Attribute = new SimpleSchema({
mul: { type: [Schemas.Effect], defaultValue: [] },
min: { type: [Schemas.Effect], defaultValue: [] },
max: { type: [Schemas.Effect], defaultValue: [] },
conditional:{ type: [Schemas.Effect], defaultValue: [] }
conditional:{ type: [Schemas.Effect], defaultValue: [] },
reset: {
type: String,
defaultValue: "longRest",
allowedValues: ["longRest", "shortRest"]
}
});
//note that to make an invulnerability add a new max of zero value
@@ -24,4 +29,9 @@ Schemas.Vulnerability = new SimpleSchema({
mul: { type: [Schemas.Effect], defaultValue: [] },
min: { type: [Schemas.Effect], defaultValue: [{name: "Resistance doesn't stack", value: 0.5}] },
max: { type: [Schemas.Effect], defaultValue: [{name: "Vulnerability doesn't stack", value: 2}] },
});
reset: {
type: String,
defaultValue: "longRest",
allowedValues: ["longRest", "shortRest"]
}
});

View File

@@ -26,6 +26,6 @@ Schemas.Effect = new SimpleSchema({
type: {
type: String,
defaultValue: "default",
allowedValues: ["default", "class", "race", "feat", "equippedMagic", "equippedMundane", "external"]
allowedValues: ["default", "inate", "class", "race", "feat", "equippedMagic", "equippedMundane", "external"]
}
});
});

View File

@@ -6,7 +6,8 @@ Schemas.Expiration = new SimpleSchema({
autoValue: function(){
if(!this.isSet) return Random.id();
}},
stat: { type: String },
effectId: { type: String, regEx: SimpleSchema.RegEx.Id },
expiry: { type: Number }
});
stat: { type: String },
effectIds: { type: [String], regEx: SimpleSchema.RegEx.Id },
featureIds:{ type: [String], regEx: SimpleSchema.RegEx.Id },
expiry: { type: Number }
});

View File

@@ -1,10 +1,22 @@
Schemas.Feature = new SimpleSchema({
_id: {type: String, regEx: SimpleSchema.RegEx.Id},
name: {type: String},
description:{type: String},
buffs: {type: [Schemas.Buff], optional: true},
enabled: {type: Boolean},
expires: {type: Number, optional: true},
duration: {type: Number, optional: true},
uses: {type: Number, min: 0, optional: true},
});
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
autoValue: function(){
if(!this.isSet) return Random.id();
}
},
name: {type: String},
description:{type: String},
source: {type: String},
buffs: {type: [Schemas.Buff], defaultValue: []},
enabled: {type: Boolean, defaultValue: false},
duration: {type: Number, optional: true},
uses: {type: Number, min: 0, optional: true},
maxUses: {type: Number, min: 0, optional: true},
reset: {
type: String,
optional: true,
allowedValues: ["longRest", "shortRest"]
}
});

View File

@@ -1,20 +1,23 @@
Router.configure({
loadingTemplate: 'loading'
});
Router.map( function () {
this.route('home',
this.route('home',
{
path: '/',
waitOn: function(){
return Meteor.subscribe("characterList", Meteor.userId());
},
data: {
data: {
characters: function(){
return Characters.find({}, {fields: {_id: 1}});
}
}
});
this.route('character', {
this.route('characterSheet', {
path: '/character/:_id',
notFoundTemplate: 'characterNotFound',
waitOn: function(){
return Meteor.subscribe("singleCharacter", this.params._id, Meteor.userId());
},
@@ -26,7 +29,6 @@ Router.map( function () {
this.route('inventory', {
path: '/inventory/:_id',
notFoundTemplate: 'characterNotFound',
data: {
containers: function() {
var containers = Containers.find({owner: data._id}, {fields: {_id: 1}});
@@ -38,10 +40,13 @@ Router.map( function () {
this.route('item', {
path: '/item/:_id',
notFoundTemplate: 'itemNotFound',
data: function() {
var data = Items.findOne({_id: this.params._id});
return data;
}
});
});
this.route('loading', {
path: '/loading'
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
.red {
background-color: #F44336;
}
.pink {
background-color: #E91E63;
}
.purple {
background-color: #9C27B0;
}
.deep-purple {
background-color: #673AB7;
}
.indigo {
background-color: #3F51B5;
}
.blue {
background-color: #2196F3;
}
.light-blue {
background-color: #03A9F4;
}
.cyan {
background-color: #00BCD4;
}
.teal {
background-color: #009688;
}
.green {
background-color: #4CAF50;
}
.light-green {
background-color: #8BC34A;
}
.lime {
background-color: #CDDC39;
}
.yellow {
background-color: #FFEB3B;
}
.amber {
background-color: #FFC107;
}
.orange {
background-color: #FF9800;
}
.deep-orange {
background-color: #FF5722;
}
.brown {
background-color: #795548;
}
.grey {
background-color: #9E9E9E;
}
.blue-grey {
background-color: #607D8B;
}

View File

@@ -0,0 +1,80 @@
root {
display: block;
}
body {
font-family: 'Roboto', 'Helvetica Neue', Helvetica, Arial;
margin: 0;
overflow-x: hidden;
}
body.core-narrow {
padding: 8px;
}
.calculatedValue {
color: #021C33;
font-weight: bold;
}
* {
box-sizing: border-box;
}
td {
padding: 0;
}
table {
border-spacing: 0;
}
hr {
background-color: #444;
opacity: 0.12;
border-width: 0;
color: #444;
height: 1px;
line-height: 0;
margin: 0 -16px;
text-align: center;
}
paper-button {
font-size: 14px;
font-weight: 400;
text-transform: uppercase;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.010;
}
.listRow {
height: 32px;
}
.card {
width: 148px;
margin: 4px;
padding: 16px;
font-size: 14px;
border-radius: 2px;
background-color: white;
}
.card.double {
width: 304px;
}
.card paper-button {
font-size: 14px;
letter-spacing: 0.01em;
}
.grey-background, body {
background-color: #E0E0E0;
}
.center {
text-align: center;
}

View File

@@ -0,0 +1,99 @@
.display2 {
font-size: 45px;
font-weight: 400;
color: #000;
color: rgba(0,0,0,0.54);
letter-spacing: 0;
}
.white-text .display2{
color: rgba(255,255,255,0.54);
}
.display1 {
font-size: 34px;
font-weight: 400;
color: #000;
color: rgba(0,0,0,0.54);
letter-spacing: 0;
}
.white-text .display1{
color: rgba(255,255,255,0.54);
}
h1, .headline {
font-size: 24px;
font-weight: 400;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0;
}
.white-text h1, .white-text .headline{
color: rgba(255,255,255,0.87);
}
h2, .title {
font-size: 20px;
font-weight: 500;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.005em;
}
.white-text h2{
color: rgba(255,255,255,0.87);
}
h3, .subhead {
font-size: 16px;
font-weight: 400;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.010em;
}
.white-text h3, .white-text .subhead{
color: rgba(255,255,255,0.87);
}
.body2 {
font-size: 14px;
font-weight: 500;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.010em;
}
.white-text .body2{
color: rgba(255,255,255,0.87);
}
p, .body1, body {
font-size: 14px;
font-weight: 400;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.010em;
}
.white-text p{
color: rgba(255,255,255,0.87);
}
.caption{
font-size: 12px;
font-weight: 400;
color: #000;
color: rgba(0,0,0,0.54);
letter-spacing: 0.020em;
}
.white-text .caption{
color: rgba(255,255,255,0.54);
}

View File

@@ -1,4 +1,22 @@
#stats{
#stats {
padding: 4px;
}
#stats, #stats .abilityFlex, #stats .statsFlex{
display: flex;
justify-content: space-around;
justify-content: center;
align-items: flex-start;
flex-wrap: wrap;
}
#stats .abilityFlex{
flex-basis: 642px;
flex-grow: 1;
flex-shrink: 1;
}
#stats .statsFlex{
min-width: 152px;
flex-basis: 0px;
flex-grow: 1;
}

View File

@@ -1,80 +1,84 @@
<template name="stats">
<div id="stats">
<div>
<div id="abilities">
{{> bigAbilities}}
</div>
<div id="savesAndSkills">
{{> skills}}
</div>
<div class="abilityFlex">
{{> abilityCards}}
</div>
<div>
<div id="armor">
{{attributeValue "armor"}}
</div>
<div id="initiative">
{{attributeValue "initiative"}}
</div>
<div id="proficiencyBonus">
{{attributeValue "proficiencyBonus"}}
</div>
<div id="speed">
{{attributeValue "speed"}}
</div>
<div id="passivePerception">
{{passiveSkill "perception"}}
</div>
<div id="hitDice">
{{> hitDice "d6HitDice"}}
{{> hitDice "d8HitDice"}}
{{> hitDice "d10HitDice"}}
{{> hitDice "d12HitDice"}}
</div>
<div id="spellSlots">
{{# if canCast}}
{{> spellSlots}}
{{/if}}
</div>
<div id="rages">
{{# if attributeBase "rages"}}
{{attributeValue "rages"}}/{{attributeBase "rages"}} rages
{{/if}}
</div>
<div id="sorceryPoints">
{{# if attributeBase "sorceryPoints"}}
{{attributeValue "sorceryPoints"}}/{{attributeBase "sorceryPoints"}} Sorcery Points
{{/if}}
</div>
<div id="expertiseDice">
{{# if attributeBase "expertiseDice"}}
{{attributeValue "expertiseDice"}}/{{attributeBase "expertiseDice"}} Expertise Dice
{{/if}}
</div>
<div id="superiorityDice">
{{# if attributeBase "superiorityDice"}}
{{attributeValue "superiorityDice"}}/{{attributeBase "superiorityDice"}} Superiority Dice
{{/if}}
</div>
<div class="statsFlex">
<paper-shadow class="card" id="armor">
<h1>{{attributeValue "armor"}}</h1>
<p class="caption">Armor</p>
</paper-shadow>
<paper-shadow class="card" id="initiative">
<h1>{{skillMod "initiative"}}</h1>
<p class="caption">Initiative</p>
</paper-shadow>
<paper-shadow class="card" id="proficiencyBonus">
<h1>{{attributeValue "proficiencyBonus"}}</h1>
<p class="caption">Proficiency Bonus</p>
</paper-shadow>
<paper-shadow class="card" id="speed">
<h1>{{attributeValue "speed"}}</h1>
<p class="caption">Speed</p>
</paper-shadow>
<paper-shadow class="card" id="passivePerception">
<h1>{{passiveSkill "perception"}}</h1>
<p class="caption">Passive Perception</p>
</paper-shadow>
<paper-shadow class="card" id="hitDice">
<h1>{{> hitDice hitDice="d6HitDice" d="6"}}</h1>
<h1>{{> hitDice hitDice="d8HitDice" d="8"}}</h1>
<h1>{{> hitDice hitDice="d10HitDice" d="10"}}</h1>
<h1>{{> hitDice hitDice="d12HitDice" d="12"}}</h1>
<p class="caption">Hit Dice</p>
</paper-shadow>
{{# if canCast}}
<paper-shadow class="card" id="spellSlots">
<h1>{{> spellSlots}}</h1>
<p class="caption">Spell Slots</p>
</paper-shadow>
{{/if}}
{{# if attributeBase "rages"}}
<paper-shadow class="card" id="rages">
<h1>{{attributeValue "rages"}}</h1>
<p class="caption">rages</p>
</paper-shadow>
{{/if}}
{{# if attributeBase "sorceryPoints"}}
<paper-shadow class="card" id="sorceryPoints">
<h1>{{attributeValue "sorceryPoints"}}</h1>
<p class="caption">Sorcery Points</p>
</paper-shadow>
{{/if}}
{{# if attributeBase "expertiseDice"}}
<paper-shadow class="card" id="expertiseDice">
<h1>{{attributeValue "expertiseDice"}}</h1>
<p class="caption">Expertise Dice</p>
</paper-shadow>
{{/if}}
{{# if attributeBase "superiorityDice"}}
<paper-shadow class="card" id="superiorityDice">
<h1>{{attributeValue "superiorityDice"}}</h1>
<p class="caption">Superiority Dice</p>
</paper-shadow>
{{/if}}
</div>
</div>
</template>
<template name="hitDice">
{{# if ../attributeBase hitDice}}
<div id={{hitDice}}>
{{../attributeValue hitDice}}/{{../attributeBase hitDice}}
</div>
{{../attributeValue hitDice}}d{{d}} + {{../abilityMod "constitution"}}
{{/if}}
</template>
<template name="spellSlots">
{{attributevalue "level1SpellSlots"}}
{{attributevalue "level2SpellSlots"}}
{{attributevalue "level3SpellSlots"}}
{{attributevalue "level4SpellSlots"}}
{{attributevalue "level5SpellSlots"}}
{{attributevalue "level6SpellSlots"}}
{{attributevalue "level7SpellSlots"}}
{{attributevalue "level8SpellSlots"}}
{{attributevalue "level9SpellSlots"}}
</template>
{{attributeValue "level1SpellSlots"}}
{{attributeValue "level2SpellSlots"}}
{{attributeValue "level3SpellSlots"}}
{{attributeValue "level4SpellSlots"}}
{{attributeValue "level5SpellSlots"}}
{{attributeValue "level6SpellSlots"}}
{{attributeValue "level7SpellSlots"}}
{{attributeValue "level8SpellSlots"}}
{{attributeValue "level9SpellSlots"}}
</template>

View File

@@ -0,0 +1,30 @@
.card.double {
display: flex;
}
.card.double > div{
vertical-align: top;
padding: 16px;
}
.abilityScore {
width: 70px;
text-align: center;
background-color: #D50000;
padding: 16px;
}
.abilityFlex .card {
padding: 0;
}
.abilityCardRight {
flex-grow: 1;
}
.abilityCardRight hr{
margin: 8px -16px;
}
.abilityCardRight h1{
margin-bottom: 8px;
}

View File

@@ -0,0 +1,110 @@
<template name="abilityCards">
{{> strengthCard}}
{{> dexterityCard}}
{{> constitutionCard}}
{{> intelligenceCard}}
{{> wisdomCard}}
{{> charismaCard}}
</template>
<template name="strengthCard">
<paper-shadow class="card double">
<div class="abilityScore red white-text">
<h1 class="display1">{{attributeValue "strength"}}</h1>
<h2>{{abilityMod "strength"}}</h2>
</div>
<div class="abilityCardRight">
<h1>Strength</h1>
{{> skillRow name="Save" skill="strengthSave"}}
<hr>
{{> skillRow name="Athletics" skill="athletics"}}
</div>
</paper-shadow>
</template>
<template name="dexterityCard">
<paper-shadow class="card double">
<div class="abilityScore green white-text">
<h1 class="display1">{{attributeValue "dexterity"}}</h1>
<h2>{{abilityMod "dexterity"}}</h2>
</div>
<div class="abilityCardRight">
<h1>Dexterity</h1>
{{> skillRow name="Save" skill="dexteritySave"}}
<hr>
{{> skillRow name="Acrobatics" skill="acrobatics"}}
{{> skillRow name="Sleight of Hand" skill="sleightOfHand"}}
{{> skillRow name="Stealth" skill="stealth"}}
</div>
</paper-shadow>
</template>
<template name="constitutionCard">
<paper-shadow class="card double">
<div class="abilityScore deep-orange white-text">
<h1 class="display1">{{attributeValue "constitution"}}</h1>
<h2>{{abilityMod "constitution"}}</h2>
</div>
<div class="abilityCardRight">
<h1>Constitution</h1>
{{> skillRow name="Save" skill="constitutionSave"}}
<hr>
</div>
</paper-shadow>
</template>
<template name="intelligenceCard">
<paper-shadow class="card double">
<div class="abilityScore indigo white-text">
<h1 class="display1">{{attributeValue "intelligence"}}</h1>
<h2>{{abilityMod "intelligence"}}</h2>
</div>
<div class="abilityCardRight">
<h1>Intelligence</h1>
{{> skillRow name="Save" skill="intelligenceSave"}}
<hr>
{{> skillRow name="Arcana" skill="arcana"}}
{{> skillRow name="History" skill="history"}}
{{> skillRow name="Investigation" skill="investigation"}}
{{> skillRow name="Nature" skill="nature"}}
{{> skillRow name="Religion" skill="religion"}}
</div>
</paper-shadow>
</template>
<template name="wisdomCard">
<paper-shadow class="card double">
<div class="abilityScore purple white-text">
<h1 class="display1">{{attributeValue "wisdom"}}</h1>
<h2>{{abilityMod "wisdom"}}</h2>
</div>
<div class="abilityCardRight">
<h1>Wisdom</h1>
{{> skillRow name="Save" skill="wisdomSave"}}
<hr>
{{> skillRow name="Animal Handling" skill="animalHandling"}}
{{> skillRow name="Insight" skill="insight"}}
{{> skillRow name="Medicine" skill="medicine"}}
{{> skillRow name="Perception" skill="perception"}}
{{> skillRow name="Survival" skill="survival"}}
</div>
</paper-shadow>
</template>
<template name="charismaCard">
<paper-shadow class="card double">
<div class="abilityScore pink white-text">
<h1 class="display1">{{attributeValue "charisma"}}</h1>
<h2>{{abilityMod "charisma"}}</h2>
</div>
<div class="abilityCardRight">
<h1>Charisma</h1>
{{> skillRow name="Save" skill="charismaSave"}}
<hr>
{{> skillRow name="Deception" skill="deception"}}
{{> skillRow name="Intimidation" skill="intimidation"}}
{{> skillRow name="Performance" skill="performance"}}
{{> skillRow name="Persuasion" skill="persuasion"}}
</div>
</paper-shadow>
</template>

View File

@@ -1,11 +1,35 @@
#characterSheetTabs {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: flex-start;
paper-tabs, core-toolbar {
background-color: #795548;
color: #fff;
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.2);
}
.characterTab {
flex-grow: 1;
min-width: 100px;
}
core-toolbar paper-tabs {
box-shadow: none;
}
paper-tabs[noink][nobar] paper-tab.core-selected {
color: #fff;
}
::shadow #selectionBar, #onRadio {
background-color: #d50000;
}
::shadow #ink {
color: #b22 !important;
}
paper-tabs.transparent-brown {
background-color: transparent;
color: #795548;
box-shadow: none;
}
paper-tabs.transparent-brown::shadow #selectionBar {
background-color: #795548;
}
paper-tabs.transparent-brown paper-tab::shadow #ink {
color: #795548;
}

View File

@@ -1,19 +1,19 @@
<template name="characterSheet">
<div id="characterHeader">
{{> characterName}}
{{> healthBar}}
<div id="characterSheetTabs">
<div id="statsTab" class="characterTab">Stats</div>
<div id="featuresTab" class="characterTab">Features</div>
<div id="personaTab" class="characterTab">Persona</div>
<div id="inventoryTab" class="characterTab">Inventory</div>
{{#if canCast}}
<div id="spellsTab" class="characterTab">Spellbook</div>
{{/if}}
<div id="journalTab" class="characterTab">Journal</div>
</div>
</div>
<div id="characterDetails">
{{Template.dynamic template=getTab}}
</div>
</template>
<paper-tabs id="characterSheetTabs" scrollable="true" selected={{selectedTab}}>
<paper-tab>Stats</paper-tab>
<paper-tab>Features</paper-tab>
<paper-tab>Inventory</paper-tab>
<paper-tab>Spellbook</paper-tab>
<paper-tab>Persona</paper-tab>
<paper-tab>Journal</paper-tab>
</paper-tabs>
<core-animated-pages selected={{selectedTab}} transitions="slide-from-right">
<div>{{> stats}}</div>
<div>features</div>
<div>inventory</div>
<div>spellBook</div>
<div>persona</div>
<div>journal</div>
</core-animated-pages>
</template>

View File

@@ -1,34 +1,35 @@
Template.characterSheet.created = function(){
Template.instance().tab = new ReactiveVar("characterStats")
Template.instance().selectedTab = new ReactiveVar(0)
}
Template.characterSheet.rendered = function(){
var observer = new ObjectObserver(document.querySelector('#characterSheetTabs'));
var instance = Template.instance();
observer.open(function(added, removed, changed, getOldValueFn) {
Object.keys(changed).forEach(function(property) {
if(property === "selected"){
var selected = changed[property];
instance.selectedTab.set(selected);
}
})
});
}
Template.characterSheet.helpers({
getTab: function(){
return Template.instance().tab.get();
selectedTab: function(){
return Template.instance().selectedTab.get();
},
});
var setTab = function(value){
Template.instance().tab.set(value);
}
Template.characterSheet.events({
"click #statsTab": function(){
setTab("stats");
},
"click #featuresTab": function(){
setTab("features");
},
"click #personaTab": function(){
setTab("persona");
},
"click #inventoryTab": function(){
setTab("inventory");
},
"click #spellsTab": function(){
setTab("spellbook");
},
"click #journalTab": function(){
setTab("journal");
},
})
})
/* requires the following templates
stats
features
persona
inventory
spellbook
journal
*/

View File

@@ -1,24 +1,34 @@
.skillRow {
height: 32px;
display: flex;
align-items: center;
}
.profIcon{
display: inline-block;
width: 23px;
height: 14px;
width: 40px;
height: 26px;
background-size: contain;
background-repeat: no-repeat;
position: relative;
top: 1px;
/*TODO fix the actual images and remove inversion*/
-webkit-filter: invert(100%);
opacity: 0.54;
}
table.skillTable td:nth-of-type(2) {
text-align: right;
.skillMod {
width: 20px;
text-align: right;
}
table.skillTable td:nth-of-type(3) {
padding-left: 8px;
.skillName, .skillMod{
display: inline-block;
vertical-align: top;
margin-right: 8px;
}
td.fail {
color: #AF0000;
.fail.skillMod {
color: #D50000;
}
.advantage{
@@ -35,4 +45,4 @@ td.fail {
td.conditionals::after{
content: "*";
}
}

View File

@@ -14,13 +14,13 @@
</template>
<template name="skillRow">
<tr>
<td><div class="profIcon" style="background-image: url(/png/profIcons/{{profIcon skill}})"></div></td>
<div class="subhead skillRow">
<div class="profIcon" style="background-image: url(/png/profIcons/{{profIcon skill}})"></div>
{{#if failSkill}}
<td class="fail">fail</td>
<div class="fail skillMod">fail</div>
{{else}}
<td class="{{advantage}}">{{../skillMod skill}}</td>
<div class="{{advantage}} skillMod">{{../skillMod skill}}</div>
{{/if}}
<td class={{conditionals}}>{{name}}</td>
</tr>
<div class="{{conditionals}} skillName">{{name}}</div>
</div>
</template>

View File

@@ -1,24 +0,0 @@
root {
display: block;
}
body {
font-family: sans-serif;
background: #201500;
overflow-x: hidden;
margin: 0px;
box-sizing: border-box;
}
.calculatedValue {
color: #021C33;
font-weight: bold;
}
* {
box-sizing: border-box;
}
h2 {
margin: 0;
}

View File

@@ -2,7 +2,7 @@
{{>loginButtons}}
<div>
{{# each characters}}
<li><a href="{{ pathFor 'character' }} ">{{_id}}</a> <button id="deleteChar">delete</button></li>
<li><a href="{{ pathFor 'characterSheet' }} ">{{_id}}</a> <button id="deleteChar">delete</button></li>
{{/each}}
</div>
<input id="addCharacter" type="button" value="Add Character">

View File

@@ -1,4 +1,11 @@
<head>
<title>RPG Docs</title>
<meta name="viewport" content="width=device-width initial-scale=1.0, user-scalable=no">
</head>
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/paper-tabs/paper-tabs.html">
<link rel="import" href="/bower_components/core-animated-pages/core-animated-pages.html">
<link rel="import" href="/bower_components/core-animated-pages/transitions/slide-from-right.html">
<link rel="import" href="/bower_components/paper-shadow/paper-shadow.html">
<link rel="import" href="/bower_components/paper-spinner/paper-spinner.html">
<link href='http://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic,900,900italic,100italic,100&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
</head>

View File

@@ -0,0 +1,7 @@
#iron-router-progress {
background-color : #D50000;
}
#iron-router-progress.spinner:before {
border-color : #D50000;
}

View File

@@ -0,0 +1,3 @@
<template name="loading">
loading
</template>

View File

@@ -0,0 +1,18 @@
{
"name": "context-free-parser",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"version": "0.5.1",
"homepage": "https://github.com/Polymer/context-free-parser",
"_release": "0.5.1",
"_resolution": {
"type": "version",
"tag": "0.5.1",
"commit": "d7079572e53a71ba052a04331e292c06768c39d2"
},
"_source": "git://github.com/Polymer/context-free-parser.git",
"_target": "^0.5.0",
"_originalSource": "Polymer/context-free-parser"
}

View File

@@ -0,0 +1,4 @@
context-free-parser
===================
See the [component landing page](http://polymer.github.io/context-free-parser) for more information.

View File

@@ -0,0 +1,8 @@
{
"name": "context-free-parser",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"version": "0.5.1"
}

View File

@@ -0,0 +1,49 @@
<!--
@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>

View File

@@ -0,0 +1,130 @@
/*
* @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);

View File

@@ -0,0 +1,34 @@
<!--
@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="../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,22 @@
<!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="../webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page></core-component-page>
</body>
</html>

View File

@@ -0,0 +1,16 @@
{
"name": "polymer-context-free-parser",
"version": "0.4.2",
"description": "context-free-parser scrapes source documentation data from input text or url.",
"main": "context-free-parser.js",
"repository": {
"type": "git",
"url": "ssh://git@github.com/Polymer/context-free-parser.git"
},
"author": "The Polymer Authors",
"license": "BSD",
"bugs": {
"url": "https://github.com/Polymer/context-free-parser/issues"
},
"homepage": "https://github.com/Polymer/context-free-parser"
}

View File

@@ -0,0 +1,28 @@
{
"name": "core-a11y-keys",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"devDependencies": {
"web-component-tester": "Polymer/web-component-tester#^1"
},
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"version": "0.5.1",
"homepage": "https://github.com/Polymer/core-a11y-keys",
"_release": "0.5.1",
"_resolution": {
"type": "version",
"tag": "0.5.1",
"commit": "235e4834483ee7ce04c14e53279826cd834dc22f"
},
"_source": "git://github.com/Polymer/core-a11y-keys.git",
"_target": "^0.5.0",
"_originalSource": "Polymer/core-a11y-keys"
}

View File

@@ -0,0 +1,4 @@
core-a11y-keys
==============
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-a11y-keys) for more information.

View File

@@ -0,0 +1,18 @@
{
"name": "core-a11y-keys",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"devDependencies": {
"web-component-tester": "Polymer/web-component-tester#^1"
},
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"version": "0.5.1"
}

View File

@@ -0,0 +1,335 @@
<!--
@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 = {
9: 'tab',
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() {
if (!this.target) {
this.target = this.parentNode;
}
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.
* Default to this element's parentNode unless one is assigned
*
* @attribute target
* @type Node
* @default this.parentNode
*/
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>

View File

@@ -0,0 +1,41 @@
<!--
@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="../webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="core-a11y-keys.html">
<style>
div {
height: 100px;
width: 100px;
background: gray;
}
</style>
</head>
<body>
<template is="auto-binding">
<span>Press any of these keys: {{keys}}</span>
<core-a11y-keys id="a11y" keys="{{keys}}" on-keys-pressed="{{print}}"></core-a11y-keys>
<pre id="output"></pre>
</template>
<script>
addEventListener('template-bound', function(ev) {
ev.target.keys = "* pageup pagedown left right down up shift+a alt+a home end space enter"
ev.target.print = function(ev) {
console.log(ev.detail);
this.$.output.textContent += ev.detail.key + ' pressed!\n';
}
});
</script>
</body>
</html>

View File

@@ -0,0 +1,22 @@
<!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="../webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page></core-component-page>
</body>
</html>

View File

@@ -0,0 +1,21 @@
{
"name": "core-ajax",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
},
"version": "0.5.1",
"homepage": "https://github.com/Polymer/core-ajax",
"_release": "0.5.1",
"_resolution": {
"type": "version",
"tag": "0.5.1",
"commit": "c86e3ce6520a00725ebde89a05eb5c233c601e58"
},
"_source": "git://github.com/Polymer/core-ajax.git",
"_target": "^0.5.0",
"_originalSource": "Polymer/core-ajax"
}

View File

@@ -0,0 +1,4 @@
core-ajax
=========
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-ajax) for more information.

View File

@@ -0,0 +1,11 @@
{
"name": "core-ajax",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"devDependencies": {
"polymer-test-tools": "Polymer/polymer-test-tools#master"
},
"version": "0.5.1"
}

View File

@@ -0,0 +1,406 @@
<!--
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`, `params` or `body` 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 progress loading">
<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 current 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 current request, or null if it hasn't
* completed yet or the request resulted in success.
*
* @attribute error
* @type Object
* @default null
*/
error: null,
/**
* Whether the current request is currently loading.
*
* @attribute loading
* @type boolean
* @default false
*/
loading: false,
/**
* The progress of the current request.
*
* @attribute progress
* @type {loaded: number, total: number, lengthComputable: boolean}
* @default {}
*/
progress: 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,
created: function() {
this.progress = {};
},
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});
},
processProgress: function(progress, xhr) {
if (xhr !== this.activeRequest) {
return;
}
// We create a proxy object here because these fields
// on the progress event are readonly properties, which
// causes problems in common use cases (e.g. binding to
// <paper-progress> attributes).
var progressProxy = {
lengthComputable: progress.lengthComputable,
loaded: progress.loaded,
total: progress.total
}
this.progress = progressProxy;
},
complete: function(xhr) {
if (xhr === this.activeRequest) {
this.loading = false;
}
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();
},
bodyChanged: 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 = this.progress = null;
this.activeRequest = args.url && this.xhr.request(args);
if (this.activeRequest) {
this.loading = true;
var activeRequest = this.activeRequest;
// IE < 10 doesn't support progress events.
if ('onprogress' in activeRequest) {
this.activeRequest.addEventListener(
'progress',
function(progress) {
this.processProgress(progress, activeRequest);
}.bind(this), false);
} else {
this.progress = {
lengthComputable: false,
}
}
}
return this.activeRequest;
}
});
</script>
</polymer-element>

View File

@@ -0,0 +1,116 @@
<!--
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,
PATCH: 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>

View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<script src="../webcomponentsjs/webcomponents.js" debug></script>
<meta charset="utf-8">
<title>Race condition</title>
</head>
<body>
<link rel="import" href="core-ajax.html">
<link rel="import" href="../paper-progress/paper-progress.html">
<polymer-element name="progress-test">
<template>
<core-ajax
id="ajax" auto
url="http://httpbin.org/drip"
params="{{ {numbytes: numbytes, duration:5} }}"
response="{{response}}"
progress="{{progress}}"
loading="{{loading}}"
></core-ajax>
<!--
Ordinarily you'd gate on progress.lengthComputable, but we know the
length in this case (and httpbin sadly doesn't return a
Content-Length header for this requesthere).
https://github.com/kennethreitz/httpbin/pull/160
-->
<div>
<button on-click="{{restart}}">Restart</button>
<template if="{{loading}}">
Loading...
</template>
<template if="{{!loading}}">
Loaded!
</template>
</div>
<template if="{{loading && progress.loaded}}">
<paper-progress
value="{{progress.loaded}}"
min="0"
max="{{numbytes}}">
</paper-progress><br>
</template>
</template>
<script>
Polymer('progress-test', {
loading: true,
i: 0,
numbytes: 1000,
pretty: function(i) {
return JSON.stringify(i, null, 2);
},
restart: function() {
this.$.ajax.abort();
this.$.ajax.go();
}
});
</script>
</polymer-element>
<progress-test></progress-test>
</body>
</html>

View File

@@ -0,0 +1,43 @@
<!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="../webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="core-ajax.html">
</head>
<body>
<core-ajax auto url="//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>

View File

@@ -0,0 +1,22 @@
<!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="../webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="../core-component-page/core-component-page.html">
</head>
<body unresolved>
<core-component-page></core-component-page>
</body>
</html>

View File

@@ -0,0 +1,23 @@
<!--
@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>

View File

@@ -0,0 +1,108 @@
<!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="../../webcomponentsjs/webcomponents.js"></script>
<script src="../../web-component-tester/browser.js"></script>
<link rel="import" href="../core-ajax.html">
</head>
<body>
<core-ajax
handleAs="json"
auto></core-ajax>
<!--
Test consistency of core-ajax's loading properties.
-->
<script>
test('progress', function(done) {
var ajax = document.querySelector("core-ajax");
var xhr = sinon.useFakeXMLHttpRequest();
var headers = {
"Content-Type": "text/json"
};
var body = '{"content": "plentiful"}'
var requests = this.requests = [];
xhr.onCreate = function (xhr) {
requests.push(xhr);
// Polymer inspects the xhr object for the precense of onprogress to determine
// whether to attach an event listener.
xhr['onprogress'] = null;
};
var progressEvent = function(lengthComputable, loaded, total) {
var progress = new ProgressEvent('progress', {
lengthComputable: lengthComputable,
loaded: loaded,
total: total
});
return progress;
}
// Fake a file download by sending multiple progress events.
async.series([
function(cb) {
ajax.url="http://example.org/downloadLargeFile"
cb();
},
flush,
animationFrameFlush,
function(cb) {
requests[0].dispatchEvent(progressEvent(true, 10, 100));
cb();
},
flush,
animationFrameFlush,
function(cb) {
assert(ajax.loading === true,
"Request partially complete, but loading property was false.");
var progress = ajax.progress;
assert(progress.lengthComputable, "Progress should be computable");
assert(progress.loaded == 10, "Expected 10 bytes loaded, got " + progress.loaded);
assert(progress.total == 100, "Expected 100 bytes total, got " + progress.total);
cb();
},
animationFrameFlush,
function(cb) {
requests[0].dispatchEvent(progressEvent(true, 100, 100));
cb();
},
animationFrameFlush,
function(cb) {
assert(ajax.loading === true,
"Request partially complete, but loading property was false.");
var progress = ajax.progress;
assert(progress.lengthComputable, "Progress should be computable");
assert(progress.loaded == 100, "Expected 10 bytes loaded, got " + progress.loaded);
assert(progress.total == 100, "Expected 100 bytes total, got " + progress.total);
cb();
},
function(cb) {
requests[0].respond(200, headers, body);
cb();
},
animationFrameFlush,
function(cb) {
assert(ajax.loading === false,
"Request complete, but loading property was true.");
assert(ajax.response.content === "plentiful", "response not parsed");
cb();
}
], done);
});
</script>
</body>
</html>

View File

@@ -0,0 +1,81 @@
<!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="../../webcomponentsjs/webcomponents.js"></script>
<script src="../../web-component-tester/browser.js"></script>
<link rel="import" href="../core-ajax.html">
</head>
<body>
<core-ajax
handleAs="json"
auto></core-ajax>
<!--
Test that when core-ajax fires multiple times as requests are updated,
only the response from the most recent request is used to update the response
object.
-->
<script>
test('race-condition', function(done) {
var ajax = document.querySelector("core-ajax");
var xhr = sinon.useFakeXMLHttpRequest();
var headers = {
"Content-Type": "text/json"
};
var body = function(url) {
return '{"url": "' + url + '"}';
};
var requests = [];
xhr.onCreate = function (xhr) {
requests.push(xhr);
};
// Make request1, then request2. request2 returns first, followed by request1.
async.series([
function(cb) {
ajax.url="http://example.org/request1"
cb();
},
animationFrameFlush,
function(cb) {
ajax.url="http://example.org/request2"
cb();
},
animationFrameFlush,
function(cb) {
requests[0].respond(200, headers, body("http://example.org/request2"));
cb();
},
flush,
function(cb) {
requests[1].respond(200, headers, body("http://example.org/request1"));
cb();
},
flush,
function(cb) {
assert(ajax.response.url.match('request1'),
"Race condition detected. An earlier request's delayed response " +
"caused the more recent request's response to be overwritten.");
done();
cb();
}
], function(){});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,287 @@
<!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="../../webcomponentsjs/webcomponents.js"></script>
<script src="../../web-component-tester/browser.js"></script>
<link rel="import" href="../core-ajax.html">
</head>
<body>
<core-ajax></core-ajax>
<script>
suite('core-ajax', function() {
var xhr, requests, ajax;
suiteSetup(function() {
xhr = sinon.useFakeXMLHttpRequest();
ajax = document.querySelector("core-ajax");
xhr.onCreate = function (xhr) {
requests.push(xhr);
};
// Reset the core-ajax element before each test.
ajax.auto = false;
ajax.url = '';
ajax.params = '';
ajax.handleAs = 'text';
ajax.body = '';
});
setup(function() {
requests = [];
});
suite('handleAs', function() {
suite('text', function(){
var headers = {
"Content-Type": "text/plain"
};
setup(function(done){
async.series([
function(cb){
ajax.handleAs = 'text';
ajax.url = "http://example.com/text"
ajax.auto = true;
cb();
},
animationFrameFlush,
function(cb){
requests[0].respond(200, headers, "test text");
cb();
}
], done);
});
test('Raw text should pass through', function(){
assert.equal(ajax.response, "test text")
});
});
suite('xml', function(){
var headers = {
"Content-Type": "text/xml"
};
setup(function(done){
async.series([
function(cb){
ajax.handleAs = 'xml';
ajax.url = "http://example.com/xml"
ajax.auto = true;
cb();
},
animationFrameFlush,
function(cb){
requests[0].respond(200, headers,
"<note>" +
"<to>AJ</to>" +
"<from>Dog</from>" +
"<subject>Reminder</subject>" +
"<body><q>Feed me!</q></body>" +
"</note>");
cb();
}
], done);
});
test('XML should be returned with queryable structure', function(){
var q = ajax.response.querySelector("note body q");
assert.equal(q.childNodes[0].textContent, "Feed me!");
var to = ajax.response.querySelector("to");
assert.equal(to.childNodes[0].textContent, "AJ");
})});
suite('json', function(){
var headers = {
"Content-Type": "text/json"
};
setup(function(done){
async.series([
function(cb){
ajax.handleAs = 'json';
ajax.url = "http://example.com/json"
ajax.auto = true;
cb();
},
animationFrameFlush,
function(cb){
requests[0].respond(200, headers,
'{"object" : {"list" : [2, 3, {"key": "value"}]}}');
cb();
}
], done);
});
test('JSON should be returned as an Object', function(){
var r = ajax.response;
assert.equal(r.object.list[1], 3);
assert.equal(r.object.list[2].key, "value");
});
});
suite('arraybuffer', function(){
var headers = {
"Content-Type": "text/plain"
};
setup(function(done){
async.series([
function(cb){
ajax.handleAs = 'arraybuffer';
ajax.url = "http://example.com/data"
ajax.auto = true;
cb();
},
animationFrameFlush,
function(cb){
var buf = new ArrayBuffer(8*4);
var resp = new Int32Array(buf);
resp[3] = 12;
resp[6] = 21;
requests[0].response = buf;
requests[0].respond(200, headers, 'blahblahblah');
cb();
}
], done);
});
test('arraybuffer response should be passed through', function(){
var r = ajax.response;
var ints = new Int32Array(r);
assert.equal(ints[3], 12);
assert.equal(ints[6], 21);
});
});
suite('blob', function(){});
suite('document', function(){});
});
suite('auto', function() {
suiteSetup(function(){
ajax.url = "http://example.com/"
ajax.auto = true;
});
test('url change should trigger request', function(done){
async.series([
function(cb){
ajax.url = "http://example.com/auto";
cb();
},
animationFrameFlush,
function(cb){
assert.equal(requests.length, 1);
cb();
}
], done);
});
test('params change should trigger request', function(done){
async.series([
function(cb){
ajax.params = {param: "value"};
cb();
},
animationFrameFlush,
function(cb){
assert.equal(requests.length, 1);
cb();
}
], done);
});
test('body change should trigger request', function(done){
async.series([
function(cb){
ajax.method = "POST";
ajax.body = "bodystuff";
cb();
},
animationFrameFlush,
function(cb){
assert.equal(requests.length, 1);
cb();
}
], done);
});
});
suite('events', function(){
var headers = {
"Content-Type": "text/plain"
};
var body = "somebodytext";
var responded;
setup(function(done){
async.series([
function(cb){
ajax.auto = false;
cb();
},
animationFrameFlush,
function(cb){;
ajax.handleAs = 'text';
ajax.url = "http://example.com/text"
ajax.auto = true;
cb();
},
animationFrameFlush,
], done);
responded = false;
});
suite('core-response', function(){
test('core-response should be fired on success', function(done){
window.addEventListener('core-response', function(response, xhr){
responded = true;
});
requests[0].respond(200, headers, body);
assert.isTrue(responded);
done();
});
test('core-response should not be fired on failure', function(done){
window.addEventListener('core-response', function(response, xhr){
responded = true;
});
requests[0].respond(404, headers, body);
assert.isFalse(responded);
done();
});
});
suite('core-error', function(){
test('core-error should be fired on failure', function(done){
window.addEventListener('core-error', function(response, xhr){
responded = true;
});
requests[0].respond(404, headers, body);
assert.isTrue(responded);
done();
});
test('core-error should not be fired on success', function(done){
var responded = false;
window.addEventListener('core-error', function(response, xhr){
responded = true;
});
requests[0].respond(200, headers, body);
assert.isFalse(responded);
done();
});
});
suite('core-complete', function(){
test('core-complete should be fired on success', function(done){
window.addEventListener('core-complete', function(response, xhr){
responded = true;
});
requests[0].respond(200, headers, body);
assert.isTrue(responded);
done();
});
test('core-complete should be fired on failure', function(done){
var responded = false;
window.addEventListener('core-complete', function(response, xhr){
responded = true;
});
requests[0].respond(404, headers, body);
assert.isTrue(responded);
done();
});
});
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="../../webcomponentsjs/webcomponents.js"></script>
<script src="../../web-component-tester/browser.js"></script>
</head>
<body>
<script>
WCT.loadSuites([
'core-ajax-progress.html',
'core-ajax-race.html',
'core-ajax.html'
]);
</script>
</body>
</html>

View File

@@ -0,0 +1,21 @@
{
"name": "core-animated-pages",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0",
"core-selector": "Polymer/core-selector#^0.5.0",
"core-style": "Polymer/core-style#^0.5.0",
"core-transition": "Polymer/core-transition#^0.5.0"
},
"version": "0.5.1",
"homepage": "https://github.com/Polymer/core-animated-pages",
"_release": "0.5.1",
"_resolution": {
"type": "version",
"tag": "0.5.1",
"commit": "ea600ff41cfc770b4203eaa641a72ada1c1ba154"
},
"_source": "git://github.com/Polymer/core-animated-pages.git",
"_target": "^0.5.0",
"_originalSource": "Polymer/core-animated-pages"
}

View File

@@ -0,0 +1,4 @@
core-animated-pages
===================
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-animated-pages) for more information.

View File

@@ -0,0 +1,11 @@
{
"name": "core-animated-pages",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0",
"core-selector": "Polymer/core-selector#^0.5.0",
"core-style": "Polymer/core-style#^0.5.0",
"core-transition": "Polymer/core-transition#^0.5.0"
},
"version": "0.5.1"
}

View File

@@ -0,0 +1,28 @@
/*
* @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;
}

View File

@@ -0,0 +1,436 @@
<!--
@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;
}
Polymer.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;
Polymer.flush();
Polymer.endOfMicrotask(function() {
self.applyTransition(oldItem, self.selectedItem);
});
}
}
});
</script>
</polymer-element>

View File

@@ -0,0 +1,23 @@
<!--
@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>

View File

@@ -0,0 +1,113 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,126 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,182 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,113 @@
<!--
@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>

View File

@@ -0,0 +1,112 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,255 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@@ -0,0 +1,263 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,142 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,98 @@
<!--
@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="../../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,22 @@
<!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="../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,38 @@
<!--
@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>

View File

@@ -0,0 +1,138 @@
<!--
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>

View File

@@ -0,0 +1,175 @@
<!--
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>

View File

@@ -0,0 +1,173 @@
<!--
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>

View File

@@ -0,0 +1,22 @@
/*
* @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;
}

View File

@@ -0,0 +1,324 @@
<!--
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 ?
queryAllShadows(node, selector) :
node.querySelector('::shadow ' + selector));
},
findAllInShadows: function(node, selector) {
if (hasShadowDOMPolyfill) {
var nodes = node.querySelectorAll(selector).array();
var shadowNodes = 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);
}
// }
}
});
// utility method for searching through shadowRoots.
function queryShadow(node, selector) {
var m, el = node.firstElementChild;
var shadows, sr, i;
shadows = [];
sr = node.shadowRoot;
while(sr) {
shadows.push(sr);
sr = sr.olderShadowRoot;
}
for(i = shadows.length - 1; i >= 0; i--) {
m = shadows[i].querySelector(selector);
if (m) {
return m;
}
}
while(el) {
m = queryShadow(el, selector);
if (m) {
return m;
}
el = el.nextElementSibling;
}
return null;
}
function _queryAllShadows(node, selector, results) {
var el = node.firstElementChild;
var temp, sr, shadows, i, j;
shadows = [];
sr = node.shadowRoot;
while(sr) {
shadows.push(sr);
sr = sr.olderShadowRoot;
}
for (i = shadows.length - 1; i >= 0; i--) {
temp = shadows[i].querySelectorAll(selector);
for(j = 0; j < temp.length; j++) {
results.push(temp[j]);
}
}
while (el) {
_queryAllShadows(el, selector, results);
el = el.nextElementSibling;
}
return results;
}
queryAllShadows = function(node, selector, all) {
if (all) {
return _queryAllShadows(node, selector, []);
} else {
return queryShadow(node, selector);
}
};
})();
</script>
</polymer-element>
<hero-transition id="hero-transition"></hero-transition>

View File

@@ -0,0 +1,58 @@
<!--
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>

View File

@@ -0,0 +1,37 @@
<!--
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>

View File

@@ -0,0 +1,55 @@
<!--
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>

View File

@@ -0,0 +1,38 @@
<!--
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>

View File

@@ -0,0 +1,43 @@
<!--
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>

View File

@@ -0,0 +1,82 @@
<!--
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>

View File

@@ -0,0 +1,101 @@
<!--
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>

View File

@@ -0,0 +1,19 @@
{
"name": "core-animation",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0",
"web-animations-next": "web-animations/web-animations-next#master"
},
"version": "0.5.1",
"homepage": "https://github.com/Polymer/core-animation",
"_release": "0.5.1",
"_resolution": {
"type": "version",
"tag": "0.5.1",
"commit": "3f36bd913cbc59676b8fb1dcf7248ad95c4faa47"
},
"_source": "git://github.com/Polymer/core-animation.git",
"_target": "^0.5.0",
"_originalSource": "Polymer/core-animation"
}

View File

@@ -0,0 +1,4 @@
core-animation
==============
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-animation) for more information.

View File

@@ -0,0 +1,9 @@
{
"name": "core-animation",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0",
"web-animations-next": "web-animations/web-animations-next#master"
},
"version": "0.5.1"
}

View File

@@ -0,0 +1,169 @@
<!--
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>

View File

@@ -0,0 +1,525 @@
<!--
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 customEffect 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.
*
* "forwards" 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 && this.shadowRoot) {
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);
effect = frames;
}
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>

View File

@@ -0,0 +1,193 @@
<!--
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>
<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, user-scalable=yes">
<title>core-animation</title>
<script src="../webcomponentsjs/webcomponents.js"></script>
<link href="../font-roboto/roboto.html" rel="import">
<link href="../core-icon/core-icon.html" rel="import">
<link href="../core-icons/core-icons.html" rel="import">
<link href="core-animation.html" rel="import">
<link href="core-animation-group.html" rel="import">
<style shim-shadowdom>
body {
font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial;
font-size: 14px;
margin: 0;
padding: 24px;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-touch-callout: none;
}
section {
padding: 20px 0;
}
section > div {
padding: 14px;
font-size: 16px;
}
html /deep/ core-icon {
height: 48px;
width: 48px;
}
#target {
display: inline-block;
font-size: 32px;
-webkit-transform: translateZ(0);
transform: translateZ(0);
}
</style>
</head>
<body unresolved onclick="clickAction(event);">
<section>
<div>
<div id="target" layout horizontal center>
<core-icon icon="polymer"></core-icon>
<span>polymer</span>
</div>
</div>
<button>
opacity
<core-animation id="raw" duration="1000">
<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>
</button>
<button>
group: opacity + scale
<core-animation-group type="seq">
<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>
</button>
<button>
infinite duration
<core-animation duration="1000" iterations="Infinity" direction="alternate">
<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>
</button>
<button>
custom effect
<core-animation id="custom-animation" duration="500"></core-animation>
</button>
</section>
<script>
var player;
document.body.addEventListener('core-animation-finish', function(e) {
console.log('core-animation-finish');
if (player) {
player.cancel();
player = null;
target.querySelector('span').textContent = 'polymer';
}
});
var customAnimationFn = function(timeFraction, target) {
// var colors = [
// '#db4437',
// '#ff9800',
// '#ffeb3b',
// '#0f9d58',
// '#4285f4',
// '#3f51b5',
// '#9c27b0'
// ];
target.querySelector('span').textContent = timeFraction;
};
function clickAction(e) {
var t = e.target;
if (e.target.localName !== 'button') {
return;
}
if (player) {
player.cancel();
}
var a = t.querySelector('core-animation,core-animation-group');
if (a.id === 'custom-animation') {
a.customEffect = customAnimationFn;
}
a.target = document.getElementById('target');
player = a.play();
}
</script>
</body>
</html>

View File

@@ -0,0 +1,22 @@
<!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="../webcomponentsjs/webcomponents.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>

View File

@@ -0,0 +1,24 @@
<!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>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>core-animation tests</title>
<script src="../../web-component-tester/browser.js"></script>
</head>
<body>
<script>
WCT.loadSuites([
// 'basic.html'
]);
</script>
</body>
</html>

View File

@@ -0,0 +1,10 @@
<!--
@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="../web-animations-next/web-animations.html">

View File

@@ -0,0 +1,21 @@
{
"name": "core-collapse",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"devDependencies": {
"web-component-tester": "Polymer/web-component-tester#^1.1.0"
},
"version": "0.5.1",
"homepage": "https://github.com/Polymer/core-collapse",
"_release": "0.5.1",
"_resolution": {
"type": "version",
"tag": "0.5.1",
"commit": "e07e13407280eb551f41c0ea0e702d1f11c6ca39"
},
"_source": "git://github.com/Polymer/core-collapse.git",
"_target": "^0.5.0",
"_originalSource": "Polymer/core-collapse"
}

View File

@@ -0,0 +1,4 @@
core-collapse
=============
See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-collapse) for more information.

View File

@@ -0,0 +1,11 @@
{
"name": "core-collapse",
"private": true,
"dependencies": {
"polymer": "Polymer/polymer#^0.5.0"
},
"devDependencies": {
"web-component-tester": "Polymer/web-component-tester#^1.1.0"
},
"version": "0.5.1"
}

View File

@@ -0,0 +1,16 @@
/*
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;
}

Some files were not shown because too many files have changed in this diff Show More