www.gusucode.com > 10多款支持进度条显示的CSS3按钮特效源码程序 > 10多款支持进度条显示的CSS3按钮特效/带进度条的按钮/带进度条的按钮/js/progressButton.js
/** * 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.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 ) { 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' ); }, 100 ); }; // enable button ProgressButton.prototype._enable = function() { this.button.removeAttribute( 'disabled' ); } // add to global namespace window.ProgressButton = ProgressButton; })( window );