Skip to content

Instantly share code, notes, and snippets.

@ivolivares
Forked from kaaes/popup.html
Created March 23, 2014 20:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivolivares/9729462 to your computer and use it in GitHub Desktop.
Save ivolivares/9729462 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<link href="style.css" rel="stylesheet" />
<body>
<button id="open">click!</button>
<div id="popup" class="closed"><button id="close">click!</button></div>
</body>
<script src="popup.js"></script>
<script>
var p = document.getElementById('popup');
var o = document.getElementById('open');
var c = document.getElementById('close');
var popup = new PopupAnimation(p);
popup.onOpenStart = onOpenPopupStart;
popup.onCloseStart = onClosePopupStart;
o.addEventListener('click', openPopup);
c.addEventListener('click', closePopup);
function openPopup() {
if (!popup.isOpen) { popup.open(); }
}
function closePopup() {
if (popup.isOpen) { popup.close(); }
}
function onOpenPopupStart() {
console.log('opening started');
document.body.addEventListener('click', onClickOutsidePopup);
}
function onClosePopupStart() {
console.log('closing started');
document.body.removeEventListener('click', onClickOutsidePopup);
}
function onClickOutsidePopup(evt) {
console.log(evt);
var mouseX = evt.clientX;
var mouseY = evt.clientY;
if (!popup.containsPoint(mouseX, mouseY)) {
popup.close();
}
}
</script>
</html>
function PopupAnimation(element) {
this.element = element;
this.element.classList.add('popup-window');
this.isOpen = this.element.classList.contains(this.classes.open);
this.addPrefixedEvent(this.element, 'AnimationStart', this.onAnimationEvent.bind(this))
this.addPrefixedEvent(this.element, 'AnimationEnd', this.onAnimationEvent.bind(this))
this.open = this.open.bind(this);
this.close = this.close.bind(this);
}
PopupAnimation.prototype.classes = {
ongoing: 'ongoing',
closed: 'closed',
open: 'open',
closing: 'closing',
opening: 'opening'
};
PopupAnimation.prototype.addPrefixedEvent = function(element, type, callback) {
var pfx = ["webkit", "moz", "MS", "o", ""];
for (var p = 0; p < pfx.length; p++) {
if (!pfx[p]) {
type = type.toLowerCase();
}
element.addEventListener(pfx[p] + type, callback, false);
}
};
PopupAnimation.prototype.onAnimationEvent = function(evt) {
var element = evt.currentTarget;
if (evt.type.toLowerCase().indexOf('animationstart') > -1) {
this.ongoing = true;
element.classList.add(this.classes.ongoing);
if (element.classList.contains(this.classes.opening) && typeof this.onOpenStart === 'function') {
this.onOpenStart();
}
if (element.classList.contains(this.classes.closing) && typeof this.onCloseStart === 'function') {
this.onCloseStart();
}
element.classList.remove(this.classes.open);
element.classList.remove(this.classes.closed);
}
else if (evt.type.toLowerCase().indexOf('animationend') > -1) {
this.ongoing = false;
if (element.classList.contains(this.classes.closing)) {
element.classList.add(this.classes.closed);
this.isOpen = false;
if (typeof this.onCloseEnd === 'function') {
this.onCloseEnd();
}
}
if (element.classList.contains(this.classes.opening)) {
element.classList.add(this.classes.open);
this.isOpen = true;
if (typeof this.onOpenEnd === 'function') {
this.onOpenEnd();
}
}
element.classList.remove(this.classes.opening);
element.classList.remove(this.classes.closing);
element.classList.remove(this.classes.ongoing);
}
};
PopupAnimation.prototype.open = function() {
this.element.classList.remove(this.classes.closed);
this.element.classList.add(this.classes.opening);
};
PopupAnimation.prototype.close = function() {
this.element.classList.remove(this.classes.open);
this.element.classList.add(this.classes.closing);
};
PopupAnimation.prototype.onOpenStart = function() { /* overwrite for the instance */ }
PopupAnimation.prototype.onOpenEnd = function() { /* overwrite for the instance */ }
PopupAnimation.prototype.onCloseStart = function() { /* overwrite for the instance */ }
PopupAnimation.prototype.onCloseEnd = function() { /* overwrite for the instance */ }
PopupAnimation.prototype.clickWithinPopup = function(evt) {
var el = evt.target;
if (el === this.element) {
return true;
}
el = el.parentNode;
while (el !== null) {
if (el == this.element) {
return true;
}
el = el.parentNode;
}
return false;
};
exports.PopupAnimation = PopupAnimation;
html {
/* without that and same on body good luc wih listening on click on whole page */
width: 100%;
height: 100%;
}
body {
position: relative;
/* see html */
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#popup {
width: 300px;
height: 200px;
background: #ccc;
position: absolute;
top: 50px;
left: 200px;
margin-top: 0;
}
/** ANIMATION RULES **/
.popup-window.closed, .popup-window.closing {
-webkit-transform: scale(0);
-moz-transform: scale(0);
-o-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
}
.popup-window.open, .popup-window.opening {
-webkit-transform: scale(1.0);
-moz-transform: scale(1.0);
-o-transform: scale(1.0);
-ms-transform: scale(1.0);
transform: scale(1.0);
}
.popup-window.opening {
-webkit-animation: grow .3s ease-out;
-moz-animation: grow .3s ease-out;
-o-animation: grow .3s ease-out;
-ms-animation: grow .3s ease-out;
animation: grow .3s ease-out;
}
.popup-window.closing {
-webkit-animation: shrink .3s ease-out;
-moz-animation: shrink .3s ease-out;
-o-animation: shrink .3s ease-out;
-ms-animation: shrink .3s ease-out;
animation: shrink .3s ease-out;
}
@-webkit-keyframes grow {
from {
-webkit-transform: scale(0);
margin-top: -100px;
}
80% {
-webkit-transform: scale(1.05);
margin-top: 0;
}
to {
-webkit-transform: scale(1.0);
}
}
@-moz-keyframes grow {
from {
-moz-transform: scale(0);
margin-top: -100px;
}
80% {
-moz-transform: scale(1.05);
margin-top: 0;
}
to {
-moz-transform: scale(1.0);
}
}
@-o-keyframes grow {
from {
-o-transform: scale(0);
margin-top: -100px;
}
80% {
-o-transform: scale(1.05);
margin-top: 0;
}
to {
-o-transform: scale(1.0);
}
}
@-ms-keyframes grow {
from {
-ms-transform: scale(0);
margin-top: -100px;
}
80% {
-ms-transform: scale(1.05);
margin-top: 0;
}
to {
-ms-transform: scale(1.0);
}
}
@keyframes grow {
from {
transform: scale(0);
margin-top: -100px;
}
80% {
transform: scale(1.05);
margin-top: 0;
}
to {
transform: scale(1.0);
}
}
/* How to reverse the animation n the first iteration? */
@-webkit-keyframes shrink {
from {
-webkit-transform: scale(1.0);
margin-top: 0;
}
20% {
-webkit-transform: scale(1.05);
margin-top: 0;
}
to {
-webkit-transform: scale(0);
margin-top: -100px;
}
}
@-moz-keyframes shrink {
from {
-moz-transform: scale(1.0);
margin-top: 0;
}
20% {
-moz-transform: scale(1.05);
margin-top: 0;
}
to {
-moz-transform: scale(0);
margin-top: -100px;
}
}
@-o-keyframes shrink {
from {
-o-transform: scale(1.0);
margin-top: 0;
}
20% {
-o-transform: scale(1.05);
margin-top: 0;
}
to {
-o-transform: scale(0);
margin-top: -100px;
}
}
@-ms-keyframes shrink {
from {
-ms-transform: scale(1.0);
margin-top: 0;
}
20% {
-ms-transform: scale(1.05);
margin-top: 0;
}
to {
-ms-transform: scale(0);
margin-top: -100px;
}
}
@keyframes shrink {
from {
transform: scale(1.0);
margin-top: 0;
}
20% {
transform: scale(1.05);
margin-top: 0;
}
to {
transform: scale(0);
margin-top: -100px;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment