Skip to content

Commit 30f3504

Browse files
committed
g-overlay:
- rename 'showing' property to 'opened' - simplify event listeners - style animations based on 'opened' and 'animating' attributes - add beginnings of library of open/close animations
1 parent 1b054f9 commit 30f3504

File tree

3 files changed

+177
-132
lines changed

3 files changed

+177
-132
lines changed

src/css/g-overlay.css

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2012 The Toolkitchen Authors. All rights reserved.
3+
* Use of this source code is governed by a BSD-style
4+
* license that can be found in the LICENSE file.
5+
*/
6+
7+
@host {
8+
position: fixed;
9+
z-index: 10;
10+
outline: none;
11+
}
12+
13+
/*
14+
TODO(sorvell): include a reasonable set of default overlay opening
15+
animations. What's here right now is ad hoc.
16+
*/
17+
@host.g-overlay-fade {
18+
opacity: 0;
19+
-webkit-transition: all 0.218s;
20+
}
21+
22+
@host.g-overlay-fade[opened] {
23+
opacity: 1;
24+
}
25+
26+
@host.g-overlay-scale-slideup {
27+
opacity: 0.0;
28+
-webkit-transform: scale(1.05);
29+
-webkit-transition: all 0.218s;
30+
}
31+
32+
@host.g-overlay-scale-slideup[opened] {
33+
opacity: 1.0;
34+
-webkit-transform: scale(1.0);
35+
}
36+
37+
@host.g-overlay-scale-slideup:not([opened])[animating] {
38+
opacity: 0;
39+
-webkit-transform: translateY(-100%);
40+
-webkit-transition: all 1s;
41+
}
42+
43+
@-webkit-keyframes g-overlay-shakeFadeIn {
44+
0% {
45+
display: block;
46+
opacity: 0;
47+
-webkit-transform: translateX(0);
48+
}
49+
10% {
50+
display: block;
51+
-webkit-transform: translateX(-50px);
52+
}
53+
30% {
54+
display: block;
55+
-webkit-transform: translateX(50px);
56+
}
57+
50% {
58+
display: block;
59+
-webkit-transform: translateX(-25px);
60+
}
61+
70% {
62+
display: block;
63+
-webkit-transform: translateX(25px);
64+
}
65+
90% {
66+
display: block;
67+
-webkit-transform: translateX(-13px);
68+
}
69+
100% {
70+
display: block;
71+
-webkit-transform: translateX(0);
72+
opacity: 1;
73+
}
74+
}
75+
76+
@-webkit-keyframes g-overlay-shakeFadeOut {
77+
0% {
78+
opacity: 1;
79+
-webkit-transform: translateX(0);
80+
}
81+
10% {
82+
-webkit-transform: translateX(-50px);
83+
}
84+
30% {
85+
-webkit-transform: translateX(50px);
86+
}
87+
100% {
88+
-webkit-transform: translateX(-100%);
89+
opacity: 0;
90+
}
91+
}
92+
93+
@host.g-overlay-shake[opened] {
94+
-webkit-animation-duration: 0.5s;
95+
-webkit-animation-fill-mode: both;
96+
-webkit-animation-name: g-overlay-shakeFadeIn;
97+
}
98+
99+
@host.g-overlay-shake:not([opened])[animating] {
100+
-webkit-animation-duration: 0.3s;
101+
-webkit-animation-fill-mode: both;
102+
-webkit-animation-name: g-overlay-shakeFadeOut;
103+
}

src/g-overlay.html

+65-45
Original file line numberDiff line numberDiff line change
@@ -5,70 +5,90 @@
55
* license that can be found in the LICENSE file.
66
*/
77
-->
8-
<element name="g-overlay" attributes="showing, timeout">
8+
<element name="g-overlay" attributes="opened, timeout"
9+
handlers="click: clickHandler, keydown: keydownHandler,
10+
webkitAniamtionEnd: finishAnimate, webkitTransitionEnd: finishAnimate">
911
<link rel="components" href="g-component.html">
12+
<link rel="stylesheet" href="css/g-overlay.css">
1013
<template>
11-
<style scoped>
12-
@host {
13-
position: absolute;
14-
z-index: 10;
15-
}
16-
</style>
1714
<content></content>
1815
</template>
1916
<script>
17+
// TODO(sorvell): promote this if it becomes a pattern
18+
var setBooleanAttribute = function(inNode, inName, inValue) {
19+
inNode[inValue ? 'setAttribute' : 'removeAttribute'](inName, '');
20+
};
21+
22+
// TODO(sorvell): is there a more new-fangled way to do this?
23+
var makeFocusable = function(inNode) {
24+
if (!inNode.hasAttribute('tabIndex')) {
25+
inNode.setAttribute('tabIndex', -1);
26+
}
27+
}
28+
29+
/**
30+
* The overlay component is hidden by default and can be opened to display
31+
* its content. It's common to animate an overlay opened and closed. This
32+
* can be achieved by styling the overlay node via the `opened` and
33+
* `animating` attributes.
34+
*/
2035
this.component({
2136
shadowRootCreated: function() {
2237
this.hidden = true;
2338
},
39+
created: function() {
40+
makeFocusable(this);
41+
},
2442
prototype: {
43+
//* Timeout (ms) for animation. After timeout, any opening animation will
44+
//* be aborted and overlay will be set to opened or not and not animating.
2545
timeout: 1000,
26-
showingChanged: function() {
27-
this.animateShowing();
28-
webkitRequestAnimationFrame(this.fireShowingChange.bind(this));
29-
},
30-
dispatch: function(inName, inDetail) {
31-
this.dispatchEvent(new CustomEvent(inName, {
32-
bubbles: true,
33-
detail: inDetail
34-
}));
35-
},
36-
fireShowingChange: function() {
37-
this.dispatch("showingChange", {
38-
showing: this.showing,
39-
rect: this.getBoundingClientRect()
40-
});
46+
openedChanged: function() {
47+
this.startAnimation();
48+
// TODO(sorvell): need a controllable api for this, including
49+
// maybe focusElement.
50+
if (this.opened) {
51+
this.focus();
52+
}
53+
this.fireEvent('openedChanged', {opened: this.opened});
4154
},
42-
animateShowing: function() {
55+
startAnimation: function() {
56+
this.cancelAnimation();
4357
this.hidden = false;
4458
webkitRequestAnimationFrame(function() {
45-
var setBooleanAttribute = function(inNode, inName, inValue) {
46-
inNode[inValue ? "setAttribute" : "removeAttribute"](inName, "");
47-
};
48-
setBooleanAttribute(this, "opening", this.showing);
49-
setBooleanAttribute(this, "closing", !this.showing);
50-
this.unlisten();
51-
this.listen();
59+
setBooleanAttribute(this, 'opened', this.opened);
60+
setBooleanAttribute(this, 'animating', true);
61+
this._animating = setTimeout(this.finishAnimate.bind(this), this.timeout);
5262
}.bind(this));
5363
},
54-
listen: function() {
55-
this.animationListener = this.finishAnimate.bind(this);
56-
this.addEventListener("webkitAnimationEnd", this.animationListener);
57-
this.addEventListener("webkitTransitionEnd", this.animationListener);
58-
// always finish animation within timeout
59-
this.jobId = this.utils.job(this.jobId, this.animationListener, this.timeout);
60-
},
6164
finishAnimate: function() {
62-
if (!this.showing) {
63-
this.hidden = true;
64-
this.classList.remove(this.hideClass);
65+
if (this._animating) {
66+
this.cancelAnimation();
67+
setBooleanAttribute(this, 'animating', false);
68+
if (!this.opened) {
69+
this.hidden = true;
70+
}
6571
}
66-
this.unlisten();
6772
},
68-
unlisten: function() {
69-
this.removeEventListener("webkitAnimationEnd", this.animationListener);
70-
this.removeEventListener("webkitTransitionEnd", this.animationListener);
71-
this.utils.job.stop(this.jobId);
73+
cancelAnimation: function() {
74+
if (this._animating) {
75+
clearTimeout(this._animating);
76+
this._animating = null;
77+
}
78+
},
79+
//* Toggle the opened state of the overlay.
80+
toggle: function() {
81+
this.opened = !this.opened;
82+
},
83+
clickHandler: function(e) {
84+
if (e.target && e.target.hasAttribute('overlay-toggle')) {
85+
this.toggle();
86+
}
87+
},
88+
keydownHandler: function(e) {
89+
if (e.keyCode == 27) {
90+
this.opened = false;
91+
}
7292
}
7393
}
7494
});

workbench/overlay.html

+9-87
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<title>Overlay</title>
55
<script src="../../polyfills/Components/components-polyfill.js" shadow="shim"></script>
66
<link rel="components" href="../../toolkit/src/g-overlay.html">
7+
<link rel="stylesheet" href="../../toolkit/src/css/g-overlay.css">
78
<style>
89
body {
910
font-family: Arial, Helvetica, sans-serif;
@@ -12,8 +13,8 @@
1213
font-size: 13px;
1314
}
1415

15-
.dialog {
16-
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
16+
#dialog, #dialog2 {
17+
box-shadow: 0 4px 16px rgba(0,0,0,0.2);
1718
background: white;
1819
left: 50%;
1920
outline: 1px solid rgba(0,0,0,0.2);
@@ -26,112 +27,33 @@
2627
z-index: 100;
2728
top: 72px;
2829
margin-left: -256px;
29-
30-
/*display: none;*/
31-
opacity: 0.0;
32-
-webkit-transform: scale(1.05);
33-
-webkit-transition: all 0.218s;
34-
}
35-
36-
#dialog[opening] {
37-
opacity: 1.0;
38-
-webkit-transform: scale(1.0);
39-
}
40-
41-
#dialog[closing] {
42-
opacity: 0;
43-
-webkit-transform: translateY(-100%);
44-
-webkit-transition: all 1s;
45-
}
46-
47-
@-webkit-keyframes shakeFadeIn {
48-
0% {
49-
display: block;
50-
opacity: 0;
51-
-webkit-transform: translateX(0);
52-
}
53-
10% {
54-
display: block;
55-
-webkit-transform: translateX(-50px);
56-
}
57-
30% {
58-
display: block;
59-
-webkit-transform: translateX(50px);
60-
}
61-
50% {
62-
display: block;
63-
-webkit-transform: translateX(-25px);
64-
}
65-
70% {
66-
display: block;
67-
-webkit-transform: translateX(25px);
68-
}
69-
90% {
70-
display: block;
71-
-webkit-transform: translateX(-13px);
72-
}
73-
100% {
74-
display: block;
75-
-webkit-transform: translateX(0);
76-
opacity: 1;
77-
}
78-
}
79-
80-
@-webkit-keyframes shakeFadeOut {
81-
0% {
82-
opacity: 1;
83-
-webkit-transform: translateX(0);
84-
}
85-
10% {
86-
-webkit-transform: translateX(-50px);
87-
}
88-
30% {
89-
-webkit-transform: translateX(50px);
90-
}
91-
100% {
92-
-webkit-transform: translateX(-100%);
93-
opacity: 0;
94-
}
95-
}
96-
97-
#dialog2[opening] {
98-
-webkit-animation-duration: 0.5s;
99-
-webkit-animation-fill-mode: both;
100-
-webkit-animation-name: shakeFadeIn;
101-
}
102-
103-
#dialog2[closing] {
104-
-webkit-animation-duration: 0.3s;
105-
-webkit-animation-fill-mode: both;
106-
-webkit-animation-name: shakeFadeOut;
107-
}
108-
30+
}
10931
</style>
11032
</head>
11133
<body>
11234
<button onclick="toggleDialog('#dialog')">Toggle Dialog</button>
113-
<g-overlay id="dialog" class="dialog">
35+
<g-overlay id="dialog" class="g-overlay-scale-slideup">
11436
<h2>Dialog</h2>
11537
<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>
11638
<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>
11739
<div>
11840
<g-checkbox></g-checkbox>
11941
I agree with this wholeheartedly.
12042
</div><br><br>
121-
<button onclick="toggleDialog('#dialog')">OK</button>
43+
<button overlay-toggle>OK</button>
12244
</g-overlay>
12345
<br><br>
12446
<button onclick="toggleDialog('#dialog2')">Toggle Dialog 2</button>
125-
<g-overlay id="dialog2" class="dialog" showing="true">
47+
<g-overlay id="dialog2" class="g-overlay-shake">
12648
<h2>Dialog 2</h2>
12749
I'm dizzy.
12850
</div><br><br>
129-
<button onclick="toggleDialog('#dialog2')">OK</button>
51+
<button overlay-toggle>OK</button>
13052
</g-overlay>
13153
<script>
13254
toggleDialog = function(inSlctr) {
13355
var d = document.querySelector(inSlctr);
134-
d.showing = !d.showing;
56+
d.toggle();
13557
}
13658
</script>
13759
</body>

0 commit comments

Comments
 (0)