1/*! 2 * Ladda 0.8.0 3 * http://lab.hakim.se/ladda 4 * MIT licensed 5 * 6 * Copyright (C) 2013 Hakim El Hattab, http://hakim.se 7 */ 8(function( root, factory ) { 9 10 // CommonJS 11 if( typeof exports === 'object' ) { 12 module.exports = factory(); 13 } 14 // AMD module 15 else if( typeof define === 'function' && define.amd ) { 16 define( [ 'spin' ], factory ); 17 } 18 // Browser global 19 else { 20 root.Ladda = factory( root.Spinner ); 21 } 22 23} 24(this, function( Spinner ) { 25 'use strict'; 26 27 // All currently instantiated instances of Ladda 28 var ALL_INSTANCES = []; 29 30 /** 31 * Creates a new instance of Ladda which wraps the 32 * target button element. 33 * 34 * @return An API object that can be used to control 35 * the loading animation state. 36 */ 37 function create( button ) { 38 39 if( typeof button === 'undefined' ) { 40 console.warn( "Ladda button target must be defined." ); 41 return; 42 } 43 44 // The text contents must be wrapped in a ladda-label 45 // element, create one if it doesn't already exist 46 if( !button.querySelector( '.ladda-label' ) ) { 47 button.innerHTML = '<span class="ladda-label">'+ button.innerHTML +'</span>'; 48 } 49 50 // Create the spinner 51 var spinner = createSpinner( button ); 52 53 // Wrapper element for the spinner 54 var spinnerWrapper = document.createElement( 'span' ); 55 spinnerWrapper.className = 'ladda-spinner'; 56 button.appendChild( spinnerWrapper ); 57 58 // Timer used to delay starting/stopping 59 var timer; 60 61 var instance = { 62 63 /** 64 * Enter the loading state. 65 */ 66 start: function() { 67 68 button.setAttribute( 'disabled', '' ); 69 button.setAttribute( 'data-loading', '' ); 70 71 clearTimeout( timer ); 72 spinner.spin( spinnerWrapper ); 73 74 this.setProgress( 0 ); 75 76 return this; // chain 77 78 }, 79 80 /** 81 * Enter the loading state, after a delay. 82 */ 83 startAfter: function( delay ) { 84 85 clearTimeout( timer ); 86 timer = setTimeout( function() { instance.start(); }, delay ); 87 88 return this; // chain 89 90 }, 91 92 /** 93 * Exit the loading state. 94 */ 95 stop: function() { 96 97 button.removeAttribute( 'disabled' ); 98 button.removeAttribute( 'data-loading' ); 99 100 // Kill the animation after a delay to make sure it 101 // runs for the duration of the button transition 102 clearTimeout( timer ); 103 timer = setTimeout( function() { spinner.stop(); }, 1000 ); 104 105 return this; // chain 106 107 }, 108 109 /** 110 * Toggle the loading state on/off. 111 */ 112 toggle: function() { 113 114 if( this.isLoading() ) { 115 this.stop(); 116 } 117 else { 118 this.start(); 119 } 120 121 return this; // chain 122 123 }, 124 125 /** 126 * Sets the width of the visual progress bar inside of 127 * this Ladda button 128 * 129 * @param {Number} progress in the range of 0-1 130 */ 131 setProgress: function( progress ) { 132 133 // Cap it 134 progress = Math.max( Math.min( progress, 1 ), 0 ); 135 136 var progressElement = button.querySelector( '.ladda-progress' ); 137 138 // Remove the progress bar if we're at 0 progress 139 if( progress === 0 && progressElement && progressElement.parentNode ) { 140 progressElement.parentNode.removeChild( progressElement ); 141 } 142 else { 143 if( !progressElement ) { 144 progressElement = document.createElement( 'div' ); 145 progressElement.className = 'ladda-progress'; 146 button.appendChild( progressElement ); 147 } 148 149 progressElement.style.width = ( ( progress || 0 ) * button.offsetWidth ) + 'px'; 150 } 151 152 }, 153 154 enable: function() { 155 156 this.stop(); 157 158 return this; // chain 159 160 }, 161 162 disable: function () { 163 164 this.stop(); 165 button.setAttribute( 'disabled', '' ); 166 167 return this; // chain 168 169 }, 170 171 isLoading: function() { 172 173 return button.hasAttribute( 'data-loading' ); 174 175 } 176 177 }; 178 179 ALL_INSTANCES.push( instance ); 180 181 return instance; 182 183 } 184 185 /** 186 * Binds the target buttons to automatically enter the 187 * loading state when clicked. 188 * 189 * @param target Either an HTML element or a CSS selector. 190 * @param options 191 * - timeout Number of milliseconds to wait before 192 * automatically cancelling the animation. 193 */ 194 function bind( target, options ) { 195 196 options = options || {}; 197 198 var targets = []; 199 200 if( typeof target === 'string' ) { 201 targets = toArray( document.querySelectorAll( target ) ); 202 } 203 else if( typeof target === 'object' && typeof target.nodeName === 'string' ) { 204 targets = [ target ]; 205 } 206 207 for( var i = 0, len = targets.length; i < len; i++ ) { 208 209 (function() { 210 var element = targets[i]; 211 212 // Make sure we're working with a DOM element 213 if( typeof element.addEventListener === 'function' ) { 214 var instance = create( element ); 215 var timeout = -1; 216 217 element.addEventListener( 'click', function() { 218 219 // This is asynchronous to avoid an issue where setting 220 // the disabled attribute on the button prevents forms 221 // from submitting 222 instance.startAfter( 1 ); 223 224 // Set a loading timeout if one is specified 225 if( typeof options.timeout === 'number' ) { 226 clearTimeout( timeout ); 227 timeout = setTimeout( instance.stop, options.timeout ); 228 } 229 230 // Invoke callbacks 231 if( typeof options.callback === 'function' ) { 232 options.callback.apply( null, [ instance ] ); 233 } 234 235 }, false ); 236 } 237 })(); 238 239 } 240 241 } 242
243 /** 244 * Stops ALL current loading animations. 245 */ 246 function stopAll() { 247 248 for( var i = 0, len = ALL_INSTANCES.length; i < len; i++ ) { 249 ALL_INSTANCES[i].stop(); 250 } 251 252 } 253 254 function createSpinner( button ) { 255 256 var height = button.offsetHeight, 257 spinnerColor; 258 259 // If the button is tall we can afford some padding 260 if( height > 32 ) { 261 height *= 0.8; 262 } 263 264 // Prefer an explicit height if one is defined 265 if( button.hasAttribute( 'data-spinner-size' ) ) { 266 height = parseInt( button.getAttribute( 'data-spinner-size' ), 10 ); 267 } 268 269 // Allow buttons to specify the color of the spinner element 270 if (button.hasAttribute('data-spinner-color' ) ) { 271 spinnerColor = button.getAttribute( 'data-spinner-color' ); 272 } 273 274 var lines = 12, 275 radius = height * 0.2, 276 length = radius * 0.6, 277 width = radius < 7 ? 2 : 3; 278 279 return new Spinner( { 280 color: spinnerColor || '#fff', 281 lines: lines, 282 radius: radius, 283 length: length, 284 width: width, 285 zIndex: 'auto', 286 top: 'auto', 287 left: 'auto', 288 className: '' 289 } ); 290 291 } 292 293 function toArray( nodes ) { 294 295 var a = []; 296 297 for ( var i = 0; i < nodes.length; i++ ) { 298 a.push( nodes[ i ] ); 299 } 300 301 return a; 302 303 } 304 305 // Public API 306 return { 307 308 bind: bind, 309 create: create, 310 stopAll: stopAll 311 312 }; 313 314}));
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.