ladda-rails 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }));