ladda-rails 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2U2NmJmNGJmYzdjYjc5YTczNDI5MTU0ZDAxOTk3MmVjYmQxMGM2Mw==
5
+ data.tar.gz: !binary |-
6
+ YTQyOWRhMDBhMTMzNzc4YzNhZTY0YTA5MTU2NWM5ZWZkYWU2NjJhMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ODdlODI1ODE1MGU2MWY5NGFkM2RhNmZhYzBkOTQxYzBjMzVkNWI3NmI4Mzkx
10
+ ZWU0ZjQ0ZTdiMDRkYmNhNzdkMGU2ZTQ1YzY4ZGIyOTljMjgyZWMzYjMxMDMz
11
+ ODU2YjU3OWM3NDMyY2Y0ZTZhOGI1OTIyZGQ0ZWNiYjJlZjFlNDk=
12
+ data.tar.gz: !binary |-
13
+ MDdiYTcwYzI2MzVmNmRhNmUzY2Q1OWViMjkyYTIzMWQ2MjE3NmYzYzM1NWUw
14
+ MWY2YzBiYWY0ZWUyNGUxN2Y0ZTMyZmMyMjhmZmJmODZlZjYyNTQ2MjI4MzZm
15
+ ZTE1ZmIxZjQ5MjZlMGMyYTRiMWM5NDhhZDA4ODcxOTNjNDQ1ZGQ=
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+ .idea/
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ ladda-rails
2
+ ===========
3
+
4
+ A thin wrapper around https://github.com/hakimel/Ladda .
5
+
6
+ If you copy files from the interwebs into your project, kittens die.
7
+
8
+ Do this instead (in your Gemfile):
9
+
10
+ gem "ladda-rails"
11
+
12
+ And, in your application.js and application.css:
13
+
14
+ //= require "spin"
15
+ //= require "ladda"
16
+ //= require "ladda.jquery" // only when you use jQuery already, see Ladda docs for usage
17
+
18
+ *= require ladda
19
+ *= require ladda-themed // this is optional - when you leave this out, it's equivalent to the "ladda-themeless.min.css from the Ladda project
20
+
21
+
22
+ ====================================================================
23
+
24
+ original source https://github.com/Promptus/ladda-rails
25
+
26
+ I have forked that cause I am in a hurry to build a gem on rubygems.org
27
+
28
+ And I have updated the ladda version to 0.9.7
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "ladda-rails"
5
+ s.version = "0.9.7"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Martin Tepper"]
8
+ s.email = ["mt@promptus-partners.de"]
9
+ s.homepage = "https://github.com/Promptus/ladda-rails"
10
+ s.summary = "Use Ladda with Rails 3 and 4"
11
+ s.description = "Ladda CSS and JS in a convenient fashion."
12
+ s.license = "MIT"
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
+ s.require_path = 'lib'
19
+ end
@@ -0,0 +1,6 @@
1
+ module Ladda
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,46 @@
1
+ /*!
2
+ * Ladda for jQuery
3
+ * http://lab.hakim.se/ladda
4
+ * MIT licensed
5
+ *
6
+ * Copyright (C) 2015 Hakim El Hattab, http://hakim.se
7
+ */
8
+
9
+ (function( Ladda, $ ) {
10
+ if ($ === undefined)
11
+ return console.error( 'jQuery required for Ladda.jQuery' );
12
+
13
+ var arr = [];
14
+
15
+ $ = $.extend( $, {
16
+ ladda: function( arg ) {
17
+ if( arg === 'stopAll' )
18
+ Ladda.stopAll();
19
+ }
20
+ });
21
+
22
+ $.fn = $.extend( $.fn, {
23
+ ladda: function( arg ) {
24
+ var args = arr.slice.call( arguments, 1 );
25
+
26
+ if( arg === 'bind' ) {
27
+ args.unshift( $( this ).selector );
28
+ Ladda.bind.apply( Ladda, args );
29
+ }
30
+ else {
31
+ $( this ).each( function() {
32
+ var $this = $( this ), ladda;
33
+
34
+ if( arg === undefined )
35
+ $this.data( 'ladda', Ladda.create( this ) );
36
+ else {
37
+ ladda = $this.data( 'ladda' );
38
+ ladda[arg].apply( ladda, args );
39
+ }
40
+ });
41
+ }
42
+
43
+ return this;
44
+ }
45
+ });
46
+ }( this.Ladda, this.jQuery ));
@@ -0,0 +1,423 @@
1
+ /*!
2
+ * Ladda
3
+ * http://lab.hakim.se/ladda
4
+ * MIT licensed
5
+ *
6
+ * Copyright (C) 2015 Hakim El Hattab, http://hakim.se
7
+ */
8
+ /* jshint node:true, browser:true */
9
+ (function( root, factory ) {
10
+
11
+ // CommonJS
12
+ if( typeof exports === 'object' ) {
13
+ module.exports = factory(require('spin.js'));
14
+ }
15
+ // AMD module
16
+ else if( typeof define === 'function' && define.amd ) {
17
+ define( [ 'spin' ], factory );
18
+ }
19
+ // Browser global
20
+ else {
21
+ root.Ladda = factory( root.Spinner );
22
+ }
23
+
24
+ }
25
+ (this, function( Spinner ) {
26
+ 'use strict';
27
+
28
+ // All currently instantiated instances of Ladda
29
+ var ALL_INSTANCES = [];
30
+
31
+ /**
32
+ * Creates a new instance of Ladda which wraps the
33
+ * target button element.
34
+ *
35
+ * @return An API object that can be used to control
36
+ * the loading animation state.
37
+ */
38
+ function create( button ) {
39
+
40
+ if( typeof button === 'undefined' ) {
41
+ console.warn( "Ladda button target must be defined." );
42
+ return;
43
+ }
44
+
45
+ // The text contents must be wrapped in a ladda-label
46
+ // element, create one if it doesn't already exist
47
+ if( !button.querySelector( '.ladda-label' ) ) {
48
+ button.innerHTML = '<span class="ladda-label">'+ button.innerHTML +'</span>';
49
+ }
50
+
51
+ // The spinner component
52
+ var spinner,
53
+ spinnerWrapper = button.querySelector( '.ladda-spinner' );
54
+
55
+ // Wrapper element for the spinner
56
+ if( !spinnerWrapper ) {
57
+ spinnerWrapper = document.createElement( 'span' );
58
+ spinnerWrapper.className = 'ladda-spinner';
59
+ }
60
+
61
+ button.appendChild( spinnerWrapper );
62
+
63
+ // Timer used to delay starting/stopping
64
+ var timer;
65
+
66
+ var instance = {
67
+
68
+ /**
69
+ * Enter the loading state.
70
+ */
71
+ start: function() {
72
+
73
+ // Create the spinner if it doesn't already exist
74
+ if( !spinner ) spinner = createSpinner( button );
75
+
76
+ button.setAttribute( 'disabled', '' );
77
+ button.setAttribute( 'data-loading', '' );
78
+
79
+ clearTimeout( timer );
80
+ spinner.spin( spinnerWrapper );
81
+
82
+ this.setProgress( 0 );
83
+
84
+ return this; // chain
85
+
86
+ },
87
+
88
+ /**
89
+ * Enter the loading state, after a delay.
90
+ */
91
+ startAfter: function( delay ) {
92
+
93
+ clearTimeout( timer );
94
+ timer = setTimeout( function() { instance.start(); }, delay );
95
+
96
+ return this; // chain
97
+
98
+ },
99
+
100
+ /**
101
+ * Exit the loading state.
102
+ */
103
+ stop: function() {
104
+
105
+ button.removeAttribute( 'disabled' );
106
+ button.removeAttribute( 'data-loading' );
107
+
108
+ // Kill the animation after a delay to make sure it
109
+ // runs for the duration of the button transition
110
+ clearTimeout( timer );
111
+
112
+ if( spinner ) {
113
+ timer = setTimeout( function() { spinner.stop(); }, 1000 );
114
+ }
115
+
116
+ return this; // chain
117
+
118
+ },
119
+
120
+ /**
121
+ * Toggle the loading state on/off.
122
+ */
123
+ toggle: function() {
124
+
125
+ if( this.isLoading() ) {
126
+ this.stop();
127
+ }
128
+ else {
129
+ this.start();
130
+ }
131
+
132
+ return this; // chain
133
+
134
+ },
135
+
136
+ /**
137
+ * Sets the width of the visual progress bar inside of
138
+ * this Ladda button
139
+ *
140
+ * @param {Number} progress in the range of 0-1
141
+ */
142
+ setProgress: function( progress ) {
143
+
144
+ // Cap it
145
+ progress = Math.max( Math.min( progress, 1 ), 0 );
146
+
147
+ var progressElement = button.querySelector( '.ladda-progress' );
148
+
149
+ // Remove the progress bar if we're at 0 progress
150
+ if( progress === 0 && progressElement && progressElement.parentNode ) {
151
+ progressElement.parentNode.removeChild( progressElement );
152
+ }
153
+ else {
154
+ if( !progressElement ) {
155
+ progressElement = document.createElement( 'div' );
156
+ progressElement.className = 'ladda-progress';
157
+ button.appendChild( progressElement );
158
+ }
159
+
160
+ progressElement.style.width = ( ( progress || 0 ) * button.offsetWidth ) + 'px';
161
+ }
162
+
163
+ },
164
+
165
+ enable: function() {
166
+
167
+ this.stop();
168
+
169
+ return this; // chain
170
+
171
+ },
172
+
173
+ disable: function () {
174
+
175
+ this.stop();
176
+ button.setAttribute( 'disabled', '' );
177
+
178
+ return this; // chain
179
+
180
+ },
181
+
182
+ isLoading: function() {
183
+
184
+ return button.hasAttribute( 'data-loading' );
185
+
186
+ },
187
+
188
+ remove: function() {
189
+
190
+ clearTimeout( timer );
191
+
192
+ button.removeAttribute( 'disabled', '' );
193
+ button.removeAttribute( 'data-loading', '' );
194
+
195
+ if( spinner ) {
196
+ spinner.stop();
197
+ spinner = null;
198
+ }
199
+
200
+ for( var i = 0, len = ALL_INSTANCES.length; i < len; i++ ) {
201
+ if( instance === ALL_INSTANCES[i] ) {
202
+ ALL_INSTANCES.splice( i, 1 );
203
+ break;
204
+ }
205
+ }
206
+
207
+ }
208
+
209
+ };
210
+
211
+ ALL_INSTANCES.push( instance );
212
+
213
+ return instance;
214
+
215
+ }
216
+
217
+ /**
218
+ * Get the first ancestor node from an element, having a
219
+ * certain type.
220
+ *
221
+ * @param elem An HTML element
222
+ * @param type an HTML tag type (uppercased)
223
+ *
224
+ * @return An HTML element
225
+ */
226
+ function getAncestorOfTagType( elem, type ) {
227
+
228
+ while ( elem.parentNode && elem.tagName !== type ) {
229
+ elem = elem.parentNode;
230
+ }
231
+
232
+ return ( type === elem.tagName ) ? elem : undefined;
233
+
234
+ }
235
+
236
+ /**
237
+ * Returns a list of all inputs in the given form that
238
+ * have their `required` attribute set.
239
+ *
240
+ * @param form The from HTML element to look in
241
+ *
242
+ * @return A list of elements
243
+ */
244
+ function getRequiredFields( form ) {
245
+
246
+ var requirables = [ 'input', 'textarea', 'select' ];
247
+ var inputs = [];
248
+
249
+ for( var i = 0; i < requirables.length; i++ ) {
250
+ var candidates = form.getElementsByTagName( requirables[i] );
251
+ for( var j = 0; j < candidates.length; j++ ) {
252
+ if ( candidates[j].hasAttribute( 'required' ) ) {
253
+ inputs.push( candidates[j] );
254
+ }
255
+ }
256
+ }
257
+
258
+ return inputs;
259
+
260
+ }
261
+
262
+
263
+ /**
264
+ * Binds the target buttons to automatically enter the
265
+ * loading state when clicked.
266
+ *
267
+ * @param target Either an HTML element or a CSS selector.
268
+ * @param options
269
+ * - timeout Number of milliseconds to wait before
270
+ * automatically cancelling the animation.
271
+ */
272
+ function bind( target, options ) {
273
+
274
+ options = options || {};
275
+
276
+ var targets = [];
277
+
278
+ if( typeof target === 'string' ) {
279
+ targets = toArray( document.querySelectorAll( target ) );
280
+ }
281
+ else if( typeof target === 'object' && typeof target.nodeName === 'string' ) {
282
+ targets = [ target ];
283
+ }
284
+
285
+ for( var i = 0, len = targets.length; i < len; i++ ) {
286
+
287
+ (function() {
288
+ var element = targets[i];
289
+
290
+ // Make sure we're working with a DOM element
291
+ if( typeof element.addEventListener === 'function' ) {
292
+ var instance = create( element );
293
+ var timeout = -1;
294
+
295
+ element.addEventListener( 'click', function( event ) {
296
+
297
+ // If the button belongs to a form, make sure all the
298
+ // fields in that form are filled out
299
+ var valid = true;
300
+ var form = getAncestorOfTagType( element, 'FORM' );
301
+
302
+ if( typeof form !== 'undefined' ) {
303
+ var requireds = getRequiredFields( form );
304
+ for( var i = 0; i < requireds.length; i++ ) {
305
+
306
+ // Alternatively to this trim() check,
307
+ // we could have use .checkValidity() or .validity.valid
308
+ if( requireds[i].value.replace( /^\s+|\s+$/g, '' ) === '' ) {
309
+ valid = false;
310
+ }
311
+
312
+ // Radiobuttons and Checkboxes need to be checked for the "checked" attribute
313
+ if( (requireds[i].type === 'checkbox' || requireds[i].type === 'radio' ) && !requireds[i].checked ) {
314
+ valid = false;
315
+ }
316
+
317
+ }
318
+ }
319
+
320
+ if( valid ) {
321
+ // This is asynchronous to avoid an issue where setting
322
+ // the disabled attribute on the button prevents forms
323
+ // from submitting
324
+ instance.startAfter( 1 );
325
+
326
+ // Set a loading timeout if one is specified
327
+ if( typeof options.timeout === 'number' ) {
328
+ clearTimeout( timeout );
329
+ timeout = setTimeout( instance.stop, options.timeout );
330
+ }
331
+
332
+ // Invoke callbacks
333
+ if( typeof options.callback === 'function' ) {
334
+ options.callback.apply( null, [ instance ] );
335
+ }
336
+ }
337
+
338
+ }, false );
339
+ }
340
+ })();
341
+
342
+ }
343
+
344
+ }
345
+
346
+ /**
347
+ * Stops ALL current loading animations.
348
+ */
349
+ function stopAll() {
350
+
351
+ for( var i = 0, len = ALL_INSTANCES.length; i < len; i++ ) {
352
+ ALL_INSTANCES[i].stop();
353
+ }
354
+
355
+ }
356
+
357
+ function createSpinner( button ) {
358
+
359
+ var height = button.offsetHeight,
360
+ spinnerColor;
361
+
362
+ if( height === 0 ) {
363
+ // We may have an element that is not visible so
364
+ // we attempt to get the height in a different way
365
+ height = parseFloat( window.getComputedStyle( button ).height );
366
+ }
367
+
368
+ // If the button is tall we can afford some padding
369
+ if( height > 32 ) {
370
+ height *= 0.8;
371
+ }
372
+
373
+ // Prefer an explicit height if one is defined
374
+ if( button.hasAttribute( 'data-spinner-size' ) ) {
375
+ height = parseInt( button.getAttribute( 'data-spinner-size' ), 10 );
376
+ }
377
+
378
+ // Allow buttons to specify the color of the spinner element
379
+ if( button.hasAttribute( 'data-spinner-color' ) ) {
380
+ spinnerColor = button.getAttribute( 'data-spinner-color' );
381
+ }
382
+
383
+ var lines = 12,
384
+ radius = height * 0.2,
385
+ length = radius * 0.6,
386
+ width = radius < 7 ? 2 : 3;
387
+
388
+ return new Spinner( {
389
+ color: spinnerColor || '#fff',
390
+ lines: lines,
391
+ radius: radius,
392
+ length: length,
393
+ width: width,
394
+ zIndex: 'auto',
395
+ top: 'auto',
396
+ left: 'auto',
397
+ className: ''
398
+ } );
399
+
400
+ }
401
+
402
+ function toArray( nodes ) {
403
+
404
+ var a = [];
405
+
406
+ for ( var i = 0; i < nodes.length; i++ ) {
407
+ a.push( nodes[ i ] );
408
+ }
409
+
410
+ return a;
411
+
412
+ }
413
+
414
+ // Public API
415
+ return {
416
+
417
+ bind: bind,
418
+ create: create,
419
+ stopAll: stopAll
420
+
421
+ };
422
+
423
+ }));