| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /**
- * progressButton.js v1.0.0
- * http://www.codrops.com
- *
- * Licensed under the MIT license.
- * http://www.opensource.org/licenses/mit-license.php
- *
- * Copyright 2013, Codrops
- * http://www.codrops.com
- */
-
- ;( function( window ) {
- 'use strict';
- // https://gist.github.com/edankwan/4389601
- Modernizr.addTest('csstransformspreserve3d', function () {
- var prop = Modernizr.prefixed('transformStyle');
- var val = 'preserve-3d';
- var computedStyle;
- if(!prop) return false;
- prop = prop.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
- Modernizr.testStyles('#modernizr{' + prop + ':' + val + ';}', function (el, rule) {
- computedStyle = window.getComputedStyle ? getComputedStyle(el, null).getPropertyValue(prop) : '';
- });
- return (computedStyle === val);
- });
- function extend( a, b ) {
- for( var key in b ) {
- if( b.hasOwnProperty( key ) ) {
- a[key] = b[key];
- }
- }
- return a;
- }
- // support
- var support = { transitions : Modernizr.csstransitions, transforms3d : Modernizr.csstransforms3d && Modernizr.csstransformspreserve3d },
- // transition end event name
- transEndEventNames = {
- 'WebkitTransition': 'webkitTransitionEnd',
- 'MozTransition': 'transitionend',
- 'OTransition': 'oTransitionEnd',
- 'msTransition': 'MSTransitionEnd',
- 'transition': 'transitionend'
- },
- transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ];
- function ProgressButton( el, options ) {
- this.button = el;
- this.options = extend( {}, this.options );
- extend( this.options, options );
- this._init();
- }
- ProgressButton.prototype.options = {
- // time in ms that the status (success or error will be displayed)
- // during this time the button will be disabled
- statusTime : 1500
- };
- ProgressButton.prototype._init = function() {
- this._validate();
- // create structure
- this._create();
- // init events
- this._initEvents();
- };
- ProgressButton.prototype._validate = function() {
- // we will consider the fill/horizontal as default
- if( this.button.getAttribute( 'data-style' ) === null ) {
- this.button.setAttribute( 'data-style', 'fill' );
- }
- if( this.button.getAttribute( 'data-vertical' ) === null && this.button.getAttribute( 'data-horizontal' ) === null ) {
- this.button.setAttribute( 'data-horizontal', '' );
- }
- if( !support.transforms3d && this.button.getAttribute( 'data-perspective' ) !== null ) {
- this.button.removeAttribute( 'data-perspective' );
- this.button.setAttribute( 'data-style', 'fill' );
- this.button.removeAttribute( 'data-vertical' );
- this.button.setAttribute( 'data-horizontal', '' );
- }
- };
- ProgressButton.prototype._create = function() {
- var textEl = document.createElement( 'span' );
- textEl.className = 'content';
- textEl.id = 'button_content';
- textEl.innerHTML = this.button.innerHTML;
- var progressEl = document.createElement( 'span' );
- progressEl.className = 'progress';
- var progressInnerEl = document.createElement( 'span' );
- progressInnerEl.className = 'progress-inner';
- progressEl.appendChild( progressInnerEl );
- // clear content
- this.button.innerHTML = '';
- if( this.button.getAttribute( 'data-perspective' ) !== null ) {
- var progressWrapEl = document.createElement( 'span' );
- progressWrapEl.className = 'progress-wrap';
- progressWrapEl.appendChild( textEl );
- progressWrapEl.appendChild( progressEl );
- this.button.appendChild( progressWrapEl );
- }
- else {
- this.button.appendChild( textEl );
- this.button.appendChild( progressEl );
- }
- // the element that serves as the progress bar
- this.progress = progressInnerEl;
- // property to change on the progress element
- if( this.button.getAttribute( 'data-horizontal' ) !== null ) {
- this.progressProp = 'width';
- }
- else if( this.button.getAttribute( 'data-vertical' ) !== null ) {
- this.progressProp = 'height';
- }
- this._enable();
- };
- ProgressButton.prototype._setProgress = function( val ) {
- /* Speed controlled by CSS settings */
- // console.log('Val: ' +val);
- this.progress.style[ this.progressProp ] = 100 * val + '%';
- };
- ProgressButton.prototype._initEvents = function() {
- var self = this;
- this.button.addEventListener( 'click', function() {
- // disable the button
- self.button.setAttribute( 'disabled', '' );
- // add class state-loading to the button (applies a specific transform to the button depending which data-style is defined - defined in the stylesheets)
- classie.remove( self.progress, 'notransition' );
- classie.add( this, 'state-loading' );
- setTimeout( function() {
- if( typeof self.options.callback === 'function' ) {
- self.options.callback( self );
- }
- else {
- self._setProgress( 1 );
- var onEndTransFn = function( ev ) {
- if( support.transitions && ev.propertyName !== self.progressProp ) return;
- this.removeEventListener( transEndEventName, onEndTransFn );
- self._stop();
- };
- if( support.transitions ) {
- self.progress.addEventListener( transEndEventName, onEndTransFn );
- }
- else {
- onEndTransFn.call();
- }
- }
- },
- self.button.getAttribute( 'data-style' ) === 'fill' ||
- self.button.getAttribute( 'data-style' ) === 'top-line' ||
- self.button.getAttribute( 'data-style' ) === 'lateral-lines' ? 0 : 200 ); // TODO: change timeout to transitionend event callback
- } );
- };
- ProgressButton.prototype._stop = function( status ) {
- var self = this;
- setTimeout( function() {
- // fade out progress bar
- self.progress.style.opacity = 0;
- var onEndTransFn = function( ev ) {
- if( support.transitions && ev.propertyName !== 'opacity' ) return;
- this.removeEventListener( transEndEventName, onEndTransFn );
- classie.add( self.progress, 'notransition' );
- self.progress.style[ self.progressProp ] = '0%';
- self.progress.style.opacity = 1;
- };
- if( support.transitions ) {
- self.progress.addEventListener( transEndEventName, onEndTransFn );
- }
- else {
- onEndTransFn.call();
- }
- // add class state-success to the button
- if( typeof status === 'number' ) {
- var statusClass = status >= 0 ? 'state-success' : 'state-error';
- classie.add( self.button, statusClass );
- // after options.statusTime remove status
- setTimeout( function() {
- classie.remove( self.button, statusClass );
- // self._enable();
- }, self.options.statusTime );
- }
- else {
- self._enable();
- }
- // remove class state-loading from the button
- classie.remove( self.button, 'state-loading' );
- }, 500 );
- };
- // enable button
- ProgressButton.prototype._enable = function() {
- this.button.removeAttribute( 'disabled' );
- };
- // add to global namespace
- window.ProgressButton = ProgressButton;
- })( window );
|