150 lines
4.0 KiB
JavaScript
150 lines
4.0 KiB
JavaScript
/**
|
|
* uiMorphingButton_fixed.js v1.0.0
|
|
* http://www.codrops.com
|
|
*
|
|
* Licensed under the MIT license.
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
*
|
|
* Copyright 2014, Codrops
|
|
* http://www.codrops.com
|
|
*/
|
|
;( function( window ) {
|
|
|
|
'use strict';
|
|
|
|
var transEndEventNames = {
|
|
'WebkitTransition': 'webkitTransitionEnd',
|
|
'MozTransition': 'transitionend',
|
|
'OTransition': 'oTransitionEnd',
|
|
'msTransition': 'MSTransitionEnd',
|
|
'transition': 'transitionend'
|
|
},
|
|
transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
|
|
support = { transitions : Modernizr.csstransitions };
|
|
|
|
function extend( a, b ) {
|
|
for( var key in b ) {
|
|
if( b.hasOwnProperty( key ) ) {
|
|
a[key] = b[key];
|
|
}
|
|
}
|
|
return a;
|
|
}
|
|
|
|
function UIMorphingButton( el, options ) {
|
|
this.el = el;
|
|
this.options = extend( {}, this.options );
|
|
extend( this.options, options );
|
|
this._init();
|
|
}
|
|
|
|
UIMorphingButton.prototype.options = {
|
|
closeEl : '',
|
|
onBeforeOpen : function() { return false; },
|
|
onAfterOpen : function() { return false; },
|
|
onBeforeClose : function() { return false; },
|
|
onAfterClose : function() { return false; }
|
|
}
|
|
|
|
UIMorphingButton.prototype._init = function() {
|
|
// the button
|
|
this.button = this.el.querySelector( 'button' );
|
|
// state
|
|
this.expanded = false;
|
|
// content el
|
|
this.contentEl = this.el.querySelector( '.morph-content' );
|
|
// init events
|
|
this._initEvents();
|
|
}
|
|
|
|
UIMorphingButton.prototype._initEvents = function() {
|
|
var self = this;
|
|
// open
|
|
this.button.addEventListener( 'click', function() { self.toggle(); } );
|
|
// close
|
|
if( this.options.closeEl !== '' ) {
|
|
var closeEl = this.el.querySelector( this.options.closeEl );
|
|
if( closeEl ) {
|
|
closeEl.addEventListener( 'click', function() { self.toggle(); } );
|
|
}
|
|
}
|
|
}
|
|
|
|
UIMorphingButton.prototype.toggle = function() {
|
|
if( this.isAnimating ) return false;
|
|
|
|
// callback
|
|
if( this.expanded ) {
|
|
this.options.onBeforeClose();
|
|
}
|
|
else {
|
|
// add class active (solves z-index problem when more than one button is in the page)
|
|
classie.addClass( this.el, 'active' );
|
|
this.options.onBeforeOpen();
|
|
}
|
|
|
|
this.isAnimating = true;
|
|
|
|
var self = this,
|
|
onEndTransitionFn = function( ev ) {
|
|
if( ev.target !== this ) return false;
|
|
|
|
if( support.transitions ) {
|
|
// open: first opacity then width/height/left/top
|
|
// close: first width/height/left/top then opacity
|
|
if( self.expanded && ev.propertyName !== 'opacity' || !self.expanded && ev.propertyName !== 'width' && ev.propertyName !== 'height' && ev.propertyName !== 'left' && ev.propertyName !== 'top' ) {
|
|
return false;
|
|
}
|
|
this.removeEventListener( transEndEventName, onEndTransitionFn );
|
|
}
|
|
self.isAnimating = false;
|
|
|
|
// callback
|
|
if( self.expanded ) {
|
|
// remove class active (after closing)
|
|
classie.removeClass( self.el, 'active' );
|
|
self.options.onAfterClose();
|
|
}
|
|
else {
|
|
self.options.onAfterOpen();
|
|
}
|
|
|
|
self.expanded = !self.expanded;
|
|
};
|
|
|
|
if( support.transitions ) {
|
|
this.contentEl.addEventListener( transEndEventName, onEndTransitionFn );
|
|
}
|
|
else {
|
|
onEndTransitionFn();
|
|
}
|
|
|
|
// set the left and top values of the contentEl (same like the button)
|
|
var buttonPos = this.button.getBoundingClientRect();
|
|
// need to reset
|
|
classie.addClass( this.contentEl, 'no-transition' );
|
|
this.contentEl.style.left = 'auto';
|
|
this.contentEl.style.top = 'auto';
|
|
|
|
// add/remove class "open" to the button wraper
|
|
setTimeout( function() {
|
|
self.contentEl.style.left = buttonPos.left + 'px';
|
|
self.contentEl.style.top = buttonPos.top + 'px';
|
|
|
|
if( self.expanded ) {
|
|
classie.removeClass( self.contentEl, 'no-transition' );
|
|
classie.removeClass( self.el, 'open' );
|
|
}
|
|
else {
|
|
setTimeout( function() {
|
|
classie.removeClass( self.contentEl, 'no-transition' );
|
|
classie.addClass( self.el, 'open' );
|
|
}, 25 );
|
|
}
|
|
}, 25 );
|
|
}
|
|
|
|
// add to global namespace
|
|
window.UIMorphingButton = UIMorphingButton;
|
|
|
|
})( window ); |