simple_form_extension 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 946b7d8265779451e32f1032aa3b9ace6d8f02c4
4
- data.tar.gz: 0bd6a400862b4f5fdea0b5fab2fd476c64ab0d27
3
+ metadata.gz: dce3e78a64dd2c77636f1d9a891d6863d6da048f
4
+ data.tar.gz: d4342009b4702683ce62bbc0382fd3ea27717441
5
5
  SHA512:
6
- metadata.gz: aee6e469e6e1fec674d2aae34dd90cf4b8f5a7337b7f1e479b504573082de14bd1ca43fe2990b99da422524accf9066ed96cb3d1274af8dd2d9dd051bb69f84c
7
- data.tar.gz: 1e5f4de04288e9789a897d2cd4e338a9fcaf4fa7b8854b68bd2f8b3cb6314d6a602d60d550539b9b0c36e603d5c3e4f20ef402db74b8ab13d14aced69de85514
6
+ metadata.gz: 6e9c2f6d5cb278850a4e5c97152c505ac83251442926e6b98adf16d97a193a1ab6585fbfcc07165132a8ee9db728e669fa5e5e48fe5be9ff18e2e016f9117b4e
7
+ data.tar.gz: 5ba0bceafadeeea0fbe1f114c425f5327aa7b043c7ae2d8b1ade47764763749fc2714f15f9eb1a16eab59fc3d6c685cc4049eb0d87e50cd900cc8dd49634e81f
@@ -13,7 +13,7 @@ module SimpleFormExtension
13
13
  <span class=\"fileinput-exists\">#{ _translate('image.change') }</span>
14
14
  #{@builder.file_field(attribute_name, input_html_options)}
15
15
  </div>
16
- <button class=\"btn btn-danger fileinput-exists pull-right\" data-dismiss=\"fileinput\" type=\"button\"><i class=\"fa fa-times\"></i></button>
16
+ <button class=\"btn btn-danger fileinput-exists\" data-dismiss=\"fileinput\" type=\"button\"><i class=\"fa fa-times\"></i></button>
17
17
  </div>
18
18
  <div class=\"fileinput-preview thumbnail\">
19
19
  #{ image_tag }
@@ -33,12 +33,12 @@ module SimpleFormExtension
33
33
 
34
34
  def multi?
35
35
  (options.key?(:multi) && !!options[:multi]) ||
36
- value.class.include?(Enumerable)
36
+ enumerable?(value)
37
37
  end
38
38
 
39
39
  def collection
40
40
  if (collection = options[:collection])
41
- if collection.class.include?(Enumerable)
41
+ if enumerable?(collection)
42
42
  collection.map(&method(:serialize_option))
43
43
  else
44
44
  (object.send(collection) || []).map(&method(:serialize_option))
@@ -65,8 +65,10 @@ module SimpleFormExtension
65
65
  private
66
66
 
67
67
  def serialize_option(option)
68
- if option.kind_of?(Hash) && options.key?(:text) && option.key?(:value)
68
+ if option.kind_of?(Hash) && option.key?(:text) && option.key?(:value)
69
69
  option
70
+ elsif option.kind_of?(ActiveRecord::Base)
71
+ { text: name_for(option), value: option.id }
70
72
  elsif !option.kind_of?(Hash)
71
73
  { text: option.to_s, value: option }
72
74
  else
@@ -83,6 +85,14 @@ module SimpleFormExtension
83
85
  # Return default block value or nil if no block was given
84
86
  block ? block.call : nil
85
87
  end
88
+
89
+ def enumerable?(object)
90
+ object.class.include?(Enumerable) || ActiveRecord::Relation === object
91
+ end
92
+
93
+ def name_for(option)
94
+ option.try(:name) || options.try(:title) || option.to_s
95
+ end
86
96
  end
87
97
  end
88
98
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleFormExtension
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -2,10 +2,13 @@
2
2
  #= require redactor-rails/langs/fr
3
3
  #= require redactor-rails/plugins
4
4
  #= require selectize
5
+ #= require spinbox
5
6
  #= require jquery.datetimepicker
6
7
  #= require_self
7
8
  #= require_tree ./simple_form_extension
8
9
 
10
+ $.fn.simpleForm = {}
11
+
9
12
  window.onPageReady = (callback) ->
10
13
  $(document).ready ->
11
14
  callback() if Turbolinks is undefined
@@ -43,4 +43,5 @@ onPageReady ->
43
43
 
44
44
  $('body').on 'click', '.date .datetimepicker-trigger', (e) ->
45
45
  $input = $(e.currentTarget).closest('.date').find('input.date')
46
- DatePicker.forInput($input, DatePicker).show()
46
+ DatePicker.forInput($input, DatePicker).show()
47
+
@@ -49,4 +49,3 @@ onPageReady ->
49
49
  lang: "fr"
50
50
 
51
51
  $textArea.data('initialized.redactor', true)
52
-
@@ -43,13 +43,12 @@ class Selectize
43
43
  </div>
44
44
  """
45
45
 
46
- onPageReady ->
47
- $selectizes = $('[data-selectize]')
48
-
49
- return unless $selectizes.length
50
-
51
- $('[data-selectize]').each (i, el) ->
46
+ $.fn.simpleFormSelectize = ->
47
+ @each (i, el) ->
52
48
  $select = $(el)
53
49
  return if $select.data('simple-form:selectize')
54
50
  instance = new Selectize($select)
55
51
  $select.data('simple-form:selectize', instance)
52
+
53
+ onPageReady ->
54
+ $('[data-selectize]').simpleFormSelectize()
@@ -0,0 +1,16 @@
1
+ class Spinbox
2
+ constructor: (@$el) ->
3
+ @el = @$el[0]
4
+
5
+ @$el.spinbox()
6
+
7
+ onPageReady ->
8
+ $spinbox = $('.spinner')
9
+
10
+ return unless $spinbox.length
11
+
12
+ $spinbox.each (i, el) ->
13
+ $spinner = $(el)
14
+ return if $spinner.data('simple-form:spinner')
15
+ instance = new Spinbox($spinner)
16
+ $spinner.data('simple-form:spinner', instance)
@@ -0,0 +1,445 @@
1
+ /*
2
+ * Fuel UX Spinbox
3
+ * https://github.com/ExactTarget/fuelux
4
+ *
5
+ * Copyright (c) 2014 ExactTarget
6
+ * Licensed under the BSD New license.
7
+ */
8
+
9
+ // -- BEGIN UMD WRAPPER PREFACE --
10
+
11
+ // For more information on UMD visit:
12
+ // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
13
+
14
+ (function(factory) {
15
+ if (typeof define === 'function' && define.amd) {
16
+ // if AMD loader is available, register as an anonymous module.
17
+ define(['jquery'], factory);
18
+ } else {
19
+ // OR use browser globals if AMD is not present
20
+ factory(jQuery);
21
+ }
22
+ }(function($) {
23
+ // -- END UMD WRAPPER PREFACE --
24
+
25
+ // -- BEGIN MODULE CODE HERE --
26
+
27
+ var old = $.fn.spinbox;
28
+
29
+ // SPINBOX CONSTRUCTOR AND PROTOTYPE
30
+
31
+ var Spinbox = function(element, options) {
32
+ this.$element = $(element);
33
+ this.$element.find('.btn').on('click', function(e) {
34
+ //keep spinbox from submitting if they forgot to say type="button" on their spinner buttons
35
+ e.preventDefault();
36
+ });
37
+ this.options = $.extend({}, $.fn.spinbox.defaults, options);
38
+ this.$input = this.$element.find('.spinner-input');
39
+ this.$element.on('focusin.fu.spinbox', this.$input, $.proxy(this.changeFlag, this));
40
+ this.$element.on('focusout.fu.spinbox', this.$input, $.proxy(this.change, this));
41
+ this.$element.on('keydown.fu.spinbox', this.$input, $.proxy(this.keydown, this));
42
+ this.$element.on('keyup.fu.spinbox', this.$input, $.proxy(this.keyup, this));
43
+
44
+ this.bindMousewheelListeners();
45
+ this.mousewheelTimeout = {};
46
+
47
+ if (this.options.hold) {
48
+ this.$element.on('mousedown.fu.spinbox', '.spinner-up', $.proxy(function() {
49
+ this.startSpin(true);
50
+ }, this));
51
+ this.$element.on('mouseup.fu.spinbox', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));
52
+ this.$element.on('mouseout.fu.spinbox', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));
53
+ this.$element.on('mousedown.fu.spinbox', '.spinner-down', $.proxy(function() {
54
+ this.startSpin(false);
55
+ }, this));
56
+ } else {
57
+ this.$element.on('click.fu.spinbox', '.spinner-up', $.proxy(function() {
58
+ this.step(true);
59
+ }, this));
60
+ this.$element.on('click.fu.spinbox', '.spinner-down', $.proxy(function() {
61
+ this.step(false);
62
+ }, this));
63
+ }
64
+
65
+ this.switches = {
66
+ count: 1,
67
+ enabled: true
68
+ };
69
+
70
+ if (this.options.speed === 'medium') {
71
+ this.switches.speed = 300;
72
+ } else if (this.options.speed === 'fast') {
73
+ this.switches.speed = 100;
74
+ } else {
75
+ this.switches.speed = 500;
76
+ }
77
+
78
+ this.lastValue = this.options.value;
79
+
80
+ this.render();
81
+
82
+ if (this.options.disabled) {
83
+ this.disable();
84
+ }
85
+ };
86
+
87
+ Spinbox.prototype = {
88
+ constructor: Spinbox,
89
+
90
+ destroy: function() {
91
+ this.$element.remove();
92
+ // any external bindings
93
+ // [none]
94
+ // set input value attrbute
95
+ this.$element.find('input').each(function() {
96
+ $(this).attr('value', $(this).val());
97
+ });
98
+ // empty elements to return to original markup
99
+ // [none]
100
+ // returns string of markup
101
+ return this.$element[0].outerHTML;
102
+ },
103
+
104
+ render: function() {
105
+ var inputValue = this.parseInput(this.$input.val());
106
+ var maxUnitLength = '';
107
+
108
+ // if input is empty and option value is default, 0
109
+ if (inputValue !== '' && this.options.value === 0) {
110
+ this.value(inputValue);
111
+ } else {
112
+ this.output (this.options.value);
113
+ }
114
+
115
+ if (this.options.units.length) {
116
+ $.each(this.options.units, function(index, value) {
117
+ if (value.length > maxUnitLength.length) {
118
+ maxUnitLength = value;
119
+ }
120
+ });
121
+ }
122
+
123
+ },
124
+
125
+ output: function(value, updateField) {
126
+ value = (value + '').split('.').join(this.options.decimalMark);
127
+ updateField = (updateField || true);
128
+ if (updateField) {
129
+ this.$input.val(value);
130
+ }
131
+
132
+ return value;
133
+ },
134
+
135
+ parseInput: function(value) {
136
+ value = (value + '').split(this.options.decimalMark).join('.');
137
+
138
+ return value;
139
+ },
140
+
141
+ change: function() {
142
+ var newVal = this.parseInput(this.$input.val()) || '';
143
+
144
+ if (this.options.units.length || this.options.decimalMark !== '.') {
145
+ newVal = this.parseValueWithUnit(newVal);
146
+ } else if (newVal / 1) {
147
+ newVal = this.options.value = this.checkMaxMin(newVal / 1);
148
+ } else {
149
+ newVal = this.checkMaxMin(newVal.replace(/[^0-9.-]/g, '') || '');
150
+ this.options.value = newVal / 1;
151
+ }
152
+ this.output (newVal);
153
+
154
+ this.changeFlag = false;
155
+ this.triggerChangedEvent();
156
+ },
157
+
158
+ changeFlag: function() {
159
+ this.changeFlag = true;
160
+ },
161
+
162
+ stopSpin: function() {
163
+ if (this.switches.timeout !== undefined) {
164
+ clearTimeout(this.switches.timeout);
165
+ this.switches.count = 1;
166
+ this.triggerChangedEvent();
167
+ }
168
+ },
169
+
170
+ triggerChangedEvent: function() {
171
+ var currentValue = this.value();
172
+ if (currentValue === this.lastValue) return;
173
+
174
+ this.lastValue = currentValue;
175
+
176
+ // Primary changed event
177
+ this.$element.trigger('changed.fu.spinbox', this.output(currentValue, false)); // no DOM update
178
+ },
179
+
180
+ startSpin: function(type) {
181
+
182
+ if (!this.options.disabled) {
183
+ var divisor = this.switches.count;
184
+
185
+ if (divisor === 1) {
186
+ this.step(type);
187
+ divisor = 1;
188
+ } else if (divisor < 3) {
189
+ divisor = 1.5;
190
+ } else if (divisor < 8) {
191
+ divisor = 2.5;
192
+ } else {
193
+ divisor = 4;
194
+ }
195
+
196
+ this.switches.timeout = setTimeout($.proxy(function() {
197
+ this.iterate(type);
198
+ }, this), this.switches.speed / divisor);
199
+ this.switches.count++;
200
+ }
201
+ },
202
+
203
+ iterate: function(type) {
204
+ this.step(type);
205
+ this.startSpin(type);
206
+ },
207
+
208
+ step: function(isIncrease) {
209
+ // isIncrease: true is up, false is down
210
+
211
+ var digits, multiple, currentValue, limitValue;
212
+
213
+ // trigger change event
214
+ if (this.changeFlag) {
215
+ this.change();
216
+ }
217
+
218
+ // get current value and min/max options
219
+ currentValue = this.options.value;
220
+ limitValue = isIncrease ? this.options.max : this.options.min;
221
+
222
+ if ( (isIncrease ? currentValue < limitValue : currentValue > limitValue) ) {
223
+ var newVal = currentValue + (isIncrease ? 1 : -1) * this.options.step;
224
+
225
+ // raise to power of 10 x number of decimal places, then round
226
+ if (this.options.step % 1 !== 0) {
227
+ digits = (this.options.step + '').split('.')[1].length;
228
+ multiple = Math.pow(10, digits);
229
+ newVal = Math.round(newVal * multiple) / multiple;
230
+ }
231
+
232
+ // if outside limits, set to limit value
233
+ if (isIncrease ? newVal > limitValue : newVal < limitValue) {
234
+ this.value(limitValue);
235
+ } else {
236
+ this.value(newVal);
237
+ }
238
+
239
+ } else if (this.options.cycle) {
240
+ var cycleVal = isIncrease ? this.options.min : this.options.max;
241
+ this.value(cycleVal);
242
+ }
243
+ },
244
+
245
+ value: function(value) {
246
+
247
+ if (value || value === 0) {
248
+ if (this.options.units.length || this.options.decimalMark !== '.') {
249
+ this.output(this.parseValueWithUnit(value + (this.unit || '')));
250
+ return this;
251
+
252
+ } else if (!isNaN(parseFloat(value)) && isFinite(value)) {
253
+ this.options.value = value / 1;
254
+ this.output (value + (this.unit ? this.unit : ''));
255
+ return this;
256
+
257
+ }
258
+ } else {
259
+ if (this.changeFlag) {
260
+ this.change();
261
+ }
262
+
263
+ if (this.unit) {
264
+ return this.options.value + this.unit;
265
+ } else {
266
+ return this.output(this.options.value, false); // no DOM update
267
+ }
268
+ }
269
+ },
270
+
271
+ isUnitLegal: function(unit) {
272
+ var legalUnit;
273
+
274
+ $.each(this.options.units, function(index, value) {
275
+ if (value.toLowerCase() === unit.toLowerCase()) {
276
+ legalUnit = unit.toLowerCase();
277
+ return false;
278
+ }
279
+ });
280
+
281
+ return legalUnit;
282
+ },
283
+
284
+ // strips units and add them back
285
+ parseValueWithUnit: function(value) {
286
+ var unit = value.replace(/[^a-zA-Z]/g, '');
287
+ var number = value.replace(/[^0-9.-]/g, '');
288
+
289
+ if (unit) {
290
+ unit = this.isUnitLegal(unit);
291
+ }
292
+
293
+ this.options.value = this.checkMaxMin(number / 1);
294
+ this.unit = unit || undefined;
295
+ return this.options.value + (unit || '');
296
+ },
297
+
298
+ checkMaxMin: function(value) {
299
+ // if unreadable
300
+ if (isNaN(parseFloat(value))) {
301
+ return value;
302
+ }
303
+ // if not within range return the limit
304
+ if (!(value <= this.options.max && value >= this.options.min)) {
305
+ value = value >= this.options.max ? this.options.max : this.options.min;
306
+ }
307
+ return value;
308
+ },
309
+
310
+ disable: function() {
311
+ this.options.disabled = true;
312
+ this.$element.addClass('disabled');
313
+ this.$input.attr('disabled', '');
314
+ this.$element.find('button').addClass('disabled');
315
+ },
316
+
317
+ enable: function() {
318
+ this.options.disabled = false;
319
+ this.$element.removeClass('disabled');
320
+ this.$input.removeAttr('disabled');
321
+ this.$element.find('button').removeClass('disabled');
322
+ },
323
+
324
+ keydown: function(event) {
325
+ var keyCode = event.keyCode;
326
+ if (keyCode === 38) {
327
+ this.step(true);
328
+ } else if (keyCode === 40) {
329
+ this.step(false);
330
+ }
331
+ },
332
+
333
+ keyup: function(event) {
334
+ var keyCode = event.keyCode;
335
+
336
+ if (keyCode === 38 || keyCode === 40) {
337
+ this.triggerChangedEvent();
338
+ }
339
+ },
340
+
341
+ bindMousewheelListeners: function() {
342
+ var inputEl = this.$input.get(0);
343
+ if (inputEl.addEventListener) {
344
+ //IE 9, Chrome, Safari, Opera
345
+ inputEl.addEventListener('mousewheel', $.proxy(this.mousewheelHandler, this), false);
346
+ // Firefox
347
+ inputEl.addEventListener('DOMMouseScroll', $.proxy(this.mousewheelHandler, this), false);
348
+ } else {
349
+ // IE <9
350
+ inputEl.attachEvent('onmousewheel', $.proxy(this.mousewheelHandler, this));
351
+ }
352
+ },
353
+
354
+ mousewheelHandler: function(event) {
355
+ var e = window.event || event; // old IE support
356
+ var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
357
+ var self = this;
358
+
359
+ clearTimeout(this.mousewheelTimeout);
360
+ this.mousewheelTimeout = setTimeout(function() {
361
+ self.triggerChangedEvent();
362
+ }, 300);
363
+
364
+ if (delta < 0) {
365
+ this.step(true);
366
+ } else {
367
+ this.step(false);
368
+ }
369
+
370
+ if (e.preventDefault) {
371
+ e.preventDefault();
372
+ } else {
373
+ e.returnValue = false;
374
+ }
375
+ return false;
376
+ }
377
+ };
378
+
379
+
380
+ // SPINBOX PLUGIN DEFINITION
381
+
382
+ $.fn.spinbox = function(option) {
383
+ var args = Array.prototype.slice.call(arguments, 1);
384
+ var methodReturn;
385
+
386
+ var $set = this.each(function() {
387
+ var $this = $(this);
388
+ var data = $this.data('fu.spinbox');
389
+ var options = typeof option === 'object' && option;
390
+
391
+ if (!data) {
392
+ $this.data('fu.spinbox', (data = new Spinbox(this, options)));
393
+ }
394
+ if (typeof option === 'string') {
395
+ methodReturn = data[option].apply(data, args);
396
+ }
397
+ });
398
+
399
+ return (methodReturn === undefined) ? $set : methodReturn;
400
+ };
401
+
402
+ // value needs to be 0 for this.render();
403
+ $.fn.spinbox.defaults = {
404
+ value: 0,
405
+ min: 0,
406
+ max: 999,
407
+ step: 1,
408
+ hold: true,
409
+ speed: 'medium',
410
+ disabled: false,
411
+ cycle: false,
412
+ units: [],
413
+ decimalMark: '.'
414
+ };
415
+
416
+ $.fn.spinbox.Constructor = Spinbox;
417
+
418
+ $.fn.spinbox.noConflict = function() {
419
+ $.fn.spinbox = old;
420
+ return this;
421
+ };
422
+
423
+
424
+ // DATA-API
425
+
426
+ $(document).on('mousedown.fu.spinbox.data-api', '[data-initialize=spinbox]', function(e) {
427
+ var $control = $(e.target).closest('.spinner');
428
+ if (!$control.data('fu.spinbox')) {
429
+ $control.spinbox($control.data());
430
+ }
431
+ });
432
+
433
+ // Must be domReady for AMD compatibility
434
+ $(function() {
435
+ $('[data-initialize=spinbox]').each(function() {
436
+ var $this = $(this);
437
+ if (!$this.data('fu.spinbox')) {
438
+ $this.spinbox($this.data());
439
+ }
440
+ });
441
+ });
442
+
443
+ // -- BEGIN UMD WRAPPER AFTERWORD --
444
+ }));
445
+ // -- END UMD WRAPPER AFTERWORD --
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_form_extension
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Vasseur
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-03 00:00:00.000000000 Z
11
+ date: 2015-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -140,6 +140,8 @@ files:
140
140
  - vendor/assets/javascripts/simple_form_extension/datetimepicker.coffee
141
141
  - vendor/assets/javascripts/simple_form_extension/redactor.coffee
142
142
  - vendor/assets/javascripts/simple_form_extension/selectize.coffee
143
+ - vendor/assets/javascripts/simple_form_extension/spinbox.coffee
144
+ - vendor/assets/javascripts/spinbox.js
143
145
  - vendor/assets/stylesheets/jquery.datetimepicker.css
144
146
  - vendor/assets/stylesheets/simple_form_extension.sass
145
147
  homepage: http://www.glyph.fr
@@ -162,7 +164,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
164
  version: '0'
163
165
  requirements: []
164
166
  rubyforge_project:
165
- rubygems_version: 2.4.1
167
+ rubygems_version: 2.2.2
166
168
  signing_key:
167
169
  specification_version: 4
168
170
  summary: A simple extention for simple_form with, colorpiker, icon, fileupload, image