This commit is contained in:
Scott Miles
2012-11-05 11:43:41 -08:00
15 changed files with 1018 additions and 148 deletions

103
src/css/g-overlay.css Normal file
View File

@@ -0,0 +1,103 @@
/*
* 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.
*/
@host {
position: fixed;
z-index: 10;
outline: none;
}
/*
TODO(sorvell): include a reasonable set of default overlay opening
animations. What's here right now is ad hoc.
*/
@host.g-overlay-fade {
opacity: 0;
-webkit-transition: all 0.218s;
}
@host.g-overlay-fade[opened] {
opacity: 1;
}
@host.g-overlay-scale-slideup {
opacity: 0.0;
-webkit-transform: scale(1.05);
-webkit-transition: all 0.218s;
}
@host.g-overlay-scale-slideup[opened] {
opacity: 1.0;
-webkit-transform: scale(1.0);
}
@host.g-overlay-scale-slideup:not([opened])[animating] {
opacity: 0;
-webkit-transform: translateY(-100%);
-webkit-transition: all 1s;
}
@-webkit-keyframes g-overlay-shakeFadeIn {
0% {
display: block;
opacity: 0;
-webkit-transform: translateX(0);
}
10% {
display: block;
-webkit-transform: translateX(-50px);
}
30% {
display: block;
-webkit-transform: translateX(50px);
}
50% {
display: block;
-webkit-transform: translateX(-25px);
}
70% {
display: block;
-webkit-transform: translateX(25px);
}
90% {
display: block;
-webkit-transform: translateX(-13px);
}
100% {
display: block;
-webkit-transform: translateX(0);
opacity: 1;
}
}
@-webkit-keyframes g-overlay-shakeFadeOut {
0% {
opacity: 1;
-webkit-transform: translateX(0);
}
10% {
-webkit-transform: translateX(-50px);
}
30% {
-webkit-transform: translateX(50px);
}
100% {
-webkit-transform: translateX(-100%);
opacity: 0;
}
}
@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] {
-webkit-animation-duration: 0.3s;
-webkit-animation-fill-mode: both;
-webkit-animation-name: g-overlay-shakeFadeOut;
}

335
src/css/g-panels.css Normal file
View File

@@ -0,0 +1,335 @@
/*
* 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.
*/
@host {
display: block;
position: relative;
outline: none;
overflow: hidden;
}
@host > * {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* 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 {
-webkit-transition: all 0.5s ease-in-out;
}
@host > .animate {
-webkit-animation-duration: 0.5s;
-webkit-animation-fill-mode: both;
}
/*
TODO(sorvell): include a reasonable set of default overlay opening
animations. What's here right now is ad hoc.
NOTE: until reference combinators (presumably), need to include this file
in any document that wants panel transitions.
*/
/* fade */
@host.g-panels-fade > .panels-ascending-from,
@host.g-panels-fade > .panels-descending-from {
-webkit-animation-name: g-panels-fadeOut;
}
@host.g-panels-fade > .panels-ascending-to,
@host.g-panels-fade > .panels-descending-to {
-webkit-animation-name: g-panels-fadeIn;
}
/* hslide */
@host.g-panels-hslide > .panels-ascending-from {
-webkit-animation-name: g-panels-slideLeft;
}
@host.g-panels-hslide > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromRight;
}
@host.g-panels-hslide > .panels-descending-from {
-webkit-animation-name: g-panels-slideRight;
}
@host.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;
}
@host.g-panels-vslide > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromBottom;
}
@host.g-panels-vslide > .panels-descending-from {
-webkit-animation-name: g-panels-slideBottom;
}
@host.g-panels-vslide > .panels-descending-to {
-webkit-animation-name: g-panels-slideFromTop;
}
/* hslideover */
@host.g-panels-hslideover > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromRight;
}
@host.g-panels-hslideover > .panels-descending-to {
-webkit-animation-name: g-panels-slideFromLeft;
}
/* vslideover */
@host.g-panels-vslideover > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromBottom;
}
@host.g-panels-vslideover > .panels-descending-to {
-webkit-animation-name: g-panels-slideFromTop;
}
/* explode */
@host.g-panels-explode > .panels-ascending-from,
@host.g-panels-explode > .panels-descending-from {
-webkit-animation-name: g-panels-explodeOut;
}
@host.g-panels-explode > .panels-ascending-to,
@host.g-panels-explode > .panels-descending-to {
-webkit-animation-name: g-panels-explodeIn;
}
/* scale-slide */
@host.g-panels-scale-slide > .panels-ascending-from {
-webkit-animation-name: g-panels-fadeScaleOut;
}
@host.g-panels-scale-slide > .panels-ascending-to {
-webkit-animation-name: g-panels-slideFromRight;
}
@host.g-panels-scale-slide > .panels-descending-from {
-webkit-animation-name: g-panels-slideRight;
}
@host.g-panels-scale-slide > .panels-descending-to {
-webkit-animation-name: g-panels-fadeScaleIn;
}
/* fly-up-right */
@host.g-panels-fly-up-right > .panels-ascending-from {
-webkit-animation-name: g-panels-flyOutRight;
}
@host.g-panels-fly-up-right > .panels-ascending-to {
-webkit-animation-name: g-panels-fadeInPartial;
}
@host.g-panels-fly-up-right > .panels-descending-from {
-webkit-animation-name: g-panels-fadeOutPartial;
}
@host.g-panels-fly-up-right > .panels-descending-to {
-webkit-animation-name: g-panels-flyInLeft;
}
@-webkit-keyframes g-panels-fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@-webkit-keyframes g-panels-fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes g-panels-fadeInPartial {
0% {
opacity: 0.25;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes g-panels-fadeOutPartial {
0% {
opacity: 1;
}
100% {
opacity: 0.25;
}
}
@-webkit-keyframes g-panels-fadeScaleIn {
0% {
z-index: 0;
opacity: 0.5;
-webkit-transform: scale(0.9);
}
20% {
z-index: 0;
-webkit-transform: scale(0.9);
}
100% {
z-index: 0;
opacity: 1;
-webkit-transform: scale(1);
}
}
@-webkit-keyframes g-panels-fadeScaleOut {
0% {
z-index: 0;
opacity: 1;
-webkit-transform: scale(1);
}
20% {
z-index: 0;
-webkit-transform: scale(0.9);
}
100% {
z-index: 0;
opacity: 0.5;
-webkit-transform: scale(0.9);
}
}
@-webkit-keyframes g-panels-slideRight {
0% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(100%, 0, 0);
}
}
@-webkit-keyframes g-panels-slideFromRight {
0% {
z-index: 1;
-webkit-transform: translate3d(100%, 0, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes g-panels-slideLeft {
0% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(-100%, 0, 0);
}
}
@-webkit-keyframes g-panels-slideFromLeft {
0% {
z-index: 1;
-webkit-transform: translate3d(-100%, 0, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes g-panels-slideBottom {
0% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(0, 100%, 0);
}
}
@-webkit-keyframes g-panels-slideFromBottom {
0% {
z-index: 1;
-webkit-transform: translate3d(0, 100%, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes g-panels-slideTop {
0% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(0, -100%, 0);
}
}
@-webkit-keyframes g-panels-slideFromTop {
0% {
z-index: 1;
-webkit-transform: translate3d(0, -100%, 0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes g-panels-explodeOut {
0% {
-webkit-transform: scale(1);
opacity: 1;
}
100% {
-webkit-transform: scale(0);
opacity: 0;
}
}
@-webkit-keyframes g-panels-explodeIn {
0% {
z-index: 1;
-webkit-transform: scale(0);
opacity: 0;
}
100% {
z-index: 1;
-webkit-transform: scale(1);
opacity: 1;
}
}
@-webkit-keyframes g-panels-flyOutRight {
0% {
z-index: 1;
-webkit-transform: translate3d(0) rotate(0);
}
100% {
z-index: 1;
-webkit-transform: translate3d(10%, -110%, 0) rotate(5deg);
}
}
@-webkit-keyframes g-panels-flyInLeft {
0% {
z-index: 1;
-webkit-transform: translate3d(10%, -110%, 0) rotate(5deg);
}
100% {
z-index: 1;
-webkit-transform: translate3d(0) rotate(0deg);
}
}

View File

@@ -160,7 +160,7 @@ license that can be found in the LICENSE file.
var bindProperty = function(inName, inValue) {
if (inName in this) {
// set default value in a property already bound via attrs
setPropertySilently.call(this, inName, value);
setPropertySilently.call(this, inName, inValue);
} else {
//console.log('binding', inName, this)
var value = inValue;
@@ -437,7 +437,7 @@ license that can be found in the LICENSE file.
// is in inNodes, if any
var n = inTarget;
while (n && n != this) {
var i = inNodes.indexOf(n);
var i = Array.prototype.indexOf.call(inNodes, n);
if (i >= 0) {
return i;
}

View File

@@ -5,13 +5,14 @@
* license that can be found in the LICENSE file.
*/
-->
<element name="g-menuitem" attributes="src">
<element name="g-menuitem" attributes="src, label">
<link rel="components" href="g-component.html">
<link rel="components" href="g-icon.html">
<link rel="stylesheet" href="css/g-menuitem.css" />
<template>
<g-icon id="icon"></g-icon>
<div class="label">
<span id="label"></span>
<content></content>
</div>
</template>
@@ -20,6 +21,9 @@
prototype: {
srcChanged: function() {
this.$.icon.src = this.src;
},
labelChanged: function() {
this.$.label.textContent = this.label;
}
}
});

View File

@@ -5,70 +5,90 @@
* license that can be found in the LICENSE file.
*/
-->
<element name="g-overlay" attributes="showing, timeout">
<element name="g-overlay" attributes="opened, timeout"
handlers="click: clickHandler, keydown: keydownHandler,
webkitAniamtionEnd: finishAnimate, webkitTransitionEnd: finishAnimate">
<link rel="components" href="g-component.html">
<link rel="stylesheet" href="css/g-overlay.css">
<template>
<style scoped>
@host {
position: absolute;
z-index: 10;
}
</style>
<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);
}
}
/**
* The overlay component is hidden by default and can be opened to display
* its content. It's common to animate an overlay opened and closed. This
* can be achieved by styling the overlay node via the `opened` and
* `animating` attributes.
*/
this.component({
shadowRootCreated: function() {
this.hidden = true;
},
created: function() {
makeFocusable(this);
},
prototype: {
//* Timeout (ms) for animation. After timeout, any opening animation will
//* be aborted and overlay will be set to opened or not and not animating.
timeout: 1000,
showingChanged: function() {
this.animateShowing();
webkitRequestAnimationFrame(this.fireShowingChange.bind(this));
openedChanged: function() {
this.startAnimation();
// TODO(sorvell): need a controllable api for this, including
// maybe focusElement.
if (this.opened) {
this.focus();
}
this.fireEvent('openedChanged', {opened: this.opened});
},
dispatch: function(inName, inDetail) {
this.dispatchEvent(new CustomEvent(inName, {
bubbles: true,
detail: inDetail
}));
},
fireShowingChange: function() {
this.dispatch("showingChange", {
showing: this.showing,
rect: this.getBoundingClientRect()
});
},
animateShowing: function() {
startAnimation: function() {
this.cancelAnimation();
this.hidden = false;
webkitRequestAnimationFrame(function() {
var setBooleanAttribute = function(inNode, inName, inValue) {
inNode[inValue ? "setAttribute" : "removeAttribute"](inName, "");
};
setBooleanAttribute(this, "opening", this.showing);
setBooleanAttribute(this, "closing", !this.showing);
this.unlisten();
this.listen();
setBooleanAttribute(this, 'opened', this.opened);
setBooleanAttribute(this, 'animating', true);
this._animating = setTimeout(this.finishAnimate.bind(this), this.timeout);
}.bind(this));
},
listen: function() {
this.animationListener = this.finishAnimate.bind(this);
this.addEventListener("webkitAnimationEnd", this.animationListener);
this.addEventListener("webkitTransitionEnd", this.animationListener);
// always finish animation within timeout
this.jobId = this.utils.job(this.jobId, this.animationListener, this.timeout);
},
finishAnimate: function() {
if (!this.showing) {
this.hidden = true;
this.classList.remove(this.hideClass);
if (this._animating) {
this.cancelAnimation();
setBooleanAttribute(this, 'animating', false);
if (!this.opened) {
this.hidden = true;
}
}
this.unlisten();
},
unlisten: function() {
this.removeEventListener("webkitAnimationEnd", this.animationListener);
this.removeEventListener("webkitTransitionEnd", this.animationListener);
this.utils.job.stop(this.jobId);
cancelAnimation: function() {
if (this._animating) {
clearTimeout(this._animating);
this._animating = null;
}
},
//* Toggle the opened state of the overlay.
toggle: function() {
this.opened = !this.opened;
},
clickHandler: function(e) {
if (e.target && e.target.hasAttribute('overlay-toggle')) {
this.toggle();
}
},
keydownHandler: function(e) {
if (e.keyCode == 27) {
this.opened = false;
}
}
}
});

174
src/g-panels.html Normal file
View File

@@ -0,0 +1,174 @@
<!--
/*
* 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-panels" attributes="transition, selected, index"
handlers="keydown: keydownHandler">
<link rel="components" href="g-component.html">
<link rel="components" href="panel-transitions/g-panel-transition.html">
<link rel="components" href="panel-transitions/g-keyframe-panel-transition.html">
<link rel="components" href="panel-transitions/g-flow-panel-transition.html">
<link rel="stylesheet" href="css/g-panels.css" />
<template>
<content id="content" select="*"></content>
</template>
<script>
// TODO(sorvell): promote this and figure out canonical way to do this;
// and support contenteditable.
var documentIsEditing = function() {
var a = document.activeElement;
if (a.tagName == "INPUT" || a.tagName == "SELECT" || a.tagName == "TEXTAREA") {
return true;
}
}
// TODO(sorvell): need key table
var KEY_RIGHT_ARROW = 39;
var KEY_LEFT_ARROW = 37;
this.component({
created: function() {
this.initPanels();
if (!this.index) {
this.index = 0;
}
},
prototype: {
tabIndex: -1,
defaultTransition: 'keyframe',
initPanels: function() {
this.getPanels().forEach(function(p, i) {
this.initPanel(p, i);
}, this);
},
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;
var fromPanel = this.panelAtIndex(this.lastIndex),
toPanel = this.panelAtIndex(this.index),
forward = Boolean(this.index > this.lastIndex);
if (this.canTransition() && fromPanel && toPanel) {
this.beginTransition(fromPanel, toPanel, forward);
} else {
this.finishTransition(fromPanel, toPanel, forward);
}
}
},
clampIndex: function(inIndex) {
return Math.max(0, Math.min(this.count-1, inIndex));
},
// selected is a virtual property so override getter
get selected() {
var selected = this.getSelectedPanel();
var name = selected && 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);
if (index >= 0) {
this.index = index;
}
},
transitionChanged: function(inOldValue) {
if (this.transitionNode) {
this.transitionNode.teardown();
}
this.transitionNode = this.makeTransitionNode(this.transition);
this.transitionNode.setup(this);
this.setAttribute('transition', this.transition);
},
makeTransitionNode: function(inName) {
var name = this.tagNameForTransition(inName);
var transition = document.createElement(name);
return transition.setup ? transition :
this.makeTransitionNode(this.defaultTransition);
},
tagNameForTransition: function(inName) {
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";
});
},
getSelectedPanel: function() {
return this.getPanels()[this.index];
},
indexOfName: function(inName) {
var c$ = this.getPanels();
for (var i=0, c; c=c$[i]; i++) {
if (c.getAttribute("name") == inName) {
return i;
}
}
return -1;
},
indexOf: function(inPanel) {
return this.getPanels().indexOf(inPanel);
},
panelAtIndex: function(inIndex) {
return this.getPanels()[inIndex];
},
panelAtName: function(inName) {
return this.panelAtIndex(this.indexOfName(inName));
},
get count() {
return this.getPanels().length;
},
canTransition: function() {
return Boolean(this.transitionNode);
},
beginTransition: function(inFrom, inTo, inForward) {
if (this.transitionNode) {
this.transitionNode.stop();
}
webkitRequestAnimationFrame(function() {
inFrom.hidden = false;
inTo.hidden = false;
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);
}
},
next: function() {
this.index++;
},
previous: function() {
this.index--;
},
keydownHandler: function(e) {
if (!documentIsEditing()) {
var beforeIndex = this.index;
if (e.keyCode == KEY_RIGHT_ARROW) {
this.next();
} else if (e.keyCode == KEY_LEFT_ARROW) {
this.previous();
}
if (beforeIndex != this.index) {
e.stopPropagation();
}
}
}
}
});
</script>
</element>

View File

@@ -21,10 +21,10 @@
this.stars = ShadowDOM.localQueryAll(inRoot, ".star");
},
created: function() {
this.valueAttributeChanged();
this.valueChanged();
},
prototype: {
valueAttributeChanged: function() {
valueChanged: function() {
for (var i=0, s; s=this.stars[i]; i++) {
s.classList.toggle('full', i < Number(this.value));
}

View File

@@ -9,8 +9,8 @@
<link rel="components" href="g-component.html">
<link rel="components" href="g-selection.html">
<template>
<g-selection id="selection" atselect="selectionSelect" atdeselect="selectionDeselect"></g-selection>
<content id="items"></content>
<g-selection id="selection" on-select="selectionSelect" on-deselect="selectionDeselect"></g-selection>
<content id="items" select="*"></content>
</template>
<script>
this.component({
@@ -19,12 +19,10 @@
this.$.selection.multi = this.multi;
},
getItems: function() {
// TODO(sjmiles): distributedNodes not implemented natively yet
// this.childNodes is LightDOM fallback which works unless we
// are composited (in that case childNodes = <content>, and
// distributeNodes is necessary to find the actual distributions)
return this.$.items.distributedNodes ||
Array.prototype.slice.call(this.childNodes, 0);
return this.$.items.getDistributedNodes();
},
getSelectedItem: function() {
return this.$.selection.getSelection();
},
_valueToIndex: function(inValue) {
// find an item with value == inValue and return it's index

View File

@@ -0,0 +1,113 @@
<!--
/*
* 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-flow-panel-transition" extends="g-panel-transition">
<template>
<style scoped>
x-flowpanels > .right {
left: auto;
right: 0;
}
@media screen and (max-width: 800px) {
x-flowpanels > * {
width: 100% !important;
-webkit-box-shadow: none !important;
}
}
</style>
</template>
<script>
this.component({
shadowRootCreated: function(inRoot) {
this.sheet = inRoot.querySelector("style");
},
prototype: {
highlander: false,
narrowMedia: '(max-width: 800px)',
setup: function(inPanels) {
this.base.setup.call(this, inPanels);
this.listenForMediaMatch();
this.panels.appendChild(this.sheet);
},
teardown: function() {
this.base.teardown.call(this);
this.panels.removeChild(this.sheet);
},
listenForMediaMatch: function() {
var mq = window.matchMedia(this.narrowMedia);
this.narrowLayout = mq.matches;
mq.addListener(this.layoutChange.bind(this));
this.layoutChange(mq);
},
layoutChange: function(inQuery) {
this.narrowLayout = inQuery.matches;
this.refresh();
},
enableTransitions: function(inEnable) {
this.panels.getPanels().forEach(function(p) {
p.style.webkitTransition = inEnable ? null : 'none';
});
},
refresh: function() {
this.enableTransitions(false);
this.go(null, this.panels.getSelectedPanel());
webkitRequestAnimationFrame(function() {
this.enableTransitions(true);
}.bind(this));
},
begin: function() {
var i = this.panels.indexOf(this.to);
if (this.panelIsRightAligned(this.to)) {
this.applyRightLayout(this.to, i);
} else {
this.applyLeftLayout(this.to, i);
}
},
// inIndex appears at the left with subsequent nodes
// moved out of the way to the right; right aligned nodes are ignored
applyLeftLayout: function(inTo, inIndex) {
var l, count = this.count;
this.panels.getPanels().forEach(function(p, i) {
var x = !l ? 0 : (this.narrowLayout ? (i - inIndex) * 100 +
'%' : l.offsetWidth + 'px');
var right = this.panelIsRightAligned(p);
p.style.zIndex = right ? -i : null;
p.style.webkitTransform = 'translate3d(' + (right ? 0 : x) + ',0,0)';
if (i >= inIndex) {
l = p;
}
}, this);
},
// inIndex appears at the right with previous nodes
// moved out of the way to the left; note z-index used to get proper stacking
applyRightLayout: function(inTo, inIndex) {
var p$ = this.panels.getPanels(), right=true, l;
for (var i=p$.length-1, p; p=p$[i]; i--) {
var x = l ? -l.offsetWidth : 0;
p.style.zIndex = right ? p$.length - i : null;
p.style.webkitTransform = 'translate3d(' + x + 'px,0,0)';
if (i <= inIndex) {
l = p;
}
// record where we stop being right aligned so we can stop z-stacking
right = right && this.panelIsRightAligned(p);
}
},
// TODO(sorvell): it's unsatisfying that we need a specific class to
// determine right alignment because this defeats applying rightness via
// selectors (e.g. :last-child or media queries). We could look for
// computed style right == 0 but this seems more brittle.
panelIsRightAligned: function(inNode) {
return !this.panels.narrowLayout && inNode &&
inNode.classList.contains('right');
}
}
});
</script>
</element>

View File

@@ -0,0 +1,39 @@
<!--
/*
* 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-keyframe-panel-transition" extends="g-panel-transition">
<script>
var END_EVENT = 'webkitAnimationEnd';
this.component({
prototype: {
transitionClass: 'animate',
setup: function(inPanels) {
this.base.setup.call(this, inPanels);
this.panels.addEventListener(END_EVENT, this.finishListener);
},
teardown: function() {
this.base.teardown.call(this);
this.panels.removeEventListener(END_EVENT, this.finishListener);
},
begin: function() {
this.from.classList.add(this.forward ? 'panels-ascending-from' :
'panels-descending-from');
this.to.classList.add(this.forward ? 'panels-ascending-to' :
'panels-descending-to');
},
complete: function() {
this.from.classList.remove('panels-ascending-from',
'panels-descending-from');
this.to.classList.remove('panels-ascending-to',
'panels-descending-to');
}
}
});
</script>
</element>

View File

@@ -0,0 +1,69 @@
<!--
/*
* 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-panel-transition">
<!-- remove blank template when polyfill issue #62 is fixed -->
<template></template>
<script>
this.component({
prototype: {
transitionClass: 'transition',
timeout: 1000,
//* indicates only one panel should be displayed at a time.
highlander: true,
// TODO(sorvell): promote to g-component?
get base() {
return this.__proto__.__proto__;
},
setup: function(inPanels) {
this.panels = inPanels;
inPanels.getPanels().forEach(function(p, i) {
p.classList.add(this.transitionClass);
p.hidden = this.highlander && (i != inPanels.index);
}, this);
this.finishListener = this.finish.bind(this);
},
teardown: function() {
this.panels.getPanels().forEach(function(p, i) {
p.classList.remove(this.transitionClass);
p.style.opacity = p.style.webkitTransform = null;
if (this.highlander) {
p.hidden = false;
};
}, this);
},
go: function(inFrom, inTo, inForward) {
this.from = inFrom;
this.to = inTo;
this.forward = inForward;
this._transitioning = setTimeout(this.finishListener, this.timeout);
this.begin(inFrom, inTo, inForward);
},
finish: function() {
if (this._transitioning) {
this.complete();
}
this.cancel();
this.panels.finishTransition();
},
cancel: function() {
clearTimeout(this._transitioning);
this._transitioning = null;
},
stop: function() {
this.finish();
},
// transitions typically override begin/complete
begin: function() {
},
complete: function() {
}
}
});
</script>
</element>

View File

@@ -17,7 +17,7 @@ license that can be found in the LICENSE file.
</style>
</head>
<body>
<g-menu>
<g-menu selected="0">
<g-menuitem src="images/edit_page.svg">Post a Comment</g-menuitem>
<g-menuitem src="images/chat.svg">Share Link</g-menuitem>
<g-menuitem src="images/email.svg">Email Link</g-menuitem>

View File

@@ -4,6 +4,7 @@
<title>Overlay</title>
<script src="../../polyfills/Components/components-polyfill.js" shadow="shim"></script>
<link rel="components" href="../../toolkit/src/g-overlay.html">
<link rel="stylesheet" href="../../toolkit/src/css/g-overlay.css">
<style>
body {
font-family: Arial, Helvetica, sans-serif;
@@ -12,8 +13,8 @@
font-size: 13px;
}
.dialog {
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
#dialog, #dialog2 {
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
background: white;
left: 50%;
outline: 1px solid rgba(0,0,0,0.2);
@@ -26,91 +27,12 @@
z-index: 100;
top: 72px;
margin-left: -256px;
/*display: none;*/
opacity: 0.0;
-webkit-transform: scale(1.05);
-webkit-transition: all 0.218s;
}
#dialog[opening] {
opacity: 1.0;
-webkit-transform: scale(1.0);
}
#dialog[closing] {
opacity: 0;
-webkit-transform: translateY(-100%);
-webkit-transition: all 1s;
}
@-webkit-keyframes shakeFadeIn {
0% {
display: block;
opacity: 0;
-webkit-transform: translateX(0);
}
10% {
display: block;
-webkit-transform: translateX(-50px);
}
30% {
display: block;
-webkit-transform: translateX(50px);
}
50% {
display: block;
-webkit-transform: translateX(-25px);
}
70% {
display: block;
-webkit-transform: translateX(25px);
}
90% {
display: block;
-webkit-transform: translateX(-13px);
}
100% {
display: block;
-webkit-transform: translateX(0);
opacity: 1;
}
}
@-webkit-keyframes shakeFadeOut {
0% {
opacity: 1;
-webkit-transform: translateX(0);
}
10% {
-webkit-transform: translateX(-50px);
}
30% {
-webkit-transform: translateX(50px);
}
100% {
-webkit-transform: translateX(-100%);
opacity: 0;
}
}
#dialog2[opening] {
-webkit-animation-duration: 0.5s;
-webkit-animation-fill-mode: both;
-webkit-animation-name: shakeFadeIn;
}
#dialog2[closing] {
-webkit-animation-duration: 0.3s;
-webkit-animation-fill-mode: both;
-webkit-animation-name: shakeFadeOut;
}
}
</style>
</head>
<body>
<button onclick="toggleDialog('#dialog')">Toggle Dialog</button>
<g-overlay id="dialog" class="dialog">
<g-overlay id="dialog" class="g-overlay-scale-slideup">
<h2>Dialog</h2>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed fringilla sapien sed enim sollicitudin laoreet. Suspendisse suscipit, metus ac volutpat sodales, libero magna semper lacus, molestie fringilla massa orci ut arcu. Nullam sodales urna sit amet odio vehicula mattis.</div><br><br>
<div>Ut aliquam vulputate congue. Vestibulum pretium pretium nulla quis sollicitudin. Praesent lacinia congue erat nec mattis. Fusce commodo lacus est. Duis turpis eros, ultrices sed aliquet non, blandit egestas velit. Integer a augue nec lorem tristique hendrerit. Curabitur imperdiet risus id enim bibendum vestibulum. Integer id magna at arcu faucibus fermentum vel a augue. Sed fringilla venenatis dolor, in blandit magna molestie luctus. Vestibulum dignissim posuere ultrices. Aenean urna nisl, tincidunt vitae iaculis ut, pharetra nec eros.</div><br><br>
@@ -118,20 +40,20 @@
<g-checkbox></g-checkbox>
I agree with this wholeheartedly.
</div><br><br>
<button onclick="toggleDialog('#dialog')">OK</button>
<button overlay-toggle>OK</button>
</g-overlay>
<br><br>
<button onclick="toggleDialog('#dialog2')">Toggle Dialog 2</button>
<g-overlay id="dialog2" class="dialog" showing="true">
<g-overlay id="dialog2" class="g-overlay-shake">
<h2>Dialog 2</h2>
I'm dizzy.
</div><br><br>
<button onclick="toggleDialog('#dialog2')">OK</button>
<button overlay-toggle>OK</button>
</g-overlay>
<script>
toggleDialog = function(inSlctr) {
var d = document.querySelector(inSlctr);
d.showing = !d.showing;
d.toggle();
}
</script>
</body>

93
workbench/panels.html Normal file
View File

@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html>
<head>
<title>Panels</title>
<script src="../../polyfills/Components/components-polyfill.js" shadow="webkit"></script>
<link rel="components" href="../src/g-panels.html">
<link rel="stylesheet" href="../src/css/g-panels.css" />
<style>
html, body {
height: 100%;
margin: 0;
background: whitesmoke;
}
body {
display: -webkit-flex;
-webkit-flex-flow: column;
opacity: 0;
}
.controls {
padding: 10px;
}
g-panels {
counter-reset: section;
-webkit-flex: 1;
outline: none;
border: 1px solid #ccc;
position: relative;
overflow: hidden;
font-size: 30px;
}
g-panels > * {
padding: 10px;
}
g-panels[transition="flow"] > * {
width: 80%;
-webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 4px 10px rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<div class="controls">
<button onclick="previous();">&laquo;</button>
<button onclick="next();">&raquo;</button>
<select onchange="changeTransition(event)">
<option selected>fade</option>
<option value="keyframe">hslide</option>
<option value="keyframe">vslide</option>
<option value="keyframe">hslideover</option>
<option value="keyframe">vslideover</option>
<option value="keyframe">explode</option>
<option value="keyframe">scale-slide</option>
<option value="keyframe">fly-up-right</option>
<option value="flow">flow</option>
</select>
</div>
<g-panels index="2" transition="keyframe" class="g-panels-fade">
<section name="foo" style="background: blue;">Panel 1</section>
<section name="zonk" style="background: red;">Panel 2</section>
<section name="bar" style="background: yellow;">Panel 3</section>
<section name="zing" style="background: black; color: white">Panel 4</section>
<section name="baz" style="background: white;">Panel 5</section>
</g-panels>
<script>
document.addEventListener("WebComponentsReady", function() {
document.body.style.opacity = 1;
var panels = document.querySelector("g-panels");
next = function() {
panels.next();
}
previous = function() {
panels.previous();
}
changeTransition = function(e) {
panels.transition = e.target.value;
var selectedOption = e.target.selectedOptions[0];
var className = selectedOption ? selectedOption.textContent : '';
panels.className = 'g-panels-' + className;
panels.focus();
}
panels.focus();
});
</script>
</body>
</html>

View File

@@ -6,14 +6,14 @@
<link rel="components" href="../../toolkit/src/g-tabs.html">
</head>
<body>
<g-tabs>
<g-tabs selected="0">
<span>One</span>
<span>Two</span>
<span>Three</span>
<span>Four</span>
</g-tabs>
<br><br>
<g-tabs vertical="true">
<g-tabs vertical="true" selected="0">
<span>One</span>
<span>Two</span>
<span>Three</span>