This commit is contained in:
Scott Miles
2012-11-05 18:35:10 -08:00
11 changed files with 187 additions and 71 deletions

View File

@@ -19,7 +19,7 @@
-webkit-transition: all 0.218s;
}
@host.g-overlay-fade[opened] {
@host.g-overlay-fade.opened {
opacity: 1;
}
@@ -29,12 +29,12 @@
-webkit-transition: all 0.218s;
}
@host.g-overlay-scale-slideup[opened] {
@host.g-overlay-scale-slideup.opened {
opacity: 1.0;
-webkit-transform: scale(1.0);
}
@host.g-overlay-scale-slideup:not([opened])[animating] {
@host.g-overlay-scale-slideup.animating:not(.opened) {
opacity: 0;
-webkit-transform: translateY(-100%);
-webkit-transition: all 1s;
@@ -90,13 +90,13 @@
}
}
@host.g-overlay-shake[opened] {
@host.g-overlay-shake.opened {
-webkit-animation-duration: 0.5s;
-webkit-animation-fill-mode: both;
-webkit-animation-name: g-overlay-shakeFadeIn;
}
@host.g-overlay-shake:not([opened])[animating] {
@host.g-overlay-shake.animating:not(.opened) {
-webkit-animation-duration: 0.3s;
-webkit-animation-fill-mode: both;
-webkit-animation-name: g-overlay-shakeFadeOut;

10
src/css/g-page.css Normal file
View File

@@ -0,0 +1,10 @@
/*
* Copyright 2012 The Toolkitchen Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
html, body {
height: 100%;
margin: 0;
font-family: 'Helvetica Nue', 'Helvetica', Arial, 'open sans' sans-serif;
}

View File

@@ -3,14 +3,14 @@
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
@host {
@host, g-panels {
display: block;
position: relative;
outline: none;
overflow: hidden;
}
@host > * {
@host > *, g-panels > * {
position: absolute;
top: 0;
left: 0;
@@ -21,11 +21,11 @@
/* TODO(sorvell): note: this is a workaround for reference combinators
approach defined in shadowDom spec */
/* TODO(sorvell): expose animation timing via css variable */
@host > .transition {
@host > .transition, g-panels > .transition {
-webkit-transition: all 0.5s ease-in-out;
}
@host > .animate {
@host > .animate, g-panels > .animate {
-webkit-animation-duration: 0.5s;
-webkit-animation-fill-mode: both;
}
@@ -39,12 +39,17 @@ approach defined in shadowDom spec */
*/
/* fade */
@host.g-panels-fade > .panels-ascending-from,
@host.g-panels-fade > .panels-descending-from {
@host > .panels-ascending-from,
@host > .panels-descending-from,
g-panels > .panels-ascending-from,
g-panels > .panels-descending-from,
{
-webkit-animation-name: g-panels-fadeOut;
}
@host.g-panels-fade > .panels-ascending-to,
@host.g-panels-fade > .panels-descending-to {
@host > .panels-ascending-to,
@host > .panels-descending-to,
g-panels > .panels-ascending-to,
g-panels > .panels-descending-to {
-webkit-animation-name: g-panels-fadeIn;
}
@@ -62,6 +67,19 @@ approach defined in shadowDom spec */
-webkit-animation-name: g-panels-slideFromLeft;
}
g-panels.g-panels-hslide > .panels-ascending-from {
-webkit-animation-name: g-panels-slideLeft;
}
g-panels.g-panels-hslide > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromRight;
}
g-panels.g-panels-hslide > .panels-descending-from {
-webkit-animation-name: g-panels-slideRight;
}
g-panels.g-panels-hslide > .panels-descending-to {
-webkit-animation-name: g-panels-slideFromLeft;
}
/* vslide */
@host.g-panels-vslide > .panels-ascending-from {
-webkit-animation-name: g-panels-slideTop;
@@ -77,6 +95,10 @@ approach defined in shadowDom spec */
}
/* hslideover */
@host.g-panels-hslideover > .panels-ascending-from,
@host.g-panels-hslideover > .panels-descending-from {
-webkit-animation-name: none;
}
@host.g-panels-hslideover > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromRight;
}
@@ -85,6 +107,10 @@ approach defined in shadowDom spec */
}
/* vslideover */
@host.g-panels-vslideover > .panels-ascending-from,
@host.g-panels-vslideover > .panels-descending-from {
-webkit-animation-name: none;
}
@host.g-panels-vslideover > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromBottom;
}

View File

@@ -5,7 +5,7 @@
* license that can be found in the LICENSE file.
*/
-->
<element name="g-ajax" attributes="url, handleAs, params">
<element name="g-ajax" attributes="url, handleAs, auto, params">
<link rel="components" href="g-component.html">
<link rel="components" href="g-xhr.html">
<template>
@@ -14,11 +14,6 @@
</template>
<script>
this.component({
created: function(inSuper) {
if (this.getAttribute('autogo')) {
this.go();
}
},
prototype: {
/**
* Performs an Ajax request to the url specified.
@@ -73,6 +68,11 @@
} catch (x) {
return r;
}
},
paramsChanged: function() {
if (this.auto) {
this.go();
}
}
}
});

View File

@@ -282,8 +282,7 @@ license that can be found in the LICENSE file.
case "\\false":
return "false";
}
var n = parseFloat(inValue);
return isNaN(n) ? inValue : n;
return isNaN(inValue) ? inValue : parseFloat(inValue);
};
// propagate initial bound-attribute values into properties

View File

@@ -14,17 +14,7 @@
<content></content>
</template>
<script>
// TODO(sorvell): promote this if it becomes a pattern
var setBooleanAttribute = function(inNode, inName, inValue) {
inNode[inValue ? 'setAttribute' : 'removeAttribute'](inName, '');
};
// TODO(sorvell): is there a more new-fangled way to do this?
var makeFocusable = function(inNode) {
if (!inNode.hasAttribute('tabIndex')) {
inNode.setAttribute('tabIndex', -1);
}
}
var ESCAPE_KEY = 27;
/**
* The overlay component is hidden by default and can be opened to display
@@ -37,7 +27,11 @@
this.hidden = true;
},
created: function() {
makeFocusable(this);
// make focusable; note that default tabIndex == -1 but node is
// only focusable if tabIndex attr is set.
if (this.tabIndex < 0) {
this.tabIndex = -1;
}
},
prototype: {
//* Timeout (ms) for animation. After timeout, any opening animation will
@@ -55,16 +49,17 @@
startAnimation: function() {
this.cancelAnimation();
this.hidden = false;
webkitRequestAnimationFrame(function() {
setBooleanAttribute(this, 'opened', this.opened);
setBooleanAttribute(this, 'animating', true);
this._animating = setTimeout(this.finishAnimate.bind(this), this.timeout);
}.bind(this));
this._animating = setTimeout(this.finishAnimate.bind(this), this.timeout);
this.asyncMethod('styleAnimationStart');
},
styleAnimationStart: function() {
this.classList.toggle('opened', this.opened);
this.classList.add('animating');
},
finishAnimate: function() {
if (this._animating) {
this.cancelAnimation();
setBooleanAttribute(this, 'animating', false);
this.classList.remove('animating');
if (!this.opened) {
this.hidden = true;
}
@@ -86,7 +81,7 @@
}
},
keydownHandler: function(e) {
if (e.keyCode == 27) {
if (e.keyCode == ESCAPE_KEY) {
this.opened = false;
}
}

35
src/g-page.html Normal file
View File

@@ -0,0 +1,35 @@
<!--
/*
* Copyright 2012 The Toolkitchen Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
-->
<element name="g-page" attributes="nofit">
<link rel="components" href="g-component.html">
<link rel="stylesheet" href="css/g-page.css" />
<template>
</template>
<script>
this.component({
shadowRootCreated: function(inRoot) {
this.makeFittable(inRoot);
},
prototype: {
makeFittable: function(inRoot) {
var sheet = document.querySelector('style[g-page]');
if (!sheet) {
sheet = inRoot.querySelector('style');
sheet.setAttribute('g-page', '');
sheet.removeAttribute('scoped');
document.head.appendChild(sheet);
}
if (!this.nofit) {
sheet.textContent += '\n' + this.tagName.toLowerCase() + ' {height: 100%;}\n';
}
}
}
});
</script>
</element>

View File

@@ -26,18 +26,29 @@
}
// TODO(sorvell): need key table
var KEY_RIGHT_ARROW = 39;
var KEY_LEFT_ARROW = 37;
var RIGHT_ARROW_KEY = 39;
var LEFT_ARROW_KEY = 37;
this.component({
created: function() {
// ensure default transition
if (!this.transition) {
this.transition = this.defaultTransition;
if (this.index != null) {
this.indexChanged();
}
}
// make focusable; note that default tabIndex == -1 but node is
// only focusable if tabIndex attr is set.
if (this.tabIndex < 0) {
this.tabIndex = -1;
}
this.initPanels();
if (!this.index) {
this.index = 0;
}
},
prototype: {
tabIndex: -1,
defaultTransition: 'keyframe',
initPanels: function() {
this.getPanels().forEach(function(p, i) {
@@ -47,13 +58,11 @@
initPanel: function() {},
indexChanged: function(inOldValue) {
var i = this.clampIndex(this.index);
var old = this.clampIndex(inOldValue);
if (i != this.index) {
this.index = i;
return;
}
if (this.index != old) {
this.lastIndex = old;
if (this.index != this.lastIndex) {
var fromPanel = this.panelAtIndex(this.lastIndex),
toPanel = this.panelAtIndex(this.index),
forward = Boolean(this.index > this.lastIndex);
@@ -62,20 +71,26 @@
} else {
this.finishTransition(fromPanel, toPanel, forward);
}
this.lastIndex = this.index;
// TODO(sorvell): replace with getter/setter for selected when
// g-component does not override these on instances.
this.selected = this.getSelectedValue();
}
},
clampIndex: function(inIndex) {
return Math.max(0, Math.min(this.count-1, inIndex));
var i = isNaN(inIndex) ? 0 : inIndex;
return Math.max(0, Math.min(this.count-1, i));
},
// selected is a virtual property so override getter
get selected() {
getSelectedValue: function() {
var selected = this.getSelectedPanel();
var name = selected && selected.getAttribute('name');
var name = selected && (selected.getAttribute('id') ||
selected.getAttribute('name'));
return name || this.index;
},
// selected is the name property of the panel to select
selectedChanged: function(inOldValue) {
var index = this.indexOfName(this.selected);
var index = this.indexOfPropValue('id', this.selected);
index = index >= 0 ? index : this.indexOfPropValue('name', this.selected);
if (index >= 0) {
this.index = index;
}
@@ -95,23 +110,23 @@
this.makeTransitionNode(this.defaultTransition);
},
tagNameForTransition: function(inName) {
return "g-" + inName + (inName ? "-" : "") + "panel-transition";
return 'g-' + inName + (inName ? '-' : '') + 'panel-transition';
},
// TODO: consider selecting something more specific so we don't need to
// filter out style/templates children.
getPanels: function() {
var n$ = this.$.content.getDistributedNodes();
return Array.prototype.filter.call(n$, function(c) {
return c.tagName != "STYLE" && c.tagName != "TEMPLATE";
return c.tagName != 'STYLE' && c.tagName != 'TEMPLATE';
});
},
getSelectedPanel: function() {
return this.getPanels()[this.index];
},
indexOfName: function(inName) {
indexOfPropValue: function(inProp, inValue) {
var c$ = this.getPanels();
for (var i=0, c; c=c$[i]; i++) {
if (c.getAttribute("name") == inName) {
if (c.getAttribute(inProp) == inValue) {
return i;
}
}
@@ -130,43 +145,57 @@
return this.getPanels().length;
},
canTransition: function() {
return Boolean(this.transitionNode);
return Boolean(this.transitionNode &&
this.transitionNode.canTransition());
},
beginTransition: function(inFrom, inTo, inForward) {
if (this.transitionNode) {
this.transitionNode.stop();
}
webkitRequestAnimationFrame(function() {
inFrom.hidden = false;
inTo.hidden = false;
this.enablePanelShowing(inFrom, true);
this.enablePanelShowing(inTo, true);
this.transitionNode.go(inFrom, inTo, inForward);
}.bind(this));
},
finishTransition: function() {
if (this.transitionNode && this.transitionNode.highlander) {
this.getPanels().forEach(function(p, i) {
p.hidden = (i != this.index);
this.enablePanelShowing(p, i == this.index);
}, this);
}
},
// note: cannot use hidden attr for this since it's trumped by display
// setting e.g. hidden + display: -webkit-flex == showing.
enablePanelShowing: function(inPanel, inEnable) {
inPanel.style.display = inEnable ? null : 'none';
},
next: function() {
this.index++;
},
previous: function() {
this.index--;
},
toggleBetween: function(inA, inB) {
this.selected = this.selected == inA ? inB : inA;
},
keydownHandler: function(e) {
if (!documentIsEditing()) {
var beforeIndex = this.index;
if (e.keyCode == KEY_RIGHT_ARROW) {
if (e.keyCode == RIGHT_ARROW_KEY) {
this.next();
} else if (e.keyCode == KEY_LEFT_ARROW) {
} else if (e.keyCode == LEFT_ARROW_KEY) {
this.previous();
}
if (beforeIndex != this.index) {
e.stopPropagation();
}
}
},
refresh: function() {
if (this.transitionNode && this.transitionNode.canTransition()) {
this.transitionNode.refresh();
}
}
}
});

View File

@@ -8,13 +8,13 @@
<element name="g-flow-panel-transition" extends="g-panel-transition">
<template>
<style scoped>
x-flowpanels > .right {
g-panels[transition='flow'] > .right {
left: auto;
right: 0;
}
@media screen and (max-width: 800px) {
x-flowpanels > * {
g-panels[transition='flow'] > * {
width: 100% !important;
-webkit-box-shadow: none !important;
}
@@ -22,6 +22,11 @@
</style>
</template>
<script>
var isNodeHidden = function(inNode) {
return (inNode.offsetWidth) == 0 && (inNode.offsetHeight == 0);
}
this.component({
shadowRootCreated: function(inRoot) {
this.sheet = inRoot.querySelector("style");
@@ -33,6 +38,9 @@
this.base.setup.call(this, inPanels);
this.listenForMediaMatch();
this.panels.appendChild(this.sheet);
// TODO(sorvell): hack, must fix better
// async refresh in case we need to wait for stylesheet to load
this.asyncMethod('refresh');
},
teardown: function() {
this.base.teardown.call(this);
@@ -40,7 +48,6 @@
},
listenForMediaMatch: function() {
var mq = window.matchMedia(this.narrowMedia);
this.narrowLayout = mq.matches;
mq.addListener(this.layoutChange.bind(this));
this.layoutChange(mq);
},
@@ -53,9 +60,16 @@
p.style.webkitTransition = inEnable ? null : 'none';
});
},
canTransition: function() {
var hidden = isNodeHidden(this.panels);
return !hidden;
},
refresh: function() {
this.enableTransitions(false);
this.go(null, this.panels.getSelectedPanel());
this.to = this.panels.getSelectedPanel();
if (this.canTransition()) {
this.begin();
}
webkitRequestAnimationFrame(function() {
this.enableTransitions(true);
}.bind(this));

View File

@@ -21,9 +21,11 @@
},
setup: function(inPanels) {
this.panels = inPanels;
inPanels.getPanels().forEach(function(p, i) {
var showing;
this.panels.getPanels().forEach(function(p, i) {
p.classList.add(this.transitionClass);
p.hidden = this.highlander && (i != inPanels.index);
showing = !this.highlander || (i == inPanels.index);
this.panels.enablePanelShowing(p, showing);
}, this);
this.finishListener = this.finish.bind(this);
},
@@ -32,10 +34,13 @@
p.classList.remove(this.transitionClass);
p.style.opacity = p.style.webkitTransform = null;
if (this.highlander) {
p.hidden = false;
this.panels.enablePanelShowing(p, true);
};
}, this);
},
canTransition: function() {
return true;
},
go: function(inFrom, inTo, inForward) {
this.from = inFrom;
this.to = inTo;
@@ -46,9 +51,9 @@
finish: function() {
if (this._transitioning) {
this.complete();
this.cancel();
this.panels.finishTransition();
}
this.cancel();
this.panels.finishTransition();
},
cancel: function() {
clearTimeout(this._transitioning);
@@ -61,6 +66,9 @@
begin: function() {
},
complete: function() {
},
// refresh the transition state
refresh: function() {
}
}
});

View File

@@ -11,7 +11,7 @@ license that can be found in the LICENSE file.
<link rel="components" href="../../toolkit/src/g-ajax.html">
</head>
<body>
<g-ajax autogo="true" url="http://gdata.youtube.com/feeds/api/videos/"
<g-ajax auto url="http://gdata.youtube.com/feeds/api/videos/"
handleAs="json" params='{"alt":"json", "q":"chrome"}'>
<div>
<template iterate="response.feed.entry">