kolo 0.6.8 → 0.6.9

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: b5ef38089284ea8b6f3a16236122f0fe21c9828c
4
- data.tar.gz: 0e54d0624c639853a5393b846525384c524cb1d5
3
+ metadata.gz: 921b9e90304df02753965f1812a7c5866abfa179
4
+ data.tar.gz: bd8a1cebabbdc185d55fc7c847e554ea28098d7e
5
5
  SHA512:
6
- metadata.gz: 639abf179c3cd0ad5afb5ad2538e30287147a90b89a150cb564de83149fb2ff3a9d2685c56ff2f07b1a2e542360cad22662eda31f9cedc718a97150d0fe5e971
7
- data.tar.gz: 63cff983dd4757054057360351465984e6cdf26cf63329b4b83836a07550a688d6ee82760cc7ce602d7e582c12700bc9c299fa9a894f6c4b5a19c0a9d9fbf477
6
+ metadata.gz: db23c23dcd0d87ab6d93a26c3743433317c7d5cfdab1f60216141c1917fa67411d858d580200c21c7a550638f8022117266a15244c57a180a467b2617c4dd1c3
7
+ data.tar.gz: 82f778ae373f0ed512c9055699eaa174c6c4e865c21b8609a9beb99da8909bd9ccfe912e0e6f1b232d5684b0913fef1f6acfd8315a81d78b91b137c5d7e9e903
@@ -0,0 +1,474 @@
1
+ /* =========================================================
2
+ * bootstrap-datepicker.js
3
+ * http://www.eyecon.ro/bootstrap-datepicker
4
+ * =========================================================
5
+ * Copyright 2012 Stefan Petre
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ * ========================================================= */
19
+
20
+ !function( $ ) {
21
+
22
+ // Picker object
23
+
24
+ var Datepicker = function(element, options){
25
+ this.element = $(element);
26
+ this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
27
+ this.picker = $(DPGlobal.template)
28
+ .appendTo('body')
29
+ .on({
30
+ click: $.proxy(this.click, this)//,
31
+ //mousedown: $.proxy(this.mousedown, this)
32
+ });
33
+ this.isInput = this.element.is('input');
34
+ this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
35
+
36
+ if (this.isInput) {
37
+ this.element.on({
38
+ focus: $.proxy(this.show, this),
39
+ //blur: $.proxy(this.hide, this),
40
+ keyup: $.proxy(this.update, this)
41
+ });
42
+ } else {
43
+ if (this.component){
44
+ this.component.on('click', $.proxy(this.show, this));
45
+ } else {
46
+ this.element.on('click', $.proxy(this.show, this));
47
+ }
48
+ }
49
+
50
+ this.minViewMode = options.minViewMode||this.element.data('date-minviewmode')||0;
51
+ if (typeof this.minViewMode === 'string') {
52
+ switch (this.minViewMode) {
53
+ case 'months':
54
+ this.minViewMode = 1;
55
+ break;
56
+ case 'years':
57
+ this.minViewMode = 2;
58
+ break;
59
+ default:
60
+ this.minViewMode = 0;
61
+ break;
62
+ }
63
+ }
64
+ this.viewMode = options.viewMode||this.element.data('date-viewmode')||0;
65
+ if (typeof this.viewMode === 'string') {
66
+ switch (this.viewMode) {
67
+ case 'months':
68
+ this.viewMode = 1;
69
+ break;
70
+ case 'years':
71
+ this.viewMode = 2;
72
+ break;
73
+ default:
74
+ this.viewMode = 0;
75
+ break;
76
+ }
77
+ }
78
+ this.startViewMode = this.viewMode;
79
+ this.weekStart = options.weekStart||this.element.data('date-weekstart')||0;
80
+ this.weekEnd = this.weekStart === 0 ? 6 : this.weekStart - 1;
81
+ this.onRender = options.onRender;
82
+ this.fillDow();
83
+ this.fillMonths();
84
+ this.update();
85
+ this.showMode();
86
+ };
87
+
88
+ Datepicker.prototype = {
89
+ constructor: Datepicker,
90
+
91
+ show: function(e) {
92
+ this.picker.show();
93
+ this.height = this.component ? this.component.outerHeight() : this.element.outerHeight();
94
+ this.place();
95
+ $(window).on('resize', $.proxy(this.place, this));
96
+ if (e ) {
97
+ e.stopPropagation();
98
+ e.preventDefault();
99
+ }
100
+ if (!this.isInput) {
101
+ }
102
+ var that = this;
103
+ $(document).on('mousedown', function(ev){
104
+ if ($(ev.target).closest('.datepicker').length == 0) {
105
+ that.hide();
106
+ }
107
+ });
108
+ this.element.trigger({
109
+ type: 'show',
110
+ date: this.date
111
+ });
112
+ },
113
+
114
+ hide: function(){
115
+ this.picker.hide();
116
+ $(window).off('resize', this.place);
117
+ this.viewMode = this.startViewMode;
118
+ this.showMode();
119
+ if (!this.isInput) {
120
+ $(document).off('mousedown', this.hide);
121
+ }
122
+ //this.set();
123
+ this.element.trigger({
124
+ type: 'hide',
125
+ date: this.date
126
+ });
127
+ },
128
+
129
+ set: function() {
130
+ var formated = DPGlobal.formatDate(this.date, this.format);
131
+ if (!this.isInput) {
132
+ if (this.component){
133
+ this.element.find('input').prop('value', formated);
134
+ }
135
+ this.element.data('date', formated);
136
+ } else {
137
+ this.element.prop('value', formated);
138
+ }
139
+ },
140
+
141
+ setValue: function(newDate) {
142
+ if (typeof newDate === 'string') {
143
+ this.date = DPGlobal.parseDate(newDate, this.format);
144
+ } else {
145
+ this.date = new Date(newDate);
146
+ }
147
+ this.set();
148
+ this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0);
149
+ this.fill();
150
+ },
151
+
152
+ place: function(){
153
+ var offset = this.component ? this.component.offset() : this.element.offset();
154
+ this.picker.css({
155
+ top: offset.top + this.height,
156
+ left: offset.left
157
+ });
158
+ },
159
+
160
+ update: function(newDate){
161
+ this.date = DPGlobal.parseDate(
162
+ typeof newDate === 'string' ? newDate : (this.isInput ? this.element.prop('value') : this.element.data('date')),
163
+ this.format
164
+ );
165
+ this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0);
166
+ this.fill();
167
+ },
168
+
169
+ fillDow: function(){
170
+ var dowCnt = this.weekStart;
171
+ var html = '<tr>';
172
+ while (dowCnt < this.weekStart + 7) {
173
+ html += '<th class="dow">'+DPGlobal.dates.daysMin[(dowCnt++)%7]+'</th>';
174
+ }
175
+ html += '</tr>';
176
+ this.picker.find('.datepicker-days thead').append(html);
177
+ },
178
+
179
+ fillMonths: function(){
180
+ var html = '';
181
+ var i = 0
182
+ while (i < 12) {
183
+ html += '<span class="month">'+DPGlobal.dates.monthsShort[i++]+'</span>';
184
+ }
185
+ this.picker.find('.datepicker-months td').append(html);
186
+ },
187
+
188
+ fill: function() {
189
+ var d = new Date(this.viewDate),
190
+ year = d.getFullYear(),
191
+ month = d.getMonth(),
192
+ currentDate = this.date.valueOf();
193
+ this.picker.find('.datepicker-days th:eq(1)')
194
+ .text(DPGlobal.dates.months[month]+' '+year);
195
+ var prevMonth = new Date(year, month-1, 28,0,0,0,0),
196
+ day = DPGlobal.getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());
197
+ prevMonth.setDate(day);
198
+ prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7)%7);
199
+ var nextMonth = new Date(prevMonth);
200
+ nextMonth.setDate(nextMonth.getDate() + 42);
201
+ nextMonth = nextMonth.valueOf();
202
+ var html = [];
203
+ var clsName,
204
+ prevY,
205
+ prevM;
206
+ while(prevMonth.valueOf() < nextMonth) {
207
+ if (prevMonth.getDay() === this.weekStart) {
208
+ html.push('<tr>');
209
+ }
210
+ clsName = this.onRender(prevMonth);
211
+ prevY = prevMonth.getFullYear();
212
+ prevM = prevMonth.getMonth();
213
+ if ((prevM < month && prevY === year) || prevY < year) {
214
+ clsName += ' old';
215
+ } else if ((prevM > month && prevY === year) || prevY > year) {
216
+ clsName += ' new';
217
+ }
218
+ if (prevMonth.valueOf() === currentDate) {
219
+ clsName += ' active';
220
+ }
221
+ html.push('<td class="day '+clsName+'">'+prevMonth.getDate() + '</td>');
222
+ if (prevMonth.getDay() === this.weekEnd) {
223
+ html.push('</tr>');
224
+ }
225
+ prevMonth.setDate(prevMonth.getDate()+1);
226
+ }
227
+ this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
228
+ var currentYear = this.date.getFullYear();
229
+
230
+ var months = this.picker.find('.datepicker-months')
231
+ .find('th:eq(1)')
232
+ .text(year)
233
+ .end()
234
+ .find('span').removeClass('active');
235
+ if (currentYear === year) {
236
+ months.eq(this.date.getMonth()).addClass('active');
237
+ }
238
+
239
+ html = '';
240
+ year = parseInt(year/10, 10) * 10;
241
+ var yearCont = this.picker.find('.datepicker-years')
242
+ .find('th:eq(1)')
243
+ .text(year + '-' + (year + 9))
244
+ .end()
245
+ .find('td');
246
+ year -= 1;
247
+ for (var i = -1; i < 11; i++) {
248
+ html += '<span class="year'+(i === -1 || i === 10 ? ' old' : '')+(currentYear === year ? ' active' : '')+'">'+year+'</span>';
249
+ year += 1;
250
+ }
251
+ yearCont.html(html);
252
+ },
253
+
254
+ click: function(e) {
255
+ e.stopPropagation();
256
+ e.preventDefault();
257
+ var target = $(e.target).closest('span, td, th');
258
+ if (target.length === 1) {
259
+ switch(target[0].nodeName.toLowerCase()) {
260
+ case 'th':
261
+ switch(target[0].className) {
262
+ case 'switch':
263
+ this.showMode(1);
264
+ break;
265
+ case 'prev':
266
+ case 'next':
267
+ this.viewDate['set'+DPGlobal.modes[this.viewMode].navFnc].call(
268
+ this.viewDate,
269
+ this.viewDate['get'+DPGlobal.modes[this.viewMode].navFnc].call(this.viewDate) +
270
+ DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1)
271
+ );
272
+ this.fill();
273
+ this.set();
274
+ break;
275
+ }
276
+ break;
277
+ case 'span':
278
+ if (target.is('.month')) {
279
+ var month = target.parent().find('span').index(target);
280
+ this.viewDate.setMonth(month);
281
+ } else {
282
+ var year = parseInt(target.text(), 10)||0;
283
+ this.viewDate.setFullYear(year);
284
+ }
285
+ if (this.viewMode !== 0) {
286
+ this.date = new Date(this.viewDate);
287
+ this.element.trigger({
288
+ type: 'changeDate',
289
+ date: this.date,
290
+ viewMode: DPGlobal.modes[this.viewMode].clsName
291
+ });
292
+ }
293
+ this.showMode(-1);
294
+ this.fill();
295
+ this.set();
296
+ break;
297
+ case 'td':
298
+ if (target.is('.day') && !target.is('.disabled')){
299
+ var day = parseInt(target.text(), 10)||1;
300
+ var month = this.viewDate.getMonth();
301
+ if (target.is('.old')) {
302
+ month -= 1;
303
+ } else if (target.is('.new')) {
304
+ month += 1;
305
+ }
306
+ var year = this.viewDate.getFullYear();
307
+ this.date = new Date(year, month, day,0,0,0,0);
308
+ this.viewDate = new Date(year, month, Math.min(28, day),0,0,0,0);
309
+ this.fill();
310
+ this.set();
311
+ this.element.trigger({
312
+ type: 'changeDate',
313
+ date: this.date,
314
+ viewMode: DPGlobal.modes[this.viewMode].clsName
315
+ });
316
+ }
317
+ break;
318
+ }
319
+ }
320
+ },
321
+
322
+ mousedown: function(e){
323
+ e.stopPropagation();
324
+ e.preventDefault();
325
+ },
326
+
327
+ showMode: function(dir) {
328
+ if (dir) {
329
+ this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
330
+ }
331
+ this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
332
+ }
333
+ };
334
+
335
+ $.fn.datepicker = function ( option, val ) {
336
+ return this.each(function () {
337
+ var $this = $(this),
338
+ data = $this.data('datepicker'),
339
+ options = typeof option === 'object' && option;
340
+ if (!data) {
341
+ $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options))));
342
+ }
343
+ if (typeof option === 'string') data[option](val);
344
+ });
345
+ };
346
+
347
+ $.fn.datepicker.defaults = {
348
+ onRender: function(date) {
349
+ return '';
350
+ }
351
+ };
352
+ $.fn.datepicker.Constructor = Datepicker;
353
+
354
+ var DPGlobal = {
355
+ modes: [
356
+ {
357
+ clsName: 'days',
358
+ navFnc: 'Month',
359
+ navStep: 1
360
+ },
361
+ {
362
+ clsName: 'months',
363
+ navFnc: 'FullYear',
364
+ navStep: 1
365
+ },
366
+ {
367
+ clsName: 'years',
368
+ navFnc: 'FullYear',
369
+ navStep: 10
370
+ }],
371
+ dates:{
372
+ days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
373
+ daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
374
+ daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
375
+ months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
376
+ monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
377
+ },
378
+ isLeapYear: function (year) {
379
+ return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))
380
+ },
381
+ getDaysInMonth: function (year, month) {
382
+ return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
383
+ },
384
+ parseFormat: function(format){
385
+ var separator = format.match(/[.\/\-\s].*?/),
386
+ parts = format.split(/\W+/);
387
+ if (!separator || !parts || parts.length === 0){
388
+ throw new Error("Invalid date format.");
389
+ }
390
+ return {separator: separator, parts: parts};
391
+ },
392
+ parseDate: function(date, format) {
393
+ var parts = date.split(format.separator),
394
+ date = new Date(),
395
+ val;
396
+ date.setHours(0);
397
+ date.setMinutes(0);
398
+ date.setSeconds(0);
399
+ date.setMilliseconds(0);
400
+ if (parts.length === format.parts.length) {
401
+ var year = date.getFullYear(), day = date.getDate(), month = date.getMonth();
402
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
403
+ val = parseInt(parts[i], 10)||1;
404
+ switch(format.parts[i]) {
405
+ case 'dd':
406
+ case 'd':
407
+ day = val;
408
+ date.setDate(val);
409
+ break;
410
+ case 'mm':
411
+ case 'm':
412
+ month = val - 1;
413
+ date.setMonth(val - 1);
414
+ break;
415
+ case 'yy':
416
+ year = 2000 + val;
417
+ date.setFullYear(2000 + val);
418
+ break;
419
+ case 'yyyy':
420
+ year = val;
421
+ date.setFullYear(val);
422
+ break;
423
+ }
424
+ }
425
+ date = new Date(year, month, day, 0 ,0 ,0);
426
+ }
427
+ return date;
428
+ },
429
+ formatDate: function(date, format){
430
+ var val = {
431
+ d: date.getDate(),
432
+ m: date.getMonth() + 1,
433
+ yy: date.getFullYear().toString().substring(2),
434
+ yyyy: date.getFullYear()
435
+ };
436
+ val.dd = (val.d < 10 ? '0' : '') + val.d;
437
+ val.mm = (val.m < 10 ? '0' : '') + val.m;
438
+ var date = [];
439
+ for (var i=0, cnt = format.parts.length; i < cnt; i++) {
440
+ date.push(val[format.parts[i]]);
441
+ }
442
+ return date.join(format.separator);
443
+ },
444
+ headTemplate: '<thead>'+
445
+ '<tr>'+
446
+ '<th class="prev">&lsaquo;</th>'+
447
+ '<th colspan="5" class="switch"></th>'+
448
+ '<th class="next">&rsaquo;</th>'+
449
+ '</tr>'+
450
+ '</thead>',
451
+ contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
452
+ };
453
+ DPGlobal.template = '<div class="datepicker dropdown-menu">'+
454
+ '<div class="datepicker-days">'+
455
+ '<table class=" table-condensed">'+
456
+ DPGlobal.headTemplate+
457
+ '<tbody></tbody>'+
458
+ '</table>'+
459
+ '</div>'+
460
+ '<div class="datepicker-months">'+
461
+ '<table class="table-condensed">'+
462
+ DPGlobal.headTemplate+
463
+ DPGlobal.contTemplate+
464
+ '</table>'+
465
+ '</div>'+
466
+ '<div class="datepicker-years">'+
467
+ '<table class="table-condensed">'+
468
+ DPGlobal.headTemplate+
469
+ DPGlobal.contTemplate+
470
+ '</table>'+
471
+ '</div>'+
472
+ '</div>';
473
+
474
+ }( window.jQuery );
@@ -252,6 +252,7 @@ class Model
252
252
 
253
253
  select: ->
254
254
  @db.selected this
255
+ @initDateControls()
255
256
 
256
257
  deselect: ->
257
258
  @deleting false
@@ -265,6 +266,19 @@ class Model
265
266
  @select()
266
267
  @editing true
267
268
 
269
+ initDateControls: ->
270
+ setTimeout ->
271
+ return unless @requiresDatePicker()
272
+ $('input.datepicker').datepicker(format: 'yyyy-mm-dd')
273
+ $('input.datepicker').on 'changeDate', (evt)->
274
+ $(this).trigger 'change'
275
+ , 100
276
+
277
+ requiresDatePicker: ->
278
+ i = document.createElement 'input'
279
+ i.setAttribute 'type', 'date'
280
+ return i.type != 'date'
281
+
268
282
  startDeleting: ->
269
283
  @edit()
270
284
  @deleting true
@@ -0,0 +1,182 @@
1
+ /*!
2
+ * Datepicker for Bootstrap
3
+ *
4
+ * Copyright 2012 Stefan Petre
5
+ * Licensed under the Apache License v2.0
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ */
9
+ .datepicker {
10
+ top: 0;
11
+ left: 0;
12
+ padding: 4px;
13
+ margin-top: 1px;
14
+ -webkit-border-radius: 4px;
15
+ -moz-border-radius: 4px;
16
+ border-radius: 4px;
17
+ /*.dow {
18
+ border-top: 1px solid #ddd !important;
19
+ }*/
20
+
21
+ }
22
+ .datepicker:before {
23
+ content: '';
24
+ display: inline-block;
25
+ border-left: 7px solid transparent;
26
+ border-right: 7px solid transparent;
27
+ border-bottom: 7px solid #ccc;
28
+ border-bottom-color: rgba(0, 0, 0, 0.2);
29
+ position: absolute;
30
+ top: -7px;
31
+ left: 6px;
32
+ }
33
+ .datepicker:after {
34
+ content: '';
35
+ display: inline-block;
36
+ border-left: 6px solid transparent;
37
+ border-right: 6px solid transparent;
38
+ border-bottom: 6px solid #ffffff;
39
+ position: absolute;
40
+ top: -6px;
41
+ left: 7px;
42
+ }
43
+ .datepicker > div {
44
+ display: none;
45
+ }
46
+ .datepicker table {
47
+ width: 100%;
48
+ margin: 0;
49
+ }
50
+ .datepicker td,
51
+ .datepicker th {
52
+ text-align: center;
53
+ width: 20px;
54
+ height: 20px;
55
+ -webkit-border-radius: 4px;
56
+ -moz-border-radius: 4px;
57
+ border-radius: 4px;
58
+ }
59
+ .datepicker td.day:hover {
60
+ background: #eeeeee;
61
+ cursor: pointer;
62
+ }
63
+ .datepicker td.day.disabled {
64
+ color: #eeeeee;
65
+ }
66
+ .datepicker td.old,
67
+ .datepicker td.new {
68
+ color: #999999;
69
+ }
70
+ .datepicker td.active,
71
+ .datepicker td.active:hover {
72
+ color: #ffffff;
73
+ background-color: #006dcc;
74
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
75
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
76
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
77
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
78
+ background-image: linear-gradient(to bottom, #0088cc, #0044cc);
79
+ background-repeat: repeat-x;
80
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
81
+ border-color: #0044cc #0044cc #002a80;
82
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
83
+ *background-color: #0044cc;
84
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
85
+
86
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
87
+ color: #fff;
88
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
89
+ }
90
+ .datepicker td.active:hover,
91
+ .datepicker td.active:hover:hover,
92
+ .datepicker td.active:focus,
93
+ .datepicker td.active:hover:focus,
94
+ .datepicker td.active:active,
95
+ .datepicker td.active:hover:active,
96
+ .datepicker td.active.active,
97
+ .datepicker td.active:hover.active,
98
+ .datepicker td.active.disabled,
99
+ .datepicker td.active:hover.disabled,
100
+ .datepicker td.active[disabled],
101
+ .datepicker td.active:hover[disabled] {
102
+ color: #ffffff;
103
+ background-color: #0044cc;
104
+ *background-color: #003bb3;
105
+ }
106
+ .datepicker td.active:active,
107
+ .datepicker td.active:hover:active,
108
+ .datepicker td.active.active,
109
+ .datepicker td.active:hover.active {
110
+ background-color: #003399 \9;
111
+ }
112
+ .datepicker td span {
113
+ display: block;
114
+ width: 47px;
115
+ height: 54px;
116
+ line-height: 54px;
117
+ float: left;
118
+ margin: 2px;
119
+ cursor: pointer;
120
+ -webkit-border-radius: 4px;
121
+ -moz-border-radius: 4px;
122
+ border-radius: 4px;
123
+ }
124
+ .datepicker td span:hover {
125
+ background: #eeeeee;
126
+ }
127
+ .datepicker td span.active {
128
+ color: #ffffff;
129
+ background-color: #006dcc;
130
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
131
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
132
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
133
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
134
+ background-image: linear-gradient(to bottom, #0088cc, #0044cc);
135
+ background-repeat: repeat-x;
136
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
137
+ border-color: #0044cc #0044cc #002a80;
138
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
139
+ *background-color: #0044cc;
140
+ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
141
+
142
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
143
+ color: #fff;
144
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
145
+ }
146
+ .datepicker td span.active:hover,
147
+ .datepicker td span.active:focus,
148
+ .datepicker td span.active:active,
149
+ .datepicker td span.active.active,
150
+ .datepicker td span.active.disabled,
151
+ .datepicker td span.active[disabled] {
152
+ color: #ffffff;
153
+ background-color: #0044cc;
154
+ *background-color: #003bb3;
155
+ }
156
+ .datepicker td span.active:active,
157
+ .datepicker td span.active.active {
158
+ background-color: #003399 \9;
159
+ }
160
+ .datepicker td span.old {
161
+ color: #999999;
162
+ }
163
+ .datepicker th.switch {
164
+ width: 145px;
165
+ }
166
+ .datepicker th.next,
167
+ .datepicker th.prev {
168
+ font-size: 21px;
169
+ }
170
+ .datepicker thead tr:first-child th {
171
+ cursor: pointer;
172
+ }
173
+ .datepicker thead tr:first-child th:hover {
174
+ background: #eeeeee;
175
+ }
176
+ .input-append.date .add-on i,
177
+ .input-prepend.date .add-on i {
178
+ display: block;
179
+ cursor: pointer;
180
+ width: 16px;
181
+ height: 16px;
182
+ }
data/lib/kolo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Kolo
2
- VERSION = "0.6.8"
2
+ VERSION = "0.6.9"
3
3
  end
@@ -1,31 +1,33 @@
1
- // Generated by CoffeeScript 1.6.2
1
+ // Generated by CoffeeScript 1.7.1
2
2
  (function() {
3
3
  var Db, Model, ViewModel,
4
4
  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
5
5
 
6
6
  ViewModel = (function() {
7
7
  function ViewModel() {
8
- var _this = this;
9
-
10
8
  this.loading = ko.observable(false);
11
9
  this.flashMessage = ko.observable('');
12
- this.flashMessage.subscribe(function(newValue) {
13
- if ((newValue != null) && newValue !== '') {
14
- setTimeout(function() {
15
- return _this.flashMessage('');
16
- }, 10000);
17
- }
18
- return true;
19
- });
10
+ this.flashMessage.subscribe((function(_this) {
11
+ return function(newValue) {
12
+ if ((newValue != null) && newValue !== '') {
13
+ setTimeout(function() {
14
+ return _this.flashMessage('');
15
+ }, 10000);
16
+ }
17
+ return true;
18
+ };
19
+ })(this));
20
20
  this.errorMessage = ko.observable('');
21
- this.errorMessage.subscribe(function(newValue) {
22
- if ((newValue != null) && newValue !== '') {
23
- setTimeout(function() {
24
- return _this.errorMessage('');
25
- }, 10000);
26
- }
27
- return true;
28
- });
21
+ this.errorMessage.subscribe((function(_this) {
22
+ return function(newValue) {
23
+ if ((newValue != null) && newValue !== '') {
24
+ setTimeout(function() {
25
+ return _this.errorMessage('');
26
+ }, 10000);
27
+ }
28
+ return true;
29
+ };
30
+ })(this));
29
31
  }
30
32
 
31
33
  ViewModel.prototype.systemNotification = function(name, value) {
@@ -34,12 +36,12 @@
34
36
  };
35
37
 
36
38
  ViewModel.prototype.flashPanel = function(elementId) {
37
- var _this = this;
38
-
39
39
  $(elementId).fadeIn();
40
- return setTimeout(function() {
41
- return $(elementId).fadeOut();
42
- }, 10000);
40
+ return setTimeout((function(_this) {
41
+ return function() {
42
+ return $(elementId).fadeOut();
43
+ };
44
+ })(this), 10000);
43
45
  };
44
46
 
45
47
  return ViewModel;
@@ -48,8 +50,6 @@
48
50
 
49
51
  Db = (function() {
50
52
  function Db(viewModel, name, url, pushStateUri) {
51
- var _this = this;
52
-
53
53
  this.viewModel = viewModel;
54
54
  this.name = name;
55
55
  this.pushStateUri = pushStateUri;
@@ -74,14 +74,16 @@
74
74
  this.createUrl = ko.observable(url);
75
75
  this.items = ko.observableArray([]);
76
76
  this.selected = ko.observable(null);
77
- this.selected.subscribe(function(newValue) {
78
- if (_this.selected() == null) {
79
- return;
80
- }
81
- if (_this.selected().hasBeenSelected) {
82
- return _this.selected().hasBeenSelected();
83
- }
84
- });
77
+ this.selected.subscribe((function(_this) {
78
+ return function(newValue) {
79
+ if (_this.selected() == null) {
80
+ return;
81
+ }
82
+ if (_this.selected().hasBeenSelected) {
83
+ return _this.selected().hasBeenSelected();
84
+ }
85
+ };
86
+ })(this));
85
87
  this.plural = "" + this.name + "s";
86
88
  this.sortFunction = null;
87
89
  this.onAfterLoad = null;
@@ -91,25 +93,28 @@
91
93
  this.onAfterPost = null;
92
94
  this.autoLoading = false;
93
95
  this.loading = false;
94
- this.url.subscribe(function(newValue) {
95
- if (newValue != null) {
96
- return _this.load(false);
97
- }
98
- });
99
- if ((this.pushStateUri != null) && (history.pushState != null)) {
100
- this.selected.subscribe(function(newValue) {
101
- if ((newValue != null) && (newValue.id != null)) {
102
- return history.pushState(_this.selected().name(), _this.selected().name(), "" + _this.pushStateUri + "/" + (_this.selected().id));
103
- } else {
104
- return history.pushState('', '', _this.pushStateUri);
96
+ this.url.subscribe((function(_this) {
97
+ return function(newValue) {
98
+ if (newValue != null) {
99
+ return _this.load(false);
105
100
  }
106
- });
101
+ };
102
+ })(this));
103
+ if ((this.pushStateUri != null) && (history.pushState != null)) {
104
+ this.selected.subscribe((function(_this) {
105
+ return function(newValue) {
106
+ if ((newValue != null) && (newValue.id != null)) {
107
+ return history.pushState(_this.selected().name(), _this.selected().name(), "" + _this.pushStateUri + "/" + (_this.selected().id));
108
+ } else {
109
+ return history.pushState('', '', _this.pushStateUri);
110
+ }
111
+ };
112
+ })(this));
107
113
  }
108
114
  }
109
115
 
110
116
  Db.prototype.find = function(id) {
111
117
  var item, _i, _len, _ref;
112
-
113
118
  _ref = this.items();
114
119
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
115
120
  item = _ref[_i];
@@ -122,7 +127,6 @@
122
127
 
123
128
  Db.prototype.findOrCreate = function(id) {
124
129
  var item;
125
-
126
130
  item = this.find(id);
127
131
  if (item == null) {
128
132
  item = this.newItem(id);
@@ -139,8 +143,6 @@
139
143
  };
140
144
 
141
145
  Db.prototype.load = function(autoReload, afterLoad) {
142
- var _this = this;
143
-
144
146
  if (autoReload == null) {
145
147
  autoReload = false;
146
148
  }
@@ -156,30 +158,32 @@
156
158
  if (this.onBeforeLoad != null) {
157
159
  this.onBeforeLoad();
158
160
  }
159
- $.get(this.url(), function(data) {
160
- _this.doLoad(data);
161
- if (afterLoad != null) {
162
- afterLoad(data);
163
- }
164
- if (_this.onAfterLoad != null) {
165
- _this.onAfterLoad(data);
166
- }
167
- _this.viewModel.loading(false);
168
- return _this.viewModel.systemNotification(_this.plural, 'loaded');
169
- });
161
+ $.get(this.url(), (function(_this) {
162
+ return function(data) {
163
+ _this.doLoad(data);
164
+ if (afterLoad != null) {
165
+ afterLoad(data);
166
+ }
167
+ if (_this.onAfterLoad != null) {
168
+ _this.onAfterLoad(data);
169
+ }
170
+ _this.viewModel.loading(false);
171
+ return _this.viewModel.systemNotification(_this.plural, 'loaded');
172
+ };
173
+ })(this));
170
174
  }
171
175
  if (autoReload) {
172
176
  this.autoLoading = true;
173
- setTimeout(function() {
174
- return _this.load(true, afterLoad);
175
- }, 30000);
177
+ setTimeout((function(_this) {
178
+ return function() {
179
+ return _this.load(true, afterLoad);
180
+ };
181
+ })(this), 30000);
176
182
  }
177
183
  return false;
178
184
  };
179
185
 
180
186
  Db.prototype.postTo = function(url, data, afterPost) {
181
- var _this = this;
182
-
183
187
  this.viewModel.systemNotification(this.name, 'saving');
184
188
  this.viewModel.loading(true);
185
189
  $.ajax({
@@ -187,24 +191,25 @@
187
191
  dataType: 'json',
188
192
  type: 'POST',
189
193
  data: data,
190
- success: function(data) {
191
- if (afterPost != null) {
192
- afterPost(data);
193
- }
194
- if (_this.onAfterPost != null) {
195
- _this.onAfterPost(data);
196
- }
197
- _this.viewModel.loading(false);
198
- _this.viewModel.systemNotification(_this.name, 'saved');
199
- return _this.load(false);
200
- }
194
+ success: (function(_this) {
195
+ return function(data) {
196
+ if (afterPost != null) {
197
+ afterPost(data);
198
+ }
199
+ if (_this.onAfterPost != null) {
200
+ _this.onAfterPost(data);
201
+ }
202
+ _this.viewModel.loading(false);
203
+ _this.viewModel.systemNotification(_this.name, 'saved');
204
+ return _this.load(false);
205
+ };
206
+ })(this)
201
207
  });
202
208
  return true;
203
209
  };
204
210
 
205
211
  Db.prototype.add = function() {
206
212
  var itemToAdd;
207
-
208
213
  itemToAdd = this.newItem(null);
209
214
  this.selected(itemToAdd);
210
215
  this.viewModel.systemNotification(this.name, 'new');
@@ -224,7 +229,6 @@
224
229
 
225
230
  Db.prototype.doLoad = function(data) {
226
231
  var item, itemData, _i, _len, _ref;
227
-
228
232
  _ref = this.itemDataFrom(data);
229
233
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
230
234
  itemData = _ref[_i];
@@ -243,8 +247,6 @@
243
247
  };
244
248
 
245
249
  Db.prototype.doCreate = function(item, afterSave) {
246
- var _this = this;
247
-
248
250
  this.viewModel.systemNotification(this.name, 'saving');
249
251
  this.viewModel.loading(true);
250
252
  $.ajax({
@@ -252,28 +254,28 @@
252
254
  dataType: 'json',
253
255
  type: 'POST',
254
256
  data: this.toJS(item),
255
- success: function(data) {
256
- if (data.id != null) {
257
- item.id = data.id;
258
- }
259
- _this.selected(null);
260
- if (afterSave != null) {
261
- afterSave(item);
262
- }
263
- if (_this.onAfterSave != null) {
264
- _this.onAfterSave(item);
265
- }
266
- _this.viewModel.systemNotification(_this.name, 'saved');
267
- _this.viewModel.loading(false);
268
- return _this.load();
269
- }
257
+ success: (function(_this) {
258
+ return function(data) {
259
+ if (data.id != null) {
260
+ item.id = data.id;
261
+ }
262
+ _this.selected(null);
263
+ if (afterSave != null) {
264
+ afterSave(item);
265
+ }
266
+ if (_this.onAfterSave != null) {
267
+ _this.onAfterSave(item);
268
+ }
269
+ _this.viewModel.systemNotification(_this.name, 'saved');
270
+ _this.viewModel.loading(false);
271
+ return _this.load();
272
+ };
273
+ })(this)
270
274
  });
271
275
  return false;
272
276
  };
273
277
 
274
278
  Db.prototype.doUpdate = function(item, afterSave) {
275
- var _this = this;
276
-
277
279
  this.viewModel.systemNotification(this.name, 'saving');
278
280
  this.viewModel.loading(true);
279
281
  $.ajax({
@@ -281,45 +283,47 @@
281
283
  dataType: 'json',
282
284
  type: 'PUT',
283
285
  data: this.toJS(item),
284
- success: function(data) {
285
- _this.selected(null);
286
- if (afterSave != null) {
287
- afterSave(item);
288
- }
289
- if (_this.onAfterSave != null) {
290
- _this.onAfterSave(item);
291
- }
292
- _this.viewModel.systemNotification(_this.name, 'saved');
293
- _this.viewModel.loading(false);
294
- return _this.load();
295
- }
286
+ success: (function(_this) {
287
+ return function(data) {
288
+ _this.selected(null);
289
+ if (afterSave != null) {
290
+ afterSave(item);
291
+ }
292
+ if (_this.onAfterSave != null) {
293
+ _this.onAfterSave(item);
294
+ }
295
+ _this.viewModel.systemNotification(_this.name, 'saved');
296
+ _this.viewModel.loading(false);
297
+ return _this.load();
298
+ };
299
+ })(this)
296
300
  });
297
301
  return false;
298
302
  };
299
303
 
300
304
  Db.prototype.doDestroy = function(item, afterDelete) {
301
- var _this = this;
302
-
303
305
  this.viewModel.systemNotification(this.name, 'deleting');
304
306
  this.viewModel.loading(true);
305
307
  $.ajax({
306
308
  url: this.urlFor(item),
307
309
  dataType: 'json',
308
310
  type: 'DELETE',
309
- success: function(data) {
310
- item.id = null;
311
- _this.selected(null);
312
- _this.items.remove(item);
313
- if (afterDelete != null) {
314
- afterDelete();
315
- }
316
- if (_this.onAfterDelete != null) {
317
- _this.onAfterDelete(item);
318
- }
319
- _this.viewModel.systemNotification(_this.name, 'deleted');
320
- _this.viewModel.loading(false);
321
- return _this.load();
322
- }
311
+ success: (function(_this) {
312
+ return function(data) {
313
+ item.id = null;
314
+ _this.selected(null);
315
+ _this.items.remove(item);
316
+ if (afterDelete != null) {
317
+ afterDelete();
318
+ }
319
+ if (_this.onAfterDelete != null) {
320
+ _this.onAfterDelete(item);
321
+ }
322
+ _this.viewModel.systemNotification(_this.name, 'deleted');
323
+ _this.viewModel.loading(false);
324
+ return _this.load();
325
+ };
326
+ })(this)
323
327
  });
324
328
  return false;
325
329
  };
@@ -358,8 +362,6 @@
358
362
 
359
363
  Model = (function() {
360
364
  function Model(id, db) {
361
- var _this = this;
362
-
363
365
  this.id = id;
364
366
  this.db = db;
365
367
  this.elementSelector = __bind(this.elementSelector, this);
@@ -368,9 +370,11 @@
368
370
  this.editing = ko.observable(false);
369
371
  this.deleting = ko.observable(false);
370
372
  this.updating = ko.observable(false);
371
- this.selected = ko.computed(function() {
372
- return _this.db.selected() === _this;
373
- });
373
+ this.selected = ko.computed((function(_this) {
374
+ return function() {
375
+ return _this.db.selected() === _this;
376
+ };
377
+ })(this));
374
378
  }
375
379
 
376
380
  Model.prototype.viewModel = function() {
@@ -394,7 +398,8 @@
394
398
  };
395
399
 
396
400
  Model.prototype.select = function() {
397
- return this.db.selected(this);
401
+ this.db.selected(this);
402
+ return this.initDateControls();
398
403
  };
399
404
 
400
405
  Model.prototype.deselect = function() {
@@ -410,6 +415,27 @@
410
415
  return this.editing(true);
411
416
  };
412
417
 
418
+ Model.prototype.initDateControls = function() {
419
+ return setTimeout(function() {
420
+ if (!this.requiresDatePicker()) {
421
+ return;
422
+ }
423
+ $('input.datepicker').datepicker({
424
+ format: 'yyyy-mm-dd'
425
+ });
426
+ return $('input.datepicker').on('changeDate', function(evt) {
427
+ return $(this).trigger('change');
428
+ });
429
+ }, 100);
430
+ };
431
+
432
+ Model.prototype.requiresDatePicker = function() {
433
+ var i;
434
+ i = document.createElement('input');
435
+ i.setAttribute('type', 'date');
436
+ return i.type !== 'date';
437
+ };
438
+
413
439
  Model.prototype.startDeleting = function() {
414
440
  this.edit();
415
441
  return this.deleting(true);
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kolo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.8
4
+ version: 0.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rahoul Baruah
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-04 00:00:00.000000000 Z
11
+ date: 2014-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -60,6 +60,7 @@ files:
60
60
  - lib/assets/images/glyphicons-halflings.png
61
61
  - lib/assets/images/loader.gif
62
62
  - lib/assets/javascripts/bindings.js.coffee
63
+ - lib/assets/javascripts/bootstrap-datepicker.js
63
64
  - lib/assets/javascripts/bootstrap.min.js
64
65
  - lib/assets/javascripts/data-access.js.coffee
65
66
  - lib/assets/javascripts/jquery.hammer.js
@@ -70,6 +71,7 @@ files:
70
71
  - lib/assets/javascripts/knockout.mapping.js
71
72
  - lib/assets/stylesheets/bootstrap-responsive.css
72
73
  - lib/assets/stylesheets/bootstrap.css
74
+ - lib/assets/stylesheets/datepicker.css
73
75
  - lib/assets/stylesheets/font-awesome.css.erb
74
76
  - lib/kolo.rb
75
77
  - lib/kolo/icons.rb