1/** 2 * progressButton.js v1.0.0 3 * http://www.codrops.com 4 * 5 * Licensed under the MIT license. 6 * http://www.opensource.org/licenses/mit-license.php 7 * 8 * Copyright 2013, Codrops 9 * http://www.codrops.com 10 */ 11;( function( window ) { 12 13 'use strict'; 14 15 // https://gist.github.com/edankwan/4389601 16 Modernizr.addTest('csstransformspreserve3d', function () { 17 var prop = Modernizr.prefixed('transformStyle'); 18 var val = 'preserve-3d'; 19 var computedStyle; 20 if(!prop) return false; 21 22 prop = prop.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); 23 24 Modernizr.testStyles('#modernizr{' + prop + ':' + val + ';}', function (el, rule) { 25 computedStyle = window.getComputedStyle ? getComputedStyle(el, null).getPropertyValue(prop) : ''; 26 }); 27 28 return (computedStyle === val); 29 }); 30 31 function extend( a, b ) { 32 for( var key in b ) { 33 if( b.hasOwnProperty( key ) ) { 34 a[key] = b[key]; 35 } 36 } 37 return a; 38 } 39 40 // support 41 var support = { transitions : Modernizr.csstransitions, transforms3d : Modernizr.csstransforms3d && Modernizr.csstransformspreserve3d }, 42 // transition end event name 43 transEndEventNames = { 44 'WebkitTransition': 'webkitTransitionEnd', 45 'MozTransition': 'transitionend', 46 'OTransition': 'oTransitionEnd', 47 'msTransition': 'MSTransitionEnd', 48 'transition': 'transitionend' 49 }, 50 transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ]; 51 52 function ProgressButton( el, options ) { 53 this.button = el; 54 this.options = extend( {}, this.options ); 55 extend( this.options, options ); 56 this._init(); 57 } 58 59 ProgressButton.prototype.options = { 60 // time in ms that the status (success or error will be displayed) 61 // during this time the button will be disabled 62 statusTime : 1500 63 }; 64 65 ProgressButton.prototype._init = function() { 66 this._validate(); 67 // create structure 68 this._create(); 69 // init events 70 this._initEvents(); 71 }; 72 73 ProgressButton.prototype._validate = function() { 74 // fancy style-rotate effect is default 75 if(!this.button.classList.contains('style-rotate') && !this.button.classList.contains('style-fill')) 76 { 77 this.button.classList.add('style-rotate'); 78 this.button.classList.add('perspective'); 79 } 80 if( !support.transforms3d && this.button.classList.contains( 'perspective' ) ) { 81 this.button.classList.remove('perspective'); 82 this.button.classList.remove('style-rotate'); 83 this.button.classList.add('style-fill'); 84 } 85 }; 86 87 ProgressButton.prototype._create = function() { 88 var textEl = document.createElement( 'span' ); 89 textEl.className = 'content'; 90 textEl.innerHTML = this.button.innerHTML; 91 var progressEl = document.createElement( 'span' ); 92 progressEl.className = 'progress'; 93 94 var progressInnerEl = document.createElement( 'span' ); 95 progressInnerEl.className = 'progress-inner'; 96 progressEl.appendChild( progressInnerEl ); 97 // clear content 98 this.button.innerHTML = ''; 99 100 if( this.button.classList.contains( 'perspective' ) !== null ) { 101 var progressWrapEl = document.createElement( 'span' ); 102 progressWrapEl.className = 'progress-wrap'; 103 progressWrapEl.appendChild( textEl ); 104 progressWrapEl.appendChild( progressEl ); 105 this.button.appendChild( progressWrapEl ); 106 } 107 else { 108 this.button.appendChild( textEl ); 109 this.button.appendChild( progressEl ); 110 } 111 112 // the element that serves as the progress bar 113 this.progress = progressInnerEl; 114 115 // property to change on the progress element 116 this.progressProp = 'width'; 117 this._enable(); 118 }; 119 120 ProgressButton.prototype._setProgress = function( val ) { 121 this.progress.style[ this.progressProp ] = 100 * val + '%'; 122 }; 123 124 ProgressButton.prototype._initEvents = function() { 125 var self = this; 126 this.button.addEventListener( 'click', function() { 127 // disable the button 128 self.button.disabled = true; 129 // add class state-loading to the button (applies a specific transform to the button depending which data-style is defined - defined in the stylesheets) 130 self.progress.classList.remove( 'notransition' ); 131 this.classList.add( 'state-loading' ); 132 133 setTimeout( function() { 134 if( typeof self.options.callback === 'function' ) { 135 self.options.callback( self ); 136 } 137 else { 138 self._setProgress( 1 ); 139 var onEndTransFn = function( ev ) { 140 if( support.transitions && ev.propertyName !== self.progressProp ) return; 141 this.removeEventListener( transEndEventName, onEndTransFn ); 142 self._stop(); 143 }; 144 145 if( support.transitions ) { 146 self.progress.addEventListener( transEndEventName, onEndTransFn ); 147 } 148 else { 149 onEndTransFn.call(); 150 } 151 } 152 }, 153 self.button.classList.contains( 'style-fill' ) ? 0 : 200 ); // TODO: change timeout to transitionend event callback 154 } ); 155 }; 156 157 ProgressButton.prototype._stop = function( status ) { 158 var self = this; 159 160 setTimeout( function() { 161 // fade out progress bar 162 self.progress.style.opacity = 0; 163 var onEndTransFn = function( ev ) { 164 if( support.transitions && ev.propertyName !== 'opacity' ) return; 165 this.removeEventListener( transEndEventName, onEndTransFn ); 166 self.progress.classList.add( 'notransition' ); 167 self.progress.style[ self.progressProp ] = '0%'; 168 self.progress.style.opacity = 1; 169 }; 170 171 if( support.transitions ) { 172 self.progress.addEventListener( transEndEventName, onEndTransFn ); 173 } 174 else { 175 onEndTransFn.call(); 176 } 177 178 179 // add class state-success to the button 180 if( typeof status === 'boolean' ) { 181 var statusClass = status ? 'state-success' : 'state-error';
182 self.button.classList.add( statusClass ); 183 // after options.statusTime remove status 184 setTimeout( function() { 185 self.button.classList.remove( statusClass ); 186 self._enable(); 187 }, self.options.statusTime ); 188 } 189 else { 190 self._enable(); 191 } 192 193 // remove class state-loading from the button 194 self.button.classList.remove( 'state-loading' ); 195 }, 100 ); 196 }; 197 198 // enable button 199 ProgressButton.prototype._enable = function() { 200 this.button.disabled = false; 201 } 202 203 // add to global namespace 204 window.ProgressButton = ProgressButton; 205 206})( window );
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.