combodate-rails 1.0.1 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6807459d342dc5eb711df015ed49e5c1037cee65
4
+ data.tar.gz: 566df1d8b8454adae4b7229fbc77e1972e371d30
5
+ SHA512:
6
+ metadata.gz: '090eb19579f3d223c1438635921f64ec52b873bb238e86d2e93a4f01795f3684d4a575a986b393245bac26ff9ca1da85effae58f9d8d0d4b542be797a27c2c9e'
7
+ data.tar.gz: 2d4ebc7fb40fbc5f2800ab172e01bf7e9c494eda4321269ed5c9cebea33a6fa30e1cd516ff3476ab5ce657676f0446c3c99df58aae2ae00664a15dec02f2775b
data/README.md CHANGED
@@ -4,7 +4,7 @@ combodate-rails wraps the [combodate.js](http://http://vitalets.github.com/combo
4
4
  for simple use with the asset pipeline provided by rails 3.1. The gem includes the development (non-minified)
5
5
  source for ease of exploration. The asset pipeline will minify in production.
6
6
 
7
- combodate.js is a plugin that "...converts <input> into dropdown elements to pick day, month, year, hour, minutes
7
+ combodate.js is a plugin that "...converts \<input> into dropdown elements to pick day, month, year, hour, minutes
8
8
  and seconds." Please see the [documentation](http://vitalets.github.com/combodate/#docs) for details.
9
9
 
10
10
  ## Usage
@@ -24,8 +24,9 @@ If you want to include a localization file, also add the following directive:
24
24
  ## Versioning
25
25
 
26
26
  combodate-rails 1.0.1 == combodate.js 1.0.1
27
+ combodate-rails 1.0.7 == combodate.js 1.0.7
27
28
 
28
29
  Every attempt is made to mirror the currently shipping combodate.js version number wherever possible.
29
- The major, minor, and patch version numbers will always represent the Momentum.js version. Should a gem
30
+ The major, minor, and patch version numbers will always represent the combodate.js version. Should a gem
30
31
  bug be discovered, a 4th version identifier will be added and incremented.
31
32
 
@@ -1,10 +1,20 @@
1
1
  /**
2
- * Combodate - 1.0.1
2
+ * Combodate - 1.0.7
3
3
  * Dropdown date and time picker.
4
4
  * Converts text input into dropdowns to pick day, month, year, hour, minute and second.
5
5
  * Uses momentjs as datetime library http://momentjs.com.
6
6
  * For i18n include corresponding file from https://github.com/timrwood/moment/tree/master/lang
7
7
  *
8
+ * Confusion at noon and midnight - see http://en.wikipedia.org/wiki/12-hour_clock#Confusion_at_noon_and_midnight
9
+ * In combodate:
10
+ * 12:00 pm --> 12:00 (24-h format, midday)
11
+ * 12:00 am --> 00:00 (24-h format, midnight, start of day)
12
+ *
13
+ * Differs from momentjs parse rules:
14
+ * 00:00 pm, 12:00 pm --> 12:00 (24-h format, day not change)
15
+ * 00:00 am, 12:00 am --> 00:00 (24-h format, day not change)
16
+ *
17
+ *
8
18
  * Author: Vitaliy Potapov
9
19
  * Project page: http://github.com/vitalets/combodate
10
20
  * Copyright (c) 2012 Vitaliy Potapov. Released under MIT License.
@@ -40,16 +50,22 @@
40
50
  this.initCombos();
41
51
 
42
52
  //update original input on change
43
- this.$widget.on('change', 'select', $.proxy(function(){
44
- this.$element.val(this.getValue());
53
+ this.$widget.on('change', 'select', $.proxy(function(e) {
54
+ this.$element.val(this.getValue()).change();
55
+ // update days count if month or year changes
56
+ if (this.options.smartDays) {
57
+ if ($(e.target).is('.month') || $(e.target).is('.year')) {
58
+ this.fillCombo('day');
59
+ }
60
+ }
45
61
  }, this));
46
62
 
47
63
  this.$widget.find('select').css('width', 'auto');
48
64
 
49
- //hide original input and insert widget
65
+ // hide original input and insert widget
50
66
  this.$element.hide().after(this.$widget);
51
67
 
52
- //set initial value
68
+ // set initial value
53
69
  this.setValue(this.$element.val() || this.options.value);
54
70
  },
55
71
 
@@ -58,6 +74,7 @@
58
74
  */
59
75
  getTemplate: function() {
60
76
  var tpl = this.options.template;
77
+ var customClass = this.options.customClass;
61
78
 
62
79
  //first pass
63
80
  $.each(this.map, function(k, v) {
@@ -76,7 +93,7 @@
76
93
  v = v[0];
77
94
  var token = v.length > 1 ? v.substring(1, 2) : v;
78
95
 
79
- tpl = tpl.replace('{'+token+'}', '<select class="'+k+'"></select>');
96
+ tpl = tpl.replace('{'+token+'}', '<select class="'+k+' '+customClass+'"></select>');
80
97
  });
81
98
 
82
99
  return tpl;
@@ -86,25 +103,48 @@
86
103
  Initialize combos that presents in template
87
104
  */
88
105
  initCombos: function() {
89
- var that = this;
90
- $.each(this.map, function(k, v) {
91
- var $c = that.$widget.find('.'+k), f, items;
92
- if($c.length) {
93
- that['$'+k] = $c; //set properties like this.$day, this.$month etc.
94
- f = 'fill' + k.charAt(0).toUpperCase() + k.slice(1); //define method name to fill items, e.g `fillDays`
95
- items = that[f]();
96
- that['$'+k].html(that.renderItems(items));
97
- }
98
- });
106
+ for (var k in this.map) {
107
+ var $c = this.$widget.find('.'+k);
108
+ // set properties like this.$day, this.$month etc.
109
+ this['$'+k] = $c.length ? $c : null;
110
+ // fill with items
111
+ this.fillCombo(k);
112
+ }
99
113
  },
100
-
114
+
115
+ /*
116
+ Fill combo with items
117
+ */
118
+ fillCombo: function(k) {
119
+ var $combo = this['$'+k];
120
+ if (!$combo) {
121
+ return;
122
+ }
123
+
124
+ // define method name to fill items, e.g `fillDays`
125
+ var f = 'fill' + k.charAt(0).toUpperCase() + k.slice(1);
126
+ var items = this[f]();
127
+ var value = $combo.val();
128
+
129
+ $combo.empty();
130
+ for(var i=0; i<items.length; i++) {
131
+ $combo.append('<option value="'+items[i][0]+'">'+items[i][1]+'</option>');
132
+ }
133
+
134
+ $combo.val(value);
135
+ },
136
+
101
137
  /*
102
138
  Initialize items of combos. Handles `firstItem` option
103
139
  */
104
- initItems: function(key) {
105
- var values = [];
140
+ fillCommon: function(key) {
141
+ var values = [],
142
+ relTime;
143
+
106
144
  if(this.options.firstItem === 'name') {
107
- var header = typeof moment.relativeTime[key] === 'function' ? moment.relativeTime[key](1, true, key, false) : moment.relativeTime[key];
145
+ //need both to support moment ver < 2 and >= 2
146
+ relTime = moment.relativeTime || moment.langData()._relativeTime;
147
+ var header = typeof relTime[key] === 'function' ? relTime[key](1, true, key, false) : relTime[key];
108
148
  //take last entry (see momentjs lang files structure)
109
149
  header = header.split(' ').reverse()[0];
110
150
  values.push(['', header]);
@@ -112,27 +152,29 @@
112
152
  values.push(['', '']);
113
153
  }
114
154
  return values;
115
- },
116
-
117
- /*
118
- render items to string of <option> tags
119
- */
120
- renderItems: function(items) {
121
- var str = [];
122
- for(var i=0; i<items.length; i++) {
123
- str.push('<option value="'+items[i][0]+'">'+items[i][1]+'</option>');
124
- }
125
- return str.join("\n");
126
- },
155
+ },
156
+
127
157
 
128
158
  /*
129
159
  fill day
130
160
  */
131
161
  fillDay: function() {
132
- var items = this.initItems('d'), name, i,
133
- twoDigit = this.options.template.indexOf('DD') !== -1;
134
-
135
- for(i=1; i<=31; i++) {
162
+ var items = this.fillCommon('d'), name, i,
163
+ twoDigit = this.options.template.indexOf('DD') !== -1,
164
+ daysCount = 31;
165
+
166
+ // detect days count (depends on month and year)
167
+ // originally https://github.com/vitalets/combodate/pull/7
168
+ if (this.options.smartDays && this.$month && this.$year) {
169
+ var month = parseInt(this.$month.val(), 10);
170
+ var year = parseInt(this.$year.val(), 10);
171
+
172
+ if (!isNaN(month) && !isNaN(year)) {
173
+ daysCount = moment([year, month]).daysInMonth();
174
+ }
175
+ }
176
+
177
+ for (i = 1; i <= daysCount; i++) {
136
178
  name = twoDigit ? this.leadZero(i) : i;
137
179
  items.push([i, name]);
138
180
  }
@@ -143,16 +185,17 @@
143
185
  fill month
144
186
  */
145
187
  fillMonth: function() {
146
- var items = this.initItems('M'), name, i,
188
+ var items = this.fillCommon('M'), name, i,
147
189
  longNames = this.options.template.indexOf('MMMM') !== -1,
148
190
  shortNames = this.options.template.indexOf('MMM') !== -1,
149
191
  twoDigit = this.options.template.indexOf('MM') !== -1;
150
192
 
151
193
  for(i=0; i<=11; i++) {
152
194
  if(longNames) {
153
- name = moment.months[i];
195
+ //see https://github.com/timrwood/momentjs.com/pull/36
196
+ name = moment().date(1).month(i).format('MMMM');
154
197
  } else if(shortNames) {
155
- name = moment.monthsShort[i];
198
+ name = moment().date(1).month(i).format('MMM');
156
199
  } else if(twoDigit) {
157
200
  name = this.leadZero(i+1);
158
201
  } else {
@@ -167,13 +210,16 @@
167
210
  fill year
168
211
  */
169
212
  fillYear: function() {
170
- var items = this.initItems('y'), name, i,
213
+ var items = [], name, i,
171
214
  longNames = this.options.template.indexOf('YYYY') !== -1;
172
-
215
+
173
216
  for(i=this.options.maxYear; i>=this.options.minYear; i--) {
174
217
  name = longNames ? i : (i+'').substring(2);
175
- items.push([i, name]);
176
- }
218
+ items[this.options.yearDescending ? 'push' : 'unshift']([i, name]);
219
+ }
220
+
221
+ items = this.fillCommon('y').concat(items);
222
+
177
223
  return items;
178
224
  },
179
225
 
@@ -181,13 +227,14 @@
181
227
  fill hour
182
228
  */
183
229
  fillHour: function() {
184
- var items = this.initItems('h'), name, i,
230
+ var items = this.fillCommon('h'), name, i,
185
231
  h12 = this.options.template.indexOf('h') !== -1,
186
232
  h24 = this.options.template.indexOf('H') !== -1,
187
233
  twoDigit = this.options.template.toLowerCase().indexOf('hh') !== -1,
234
+ min = h12 ? 1 : 0,
188
235
  max = h12 ? 12 : 23;
189
236
 
190
- for(i=0; i<=max; i++) {
237
+ for(i=min; i<=max; i++) {
191
238
  name = twoDigit ? this.leadZero(i) : i;
192
239
  items.push([i, name]);
193
240
  }
@@ -198,7 +245,7 @@
198
245
  fill minute
199
246
  */
200
247
  fillMinute: function() {
201
- var items = this.initItems('m'), name, i,
248
+ var items = this.fillCommon('m'), name, i,
202
249
  twoDigit = this.options.template.indexOf('mm') !== -1;
203
250
 
204
251
  for(i=0; i<=59; i+= this.options.minuteStep) {
@@ -212,7 +259,7 @@
212
259
  fill second
213
260
  */
214
261
  fillSecond: function() {
215
- var items = this.initItems('s'), name, i,
262
+ var items = this.fillCommon('s'), name, i,
216
263
  twoDigit = this.options.template.indexOf('ss') !== -1;
217
264
 
218
265
  for(i=0; i<=59; i+= this.options.secondStep) {
@@ -234,9 +281,9 @@
234
281
  ];
235
282
  return items;
236
283
  },
237
-
284
+
238
285
  /*
239
- Returns current date value.
286
+ Returns current date value from combos.
240
287
  If format not specified - `options.format` used.
241
288
  If format = `null` - Moment object returned.
242
289
  */
@@ -265,12 +312,14 @@
265
312
  return '';
266
313
  }
267
314
 
268
- //convert hours if 12h format
315
+ //convert hours 12h --> 24h
269
316
  if(this.$ampm) {
270
- values.hour = this.$ampm.val() === 'am' ? values.hour : values.hour+12;
271
- if(values.hour === 24) {
272
- values.hour = 0;
273
- }
317
+ //12:00 pm --> 12:00 (24-h format, midday), 12:00 am --> 00:00 (24-h format, midnight, start of day)
318
+ if(values.hour === 12) {
319
+ values.hour = this.$ampm.val() === 'am' ? 0 : 12;
320
+ } else {
321
+ values.hour = this.$ampm.val() === 'am' ? values.hour : values.hour+12;
322
+ }
274
323
  }
275
324
 
276
325
  dt = moment([values.year, values.month, values.day, values.hour, values.minute, values.second]);
@@ -291,35 +340,73 @@
291
340
  return;
292
341
  }
293
342
 
294
- var dt = typeof value === 'string' ? moment(value, this.options.format) : moment(value),
343
+ // parse in strict mode (third param `true`)
344
+ var dt = typeof value === 'string' ? moment(value, this.options.format, true) : moment(value),
295
345
  that = this,
296
346
  values = {};
297
347
 
348
+ //function to find nearest value in select options
349
+ function getNearest($select, value) {
350
+ var delta = {};
351
+ $select.children('option').each(function(i, opt){
352
+ var optValue = $(opt).attr('value'),
353
+ distance;
354
+
355
+ if(optValue === '') return;
356
+ distance = Math.abs(optValue - value);
357
+ if(typeof delta.distance === 'undefined' || distance < delta.distance) {
358
+ delta = {value: optValue, distance: distance};
359
+ }
360
+ });
361
+ return delta.value;
362
+ }
363
+
298
364
  if(dt.isValid()) {
299
- //read values from date object
300
- $.each(this.map, function(k, v) {
301
- if(k === 'ampm') {
302
- return;
303
- }
304
- values[k] = dt[v[1]]();
305
- });
365
+ //read values from date object
366
+ $.each(this.map, function(k, v) {
367
+ if(k === 'ampm') {
368
+ return;
369
+ }
370
+ values[k] = dt[v[1]]();
371
+ });
306
372
 
307
- if(this.$ampm) {
308
- if(values.hour > 12) {
309
- values.hour -= 12;
310
- values.ampm = 'pm';
311
- } else {
312
- values.ampm = 'am';
313
- }
314
- }
373
+ if(this.$ampm) {
374
+ //12:00 pm --> 12:00 (24-h format, midday), 12:00 am --> 00:00 (24-h format, midnight, start of day)
375
+ if(values.hour >= 12) {
376
+ values.ampm = 'pm';
377
+ if(values.hour > 12) {
378
+ values.hour -= 12;
379
+ }
380
+ } else {
381
+ values.ampm = 'am';
382
+ if(values.hour === 0) {
383
+ values.hour = 12;
384
+ }
385
+ }
386
+ }
315
387
 
316
- $.each(values, function(k, v) {
317
- if(that['$'+k]) {
318
- that['$'+k].val(v);
319
- }
320
- });
388
+ $.each(values, function(k, v) {
389
+ //call val() for each existing combo, e.g. this.$hour.val()
390
+ if(that['$'+k]) {
391
+
392
+ if(k === 'minute' && that.options.minuteStep > 1 && that.options.roundTime) {
393
+ v = getNearest(that['$'+k], v);
394
+ }
395
+
396
+ if(k === 'second' && that.options.secondStep > 1 && that.options.roundTime) {
397
+ v = getNearest(that['$'+k], v);
398
+ }
399
+
400
+ that['$'+k].val(v);
401
+ }
402
+ });
403
+
404
+ // update days count
405
+ if (this.options.smartDays) {
406
+ this.fillCombo('day');
407
+ }
321
408
 
322
- this.$element.val(dt.format(this.options.format));
409
+ this.$element.val(dt.format(this.options.format)).change();
323
410
  }
324
411
  },
325
412
 
@@ -389,10 +476,14 @@
389
476
  value: null,
390
477
  minYear: 1970,
391
478
  maxYear: 2015,
479
+ yearDescending: true,
392
480
  minuteStep: 5,
393
481
  secondStep: 1,
394
482
  firstItem: 'empty', //'name', 'empty', 'none'
395
- errorClass: null
483
+ errorClass: null,
484
+ customClass: '',
485
+ roundTime: true, // whether to round minutes and seconds if step > 1
486
+ smartDays: false // whether days in combo depend on selected month: 31, 30, 28
396
487
  };
397
488
 
398
489
  }(window.jQuery));
metadata CHANGED
@@ -1,49 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: combodate-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
5
- prerelease:
4
+ version: 1.0.7
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ruurd Pels
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-01-16 00:00:00.000000000 Z
11
+ date: 2016-12-02 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: momentjs-rails
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: 1.7.2
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: 1.7.2
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: railties
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
33
  version: '3.1'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
40
  version: '3.1'
46
- description: ! "\tCombodate is a javascript library for entering dates/times.\n\tIt
41
+ description: "\tCombodate is a javascript library for entering dates/times.\n\tIt
47
42
  depends on momentjs-rails that is included as a dependency.\n This gem allows
48
43
  for its easy inclusion into the rails asset pipeline.\n"
49
44
  email:
@@ -51,33 +46,32 @@ executables: []
51
46
  extensions: []
52
47
  extra_rdoc_files: []
53
48
  files:
54
- - lib/combodate-rails.rb
55
- - vendor/assets/javascripts/combodate.js
56
- - changelog.md
57
49
  - MIT-LICENSE
58
50
  - README.md
51
+ - changelog.md
52
+ - lib/combodate-rails.rb
53
+ - vendor/assets/javascripts/combodate.js
59
54
  homepage: https://github.com/ruurd/combodate-rails
60
55
  licenses: []
56
+ metadata: {}
61
57
  post_install_message:
62
58
  rdoc_options: []
63
59
  require_paths:
64
60
  - lib
65
61
  required_ruby_version: !ruby/object:Gem::Requirement
66
- none: false
67
62
  requirements:
68
- - - ! '>='
63
+ - - ">="
69
64
  - !ruby/object:Gem::Version
70
65
  version: '0'
71
66
  required_rubygems_version: !ruby/object:Gem::Requirement
72
- none: false
73
67
  requirements:
74
- - - ! '>='
68
+ - - ">="
75
69
  - !ruby/object:Gem::Version
76
70
  version: '0'
77
71
  requirements: []
78
72
  rubyforge_project:
79
- rubygems_version: 1.8.24
73
+ rubygems_version: 2.5.2
80
74
  signing_key:
81
- specification_version: 3
75
+ specification_version: 4
82
76
  summary: The Combodate JavaScript library ready to play with Rails.
83
77
  test_files: []