combodate-rails 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright 2011 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # combodate-rails
2
+
3
+ combodate-rails wraps the [combodate.js](http://http://vitalets.github.com/combodate/) library in a rails engine
4
+ for simple use with the asset pipeline provided by rails 3.1. The gem includes the development (non-minified)
5
+ source for ease of exploration. The asset pipeline will minify in production.
6
+
7
+ combodate.js is a plugin that "...converts <input> into dropdown elements to pick day, month, year, hour, minutes
8
+ and seconds." Please see the [documentation](http://vitalets.github.com/combodate/#docs) for details.
9
+
10
+ ## Usage
11
+
12
+ Add the following to your gemfile:
13
+
14
+ gem 'combodate-rails'
15
+
16
+ Add the following directive to your Javascript manifest file (application.js):
17
+
18
+ //= require combodate
19
+
20
+ If you want to include a localization file, also add the following directive:
21
+
22
+ //= require combodate/<locale>.js
23
+
24
+ ## Versioning
25
+
26
+ combodate-rails 1.0.1 == combodate.js 1.0.1
27
+
28
+ 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
+ bug be discovered, a 4th version identifier will be added and incremented.
31
+
@@ -0,0 +1,2 @@
1
+ ### Version 1.0.1 (2013-01-16)
2
+ - Initial Release
@@ -0,0 +1,8 @@
1
+ module Combodate
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ # Get rails to add app, lib, vendor to load path
5
+ end
6
+ end
7
+ end
8
+
@@ -0,0 +1,398 @@
1
+ /**
2
+ * Combodate - 1.0.1
3
+ * Dropdown date and time picker.
4
+ * Converts text input into dropdowns to pick day, month, year, hour, minute and second.
5
+ * Uses momentjs as datetime library http://momentjs.com.
6
+ * For i18n include corresponding file from https://github.com/timrwood/moment/tree/master/lang
7
+ *
8
+ * Author: Vitaliy Potapov
9
+ * Project page: http://github.com/vitalets/combodate
10
+ * Copyright (c) 2012 Vitaliy Potapov. Released under MIT License.
11
+ **/
12
+ (function ($) {
13
+
14
+ var Combodate = function (element, options) {
15
+ this.$element = $(element);
16
+ if(!this.$element.is('input')) {
17
+ $.error('Combodate should be applied to INPUT element');
18
+ return;
19
+ }
20
+ this.options = $.extend({}, $.fn.combodate.defaults, options, this.$element.data());
21
+ this.init();
22
+ };
23
+
24
+ Combodate.prototype = {
25
+ constructor: Combodate,
26
+ init: function () {
27
+ this.map = {
28
+ //key regexp moment.method
29
+ day: ['D', 'date'],
30
+ month: ['M', 'month'],
31
+ year: ['Y', 'year'],
32
+ hour: ['[Hh]', 'hours'],
33
+ minute: ['m', 'minutes'],
34
+ second: ['s', 'seconds'],
35
+ ampm: ['[Aa]', '']
36
+ };
37
+
38
+ this.$widget = $('<span class="combodate"></span>').html(this.getTemplate());
39
+
40
+ this.initCombos();
41
+
42
+ //update original input on change
43
+ this.$widget.on('change', 'select', $.proxy(function(){
44
+ this.$element.val(this.getValue());
45
+ }, this));
46
+
47
+ this.$widget.find('select').css('width', 'auto');
48
+
49
+ //hide original input and insert widget
50
+ this.$element.hide().after(this.$widget);
51
+
52
+ //set initial value
53
+ this.setValue(this.$element.val() || this.options.value);
54
+ },
55
+
56
+ /*
57
+ Replace tokens in template with <select> elements
58
+ */
59
+ getTemplate: function() {
60
+ var tpl = this.options.template;
61
+
62
+ //first pass
63
+ $.each(this.map, function(k, v) {
64
+ v = v[0];
65
+ var r = new RegExp(v+'+'),
66
+ token = v.length > 1 ? v.substring(1, 2) : v;
67
+
68
+ tpl = tpl.replace(r, '{'+token+'}');
69
+ });
70
+
71
+ //replace spaces with &nbsp;
72
+ tpl = tpl.replace(/ /g, '&nbsp;');
73
+
74
+ //second pass
75
+ $.each(this.map, function(k, v) {
76
+ v = v[0];
77
+ var token = v.length > 1 ? v.substring(1, 2) : v;
78
+
79
+ tpl = tpl.replace('{'+token+'}', '<select class="'+k+'"></select>');
80
+ });
81
+
82
+ return tpl;
83
+ },
84
+
85
+ /*
86
+ Initialize combos that presents in template
87
+ */
88
+ 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
+ });
99
+ },
100
+
101
+ /*
102
+ Initialize items of combos. Handles `firstItem` option
103
+ */
104
+ initItems: function(key) {
105
+ var values = [];
106
+ if(this.options.firstItem === 'name') {
107
+ var header = typeof moment.relativeTime[key] === 'function' ? moment.relativeTime[key](1, true, key, false) : moment.relativeTime[key];
108
+ //take last entry (see momentjs lang files structure)
109
+ header = header.split(' ').reverse()[0];
110
+ values.push(['', header]);
111
+ } else if(this.options.firstItem === 'empty') {
112
+ values.push(['', '']);
113
+ }
114
+ 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
+ },
127
+
128
+ /*
129
+ fill day
130
+ */
131
+ 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++) {
136
+ name = twoDigit ? this.leadZero(i) : i;
137
+ items.push([i, name]);
138
+ }
139
+ return items;
140
+ },
141
+
142
+ /*
143
+ fill month
144
+ */
145
+ fillMonth: function() {
146
+ var items = this.initItems('M'), name, i,
147
+ longNames = this.options.template.indexOf('MMMM') !== -1,
148
+ shortNames = this.options.template.indexOf('MMM') !== -1,
149
+ twoDigit = this.options.template.indexOf('MM') !== -1;
150
+
151
+ for(i=0; i<=11; i++) {
152
+ if(longNames) {
153
+ name = moment.months[i];
154
+ } else if(shortNames) {
155
+ name = moment.monthsShort[i];
156
+ } else if(twoDigit) {
157
+ name = this.leadZero(i+1);
158
+ } else {
159
+ name = i+1;
160
+ }
161
+ items.push([i, name]);
162
+ }
163
+ return items;
164
+ },
165
+
166
+ /*
167
+ fill year
168
+ */
169
+ fillYear: function() {
170
+ var items = this.initItems('y'), name, i,
171
+ longNames = this.options.template.indexOf('YYYY') !== -1;
172
+
173
+ for(i=this.options.maxYear; i>=this.options.minYear; i--) {
174
+ name = longNames ? i : (i+'').substring(2);
175
+ items.push([i, name]);
176
+ }
177
+ return items;
178
+ },
179
+
180
+ /*
181
+ fill hour
182
+ */
183
+ fillHour: function() {
184
+ var items = this.initItems('h'), name, i,
185
+ h12 = this.options.template.indexOf('h') !== -1,
186
+ h24 = this.options.template.indexOf('H') !== -1,
187
+ twoDigit = this.options.template.toLowerCase().indexOf('hh') !== -1,
188
+ max = h12 ? 12 : 23;
189
+
190
+ for(i=0; i<=max; i++) {
191
+ name = twoDigit ? this.leadZero(i) : i;
192
+ items.push([i, name]);
193
+ }
194
+ return items;
195
+ },
196
+
197
+ /*
198
+ fill minute
199
+ */
200
+ fillMinute: function() {
201
+ var items = this.initItems('m'), name, i,
202
+ twoDigit = this.options.template.indexOf('mm') !== -1;
203
+
204
+ for(i=0; i<=59; i+= this.options.minuteStep) {
205
+ name = twoDigit ? this.leadZero(i) : i;
206
+ items.push([i, name]);
207
+ }
208
+ return items;
209
+ },
210
+
211
+ /*
212
+ fill second
213
+ */
214
+ fillSecond: function() {
215
+ var items = this.initItems('s'), name, i,
216
+ twoDigit = this.options.template.indexOf('ss') !== -1;
217
+
218
+ for(i=0; i<=59; i+= this.options.secondStep) {
219
+ name = twoDigit ? this.leadZero(i) : i;
220
+ items.push([i, name]);
221
+ }
222
+ return items;
223
+ },
224
+
225
+ /*
226
+ fill ampm
227
+ */
228
+ fillAmpm: function() {
229
+ var ampmL = this.options.template.indexOf('a') !== -1,
230
+ ampmU = this.options.template.indexOf('A') !== -1,
231
+ items = [
232
+ ['am', ampmL ? 'am' : 'AM'],
233
+ ['pm', ampmL ? 'pm' : 'PM']
234
+ ];
235
+ return items;
236
+ },
237
+
238
+ /*
239
+ Returns current date value.
240
+ If format not specified - `options.format` used.
241
+ If format = `null` - Moment object returned.
242
+ */
243
+ getValue: function(format) {
244
+ var dt, values = {},
245
+ that = this,
246
+ notSelected = false;
247
+
248
+ //getting selected values
249
+ $.each(this.map, function(k, v) {
250
+ if(k === 'ampm') {
251
+ return;
252
+ }
253
+ var def = k === 'day' ? 1 : 0;
254
+
255
+ values[k] = that['$'+k] ? parseInt(that['$'+k].val(), 10) : def;
256
+
257
+ if(isNaN(values[k])) {
258
+ notSelected = true;
259
+ return false;
260
+ }
261
+ });
262
+
263
+ //if at least one visible combo not selected - return empty string
264
+ if(notSelected) {
265
+ return '';
266
+ }
267
+
268
+ //convert hours if 12h format
269
+ 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
+ }
274
+ }
275
+
276
+ dt = moment([values.year, values.month, values.day, values.hour, values.minute, values.second]);
277
+
278
+ //highlight invalid date
279
+ this.highlight(dt);
280
+
281
+ format = format === undefined ? this.options.format : format;
282
+ if(format === null) {
283
+ return dt.isValid() ? dt : null;
284
+ } else {
285
+ return dt.isValid() ? dt.format(format) : '';
286
+ }
287
+ },
288
+
289
+ setValue: function(value) {
290
+ if(!value) {
291
+ return;
292
+ }
293
+
294
+ var dt = typeof value === 'string' ? moment(value, this.options.format) : moment(value),
295
+ that = this,
296
+ values = {};
297
+
298
+ 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
+ });
306
+
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
+ }
315
+
316
+ $.each(values, function(k, v) {
317
+ if(that['$'+k]) {
318
+ that['$'+k].val(v);
319
+ }
320
+ });
321
+
322
+ this.$element.val(dt.format(this.options.format));
323
+ }
324
+ },
325
+
326
+ /*
327
+ highlight combos if date is invalid
328
+ */
329
+ highlight: function(dt) {
330
+ if(!dt.isValid()) {
331
+ if(this.options.errorClass) {
332
+ this.$widget.addClass(this.options.errorClass);
333
+ } else {
334
+ //store original border color
335
+ if(!this.borderColor) {
336
+ this.borderColor = this.$widget.find('select').css('border-color');
337
+ }
338
+ this.$widget.find('select').css('border-color', 'red');
339
+ }
340
+ } else {
341
+ if(this.options.errorClass) {
342
+ this.$widget.removeClass(this.options.errorClass);
343
+ } else {
344
+ this.$widget.find('select').css('border-color', this.borderColor);
345
+ }
346
+ }
347
+ },
348
+
349
+ leadZero: function(v) {
350
+ return v <= 9 ? '0' + v : v;
351
+ },
352
+
353
+ destroy: function() {
354
+ this.$widget.remove();
355
+ this.$element.removeData('combodate').show();
356
+ }
357
+
358
+ //todo: clear method
359
+ };
360
+
361
+ $.fn.combodate = function ( option ) {
362
+ var d, args = Array.apply(null, arguments);
363
+ args.shift();
364
+
365
+ //getValue returns date as string / object (not jQuery object)
366
+ if(option === 'getValue' && this.length && (d = this.eq(0).data('combodate'))) {
367
+ return d.getValue.apply(d, args);
368
+ }
369
+
370
+ return this.each(function () {
371
+ var $this = $(this),
372
+ data = $this.data('combodate'),
373
+ options = typeof option == 'object' && option;
374
+ if (!data) {
375
+ $this.data('combodate', (data = new Combodate(this, options)));
376
+ }
377
+ if (typeof option == 'string' && typeof data[option] == 'function') {
378
+ data[option].apply(data, args);
379
+ }
380
+ });
381
+ };
382
+
383
+ $.fn.combodate.defaults = {
384
+ //in this format value stored in original input
385
+ format: 'DD-MM-YYYY HH:mm',
386
+ //in this format items in dropdowns are displayed
387
+ template: 'D / MMM / YYYY H : mm',
388
+ //initial value, can be `new Date()`
389
+ value: null,
390
+ minYear: 1970,
391
+ maxYear: 2015,
392
+ minuteStep: 5,
393
+ secondStep: 1,
394
+ firstItem: 'empty', //'name', 'empty', 'none'
395
+ errorClass: null
396
+ };
397
+
398
+ }(window.jQuery));
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: combodate-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ruurd Pels
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: momentjs-rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.7.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.7.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: railties
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3.1'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.1'
46
+ description: ! "\tCombodate is a javascript library for entering dates/times.\n\tIt
47
+ depends on momentjs-rails that is included as a dependency.\n This gem allows
48
+ for its easy inclusion into the rails asset pipeline.\n"
49
+ email:
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - lib/combodate-rails.rb
55
+ - vendor/assets/javascripts/combodate.js
56
+ - changelog.md
57
+ - MIT-LICENSE
58
+ - README.md
59
+ homepage: https://github.com/ruurd/combodate-rails
60
+ licenses: []
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 1.8.24
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: The Combodate JavaScript library ready to play with Rails.
83
+ test_files: []