right-rails 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/CHANGELOG +8 -0
  2. data/README.rdoc +71 -0
  3. data/Rakefile +144 -14
  4. data/generators/right_rails/right_rails_generator.rb +18 -21
  5. data/init.rb +11 -32
  6. data/lib/generators/right_rails/right_rails_generator.rb +27 -0
  7. data/lib/generators/right_rails/templates/iframed.html.erb +10 -0
  8. data/lib/right-rails.rb +1 -1
  9. data/lib/right_rails/config.rb +278 -0
  10. data/lib/right_rails/controller_extensions.rb +10 -5
  11. data/lib/right_rails/helpers/basic.rb +10 -66
  12. data/lib/right_rails/helpers/forms.rb +141 -139
  13. data/lib/right_rails/helpers/misc.rb +45 -67
  14. data/lib/right_rails/helpers/rails.rb +40 -105
  15. data/lib/right_rails/helpers.rb +364 -1
  16. data/lib/right_rails/java_script_generator.rb +34 -24
  17. data/lib/right_rails.rb +6 -1
  18. data/{images → public/images}/colorpicker.png +0 -0
  19. data/{images → public/images}/resizable.png +0 -0
  20. data/public/javascripts/right/autocompleter-src.js +612 -0
  21. data/public/javascripts/right/autocompleter.js +18 -0
  22. data/public/javascripts/right/calendar-src.js +1448 -0
  23. data/public/javascripts/right/calendar.js +36 -0
  24. data/public/javascripts/right/colorpicker-src.js +967 -0
  25. data/public/javascripts/right/colorpicker.js +26 -0
  26. data/{javascripts/right-dnd-src.js → public/javascripts/right/dnd-src.js} +86 -52
  27. data/public/javascripts/right/dnd.js +20 -0
  28. data/{javascripts/right-effects-src.js → public/javascripts/right/effects-src.js} +90 -45
  29. data/public/javascripts/right/effects.js +17 -0
  30. data/{javascripts/right-ui-i18n-de.js → public/javascripts/right/i18n/de.js} +7 -7
  31. data/{javascripts/right-ui-i18n-en-us.js → public/javascripts/right/i18n/en-us.js} +1 -1
  32. data/{javascripts/right-ui-i18n-es.js → public/javascripts/right/i18n/es.js} +7 -7
  33. data/{javascripts/right-ui-i18n-fr.js → public/javascripts/right/i18n/fr.js} +7 -7
  34. data/{javascripts/right-ui-i18n-hu.js → public/javascripts/right/i18n/hu.js} +7 -7
  35. data/{javascripts/right-ui-i18n-jp.js → public/javascripts/right/i18n/jp.js} +7 -7
  36. data/{javascripts/right-ui-i18n-nl.js → public/javascripts/right/i18n/nl.js} +7 -7
  37. data/{javascripts/right-ui-i18n-pt-br.js → public/javascripts/right/i18n/pt-br.js} +7 -7
  38. data/{javascripts/right-ui-i18n-ru.js → public/javascripts/right/i18n/ru.js} +7 -7
  39. data/{javascripts/right-ui-i18n-ua.js → public/javascripts/right/i18n/ua.js} +17 -12
  40. data/public/javascripts/right/in-edit-src.js +352 -0
  41. data/public/javascripts/right/in-edit.js +13 -0
  42. data/public/javascripts/right/json-src.js +160 -0
  43. data/public/javascripts/right/json.js +10 -0
  44. data/public/javascripts/right/lightbox-src.js +881 -0
  45. data/public/javascripts/right/lightbox.js +24 -0
  46. data/{javascripts/right-rails-src.js → public/javascripts/right/rails-src.js} +195 -171
  47. data/public/javascripts/right/rails.js +14 -0
  48. data/public/javascripts/right/rater-src.js +366 -0
  49. data/public/javascripts/right/rater.js +13 -0
  50. data/public/javascripts/right/resizable-src.js +420 -0
  51. data/public/javascripts/right/resizable.js +15 -0
  52. data/public/javascripts/right/selectable-src.js +687 -0
  53. data/public/javascripts/right/selectable.js +22 -0
  54. data/public/javascripts/right/slider-src.js +377 -0
  55. data/public/javascripts/right/slider.js +14 -0
  56. data/public/javascripts/right/sortable-src.js +392 -0
  57. data/public/javascripts/right/sortable.js +16 -0
  58. data/public/javascripts/right/tabs-src.js +1123 -0
  59. data/public/javascripts/right/tabs.js +29 -0
  60. data/public/javascripts/right/tooltip-src.js +307 -0
  61. data/public/javascripts/right/tooltip.js +12 -0
  62. data/public/javascripts/right/uploader-src.js +283 -0
  63. data/public/javascripts/right/uploader.js +13 -0
  64. data/{javascripts → public/javascripts}/right-olds-src.js +134 -186
  65. data/public/javascripts/right-olds.js +18 -0
  66. data/public/javascripts/right-safe-src.js +161 -0
  67. data/public/javascripts/right-safe.js +8 -0
  68. data/{javascripts → public/javascripts}/right-src.js +2558 -1750
  69. data/public/javascripts/right.js +92 -0
  70. data/spec/lib/right_rails/config_spec.rb +133 -0
  71. data/spec/lib/right_rails/controller_extensions_spec.rb +1 -1
  72. data/spec/lib/right_rails/helpers/basic_spec.rb +77 -66
  73. data/spec/lib/right_rails/helpers/forms_spec.rb +231 -33
  74. data/spec/lib/right_rails/helpers/misc_spec.rb +94 -26
  75. data/spec/lib/right_rails/helpers/rails_spec.rb +42 -7
  76. data/spec/lib/right_rails/helpers_spec.rb +125 -0
  77. data/spec/lib/right_rails/java_script_generator_spec.rb +30 -0
  78. data/spec/rcov.opts +3 -0
  79. data/spec/spec_helper.rb +12 -7
  80. metadata +70 -61
  81. data/README.textile +0 -69
  82. data/javascripts/right-autocompleter-src.js +0 -318
  83. data/javascripts/right-autocompleter.js +0 -9
  84. data/javascripts/right-behavior-src.js +0 -261
  85. data/javascripts/right-behavior.js +0 -8
  86. data/javascripts/right-calendar-src.js +0 -946
  87. data/javascripts/right-calendar.js +0 -9
  88. data/javascripts/right-colorpicker-src.js +0 -635
  89. data/javascripts/right-colorpicker.js +0 -9
  90. data/javascripts/right-dnd.js +0 -9
  91. data/javascripts/right-effects.js +0 -6
  92. data/javascripts/right-events-src.js +0 -321
  93. data/javascripts/right-events.js +0 -6
  94. data/javascripts/right-in-edit-src.js +0 -194
  95. data/javascripts/right-in-edit.js +0 -6
  96. data/javascripts/right-json-src.js +0 -141
  97. data/javascripts/right-json.js +0 -6
  98. data/javascripts/right-lightbox-src.js +0 -651
  99. data/javascripts/right-lightbox.js +0 -9
  100. data/javascripts/right-olds.js +0 -9
  101. data/javascripts/right-rails.js +0 -9
  102. data/javascripts/right-rater-src.js +0 -253
  103. data/javascripts/right-rater.js +0 -9
  104. data/javascripts/right-resizable-src.js +0 -336
  105. data/javascripts/right-resizable.js +0 -9
  106. data/javascripts/right-selectable-src.js +0 -565
  107. data/javascripts/right-selectable.js +0 -7
  108. data/javascripts/right-slider-src.js +0 -288
  109. data/javascripts/right-slider.js +0 -7
  110. data/javascripts/right-sortable-src.js +0 -225
  111. data/javascripts/right-sortable.js +0 -9
  112. data/javascripts/right-tabs-src.js +0 -937
  113. data/javascripts/right-tabs.js +0 -6
  114. data/javascripts/right-tooltips-src.js +0 -195
  115. data/javascripts/right-tooltips.js +0 -9
  116. data/javascripts/right-uploader-src.js +0 -167
  117. data/javascripts/right-uploader.js +0 -9
  118. data/javascripts/right.js +0 -7
@@ -1,946 +0,0 @@
1
- /**
2
- * The calendar widget implemented with RightJS
3
- *
4
- * Home page: http://rightjs.org/ui/calendar
5
- *
6
- * @copyright (C) 2009-2010 Nikolay V. Nemshilov
7
- */
8
- if (!RightJS) { throw "Gimme RightJS. Please." };
9
- /**
10
- * The calendar widget for RightJS
11
- *
12
- * Copyright (C) 2009-2010 Nikolay V. Nemshilov
13
- */
14
- var Calendar = new Class(Observer, {
15
- extend: {
16
- EVENTS: $w('show hide select done'),
17
-
18
- Options: {
19
- format: 'ISO', // a key out of the predefined formats or a format string
20
- showTime: null, // null for automatic, or true|false to enforce
21
- showButtons: false,
22
- minDate: null,
23
- maxDate: null,
24
- firstDay: 1, // 1 for Monday, 0 for Sunday
25
- fxName: 'fade', // set to null if you don't wanna any fx
26
- fxDuration: 200,
27
- numberOfMonths: 1, // a number or [x, y] greed definition
28
- timePeriod: 1, // the timepicker minimal periods (in minutes, might be bigger than 60)
29
-
30
- twentyFourHour: null, // null for automatic, or true|false to enforce
31
- listYears: false, // show/hide the years listing buttons
32
-
33
- hideOnPick: false, // hides the popup when the user changes a day
34
-
35
- cssRule: '[rel^=calendar]' // css rule for calendar related elements
36
- },
37
-
38
- Formats: {
39
- ISO: '%Y-%m-%d',
40
- POSIX: '%Y/%m/%d',
41
- EUR: '%d-%m-%Y',
42
- US: '%m/%d/%Y'
43
- },
44
-
45
- i18n: {
46
- Done: 'Done',
47
- Now: 'Now',
48
- Next: 'Next Month',
49
- Prev: 'Previous Month',
50
- NextYear: 'Next Year',
51
- PrevYear: 'Previous Year',
52
-
53
- dayNames: $w('Sunday Monday Tuesday Wednesday Thursday Friday Saturday'),
54
- dayNamesShort: $w('Sun Mon Tue Wed Thu Fri Sat'),
55
- dayNamesMin: $w('Su Mo Tu We Th Fr Sa'),
56
- monthNames: $w('January February March April May June July August September October November December'),
57
- monthNamesShort: $w('Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec')
58
- },
59
-
60
- current: null, // marker to the currently visible calendar
61
- instances: {}, // list of registered instances
62
-
63
- // finds and/or instanciates a Calendar related to the event target
64
- find: function(event) {
65
- var element = event.target;
66
-
67
- if (isElement(element) && element.match(Calendar.Options.cssRule)) {
68
- var uid = $uid(element);
69
- return Calendar.instances[uid] = Calendar.instances[uid] ||
70
- new Calendar(eval('('+element.get('data-calendar-options')+')'));
71
- }
72
- },
73
-
74
- // DEPRECATED scans for the auto-discoverable calendar inputs
75
- rescan: function(scope) { }
76
- },
77
-
78
- /**
79
- * Basic constructor
80
- *
81
- * @param Object options
82
- */
83
- initialize: function(options) {
84
- this.$super(options);
85
-
86
- this.element = $E('div', {'class': 'right-calendar', calendar: this});
87
- this.build().connectEvents().setDate(new Date());
88
- },
89
-
90
- /**
91
- * additional options processing
92
- *
93
- * @param Object options
94
- * @return Calendar this
95
- */
96
- setOptions: function(user_options) {
97
- this.$super(user_options);
98
-
99
- var klass = this.constructor;
100
- var options = this.options;
101
-
102
- with (this.options) {
103
- // merging the i18n tables
104
- options.i18n = {};
105
-
106
- for (var key in klass.i18n) {
107
- i18n[key] = isArray(klass.i18n[key]) ? klass.i18n[key].clone() : klass.i18n[key];
108
- }
109
- $ext(i18n, (user_options || {}).i18n);
110
-
111
- // defining the current days sequence
112
- options.dayNames = i18n.dayNamesMin;
113
- if (firstDay) {
114
- dayNames.push(dayNames.shift());
115
- }
116
-
117
- // the monthes table cleaning up
118
- if (!isArray(numberOfMonths)) {
119
- numberOfMonths = [numberOfMonths, 1];
120
- }
121
-
122
- // min/max dates preprocessing
123
- if (minDate) minDate = this.parse(minDate);
124
- if (maxDate) {
125
- maxDate = this.parse(maxDate);
126
- maxDate.setDate(maxDate.getDate() + 1);
127
- }
128
-
129
- // format catching up
130
- format = (klass.Formats[format] || format).trim();
131
-
132
- // setting up the showTime option
133
- if (showTime === null) {
134
- showTime = format.search(/%[HkIl]/) > -1;
135
- }
136
-
137
- // setting up the 24-hours format
138
- if (twentyFourHour === null) {
139
- twentyFourHour = format.search(/%[Il]/) < 0;
140
- }
141
-
142
- // enforcing the 24 hours format if the time threshold is some weird number
143
- if (timePeriod > 60 && 12 % (timePeriod/60).ceil()) {
144
- twentyFourHour = true;
145
- }
146
- }
147
-
148
- return this;
149
- },
150
-
151
- /**
152
- * Sets the date on the calendar
153
- *
154
- * @param Date date or String date
155
- * @return Calendar this
156
- */
157
- setDate: function(date) {
158
- this.date = this.prevDate = this.parse(date);
159
- return this.update();
160
- },
161
-
162
- /**
163
- * Returns the current date on the calendar
164
- *
165
- * @return Date currently selected date on the calendar
166
- */
167
- getDate: function() {
168
- return this.date;
169
- },
170
-
171
- /**
172
- * Hides the calendar
173
- *
174
- * @return Calendar this
175
- */
176
- hide: function() {
177
- this.element.hide(this.options.fxName, {duration: this.options.fxDuration});
178
- Calendar.current = null;
179
- return this;
180
- },
181
-
182
- /**
183
- * Shows the calendar
184
- *
185
- * @param Object {x,y} optional position
186
- * @return Calendar this
187
- */
188
- show: function(position) {
189
- this.element.show(this.options.fxName, {duration: this.options.fxDuration});
190
- return Calendar.current = this;
191
- },
192
-
193
- /**
194
- * Inserts the calendar into the element making it inlined
195
- *
196
- * @param Element element or String element id
197
- * @param String optional position top/bottom/before/after/instead, 'bottom' is default
198
- * @return Calendar this
199
- */
200
- insertTo: function(element, position) {
201
- this.element.addClass('right-calendar-inline').insertTo(element, position);
202
- return this;
203
- },
204
-
205
- /**
206
- * Checks if the calendar is inlined
207
- *
208
- * @return boolean check
209
- */
210
- inlined: function() {
211
- return this.element.hasClass('right-calendar-inline');
212
- }
213
- });
214
-
215
- /**
216
- * This module handles the calendar elemnts building/updating processes
217
- *
218
- * Copyright (C) 2009-2010 Nikolay V. Nemshilov
219
- */
220
- Calendar.include({
221
-
222
- // protected
223
-
224
- // updates the calendar view
225
- update: function(date) {
226
- var date = new Date(date || this.date), options = this.options;
227
-
228
- var monthes = this.element.select('div.right-calendar-month');
229
- var monthes_num = monthes.length;
230
-
231
- for (var i=-(monthes_num - monthes_num/2).ceil()+1; i < (monthes_num - monthes_num/2).floor()+1; i++) {
232
- var month_date = new Date(date);
233
- month_date.setMonth(date.getMonth() + i);
234
-
235
- this.updateMonth(monthes.shift(), month_date);
236
- }
237
-
238
- this.updateNextPrevMonthButtons(date, monthes_num);
239
-
240
- if (options.showTime) {
241
- this.hours.value = options.timePeriod < 60 ? date.getHours() :
242
- (date.getHours()/(options.timePeriod/60)).round() * (options.timePeriod/60);
243
-
244
- this.minutes.value = (date.getMinutes() / (options.timePeriod % 60)).round() * options.timePeriod;
245
- }
246
-
247
- return this;
248
- },
249
-
250
- // updates a single month-block with the given date
251
- updateMonth: function(element, date) {
252
- // getting the number of days in the month
253
- date.setDate(32);
254
- var days_number = 32 - date.getDate();
255
- date.setMonth(date.getMonth()-1);
256
-
257
- var cur_day = (this.date.getTime() / 86400000).ceil();
258
-
259
- // collecting the elements to update
260
- var rows = element.select('tbody tr');
261
- var cells = rows.shift().select('td');
262
- element.select('tbody td').each(function(td) {
263
- td.innerHTML = '';
264
- td.className = 'right-calendar-day-blank';
265
- });
266
-
267
- var options = this.options;
268
-
269
- for (var i=1; i <= days_number; i++) {
270
- date.setDate(i);
271
- var day_num = date.getDay();
272
-
273
- if (this.options.firstDay) {
274
- day_num = day_num ? day_num-1 : 6;
275
- }
276
-
277
- cells[day_num].innerHTML = ''+i;
278
- cells[day_num].className = cur_day == (date.getTime() / 86400000).ceil() ? 'right-calendar-day-selected' : '';
279
-
280
- if ((options.minDate && options.minDate > date) || (options.maxDate && options.maxDate < date))
281
- cells[day_num].className = 'right-calendar-day-disabled';
282
-
283
- cells[day_num].date = new Date(date);
284
-
285
- if (day_num == 6) {
286
- cells = rows.shift().select('td');
287
- }
288
- }
289
-
290
- var caption = (options.listYears ? options.i18n.monthNamesShort[date.getMonth()] + ',' :
291
- options.i18n.monthNames[date.getMonth()])+' '+date.getFullYear();
292
-
293
- element.first('div.right-calendar-month-caption').update(caption);
294
- },
295
-
296
- updateNextPrevMonthButtons: function(date, monthes_num) {
297
- var options = this.options;
298
-
299
- if (options.minDate) {
300
- var beginning = new Date(date.getFullYear(),0,1,0,0,0);
301
- var min_date = new Date(options.minDate.getFullYear(),0,1,0,0,0);
302
-
303
- this.hasPrevYear = beginning > min_date;
304
-
305
- beginning.setMonth(date.getMonth() - (monthes_num - monthes_num/2).ceil());
306
- min_date.setMonth(options.minDate.getMonth());
307
-
308
- this.hasPrevMonth = beginning >= min_date;
309
- } else {
310
- this.hasPrevMonth = this.hasPrevYear = true;
311
- }
312
-
313
- if (options.maxDate) {
314
- var end = new Date(date);
315
- var max_date = new Date(options.maxDate);
316
- [end, max_date].each(function(date) {
317
- date.setDate(32);
318
- date.setMonth(date.getMonth() - 1);
319
- date.setDate(32 - date.getDate());
320
- date.setHours(0);
321
- date.setMinutes(0);
322
- date.setSeconds(0);
323
- date.setMilliseconds(0);
324
- });
325
-
326
- this.hasNextMonth = end < max_date;
327
-
328
- // checking the next year
329
- [end, max_date].each('setMonth', 0);
330
- this.hasNextYear = end < max_date;
331
- } else {
332
- this.hasNextMonth = this.hasNextYear = true;
333
- }
334
-
335
- this.nextButton[this.hasNextMonth ? 'removeClass':'addClass']('right-ui-button-disabled');
336
- this.prevButton[this.hasPrevMonth ? 'removeClass':'addClass']('right-ui-button-disabled');
337
-
338
- if (this.nextYearButton) {
339
- this.nextYearButton[this.hasNextYear ? 'removeClass':'addClass']('right-ui-button-disabled');
340
- this.prevYearButton[this.hasPrevYear ? 'removeClass':'addClass']('right-ui-button-disabled');
341
- }
342
- },
343
-
344
- // builds the calendar
345
- build: function() {
346
- this.buildSwaps();
347
-
348
- // building the calendars greed
349
- var greed = tbody = $E('table', {'class': 'right-calendar-greed'}).insertTo(this.element);
350
- var options = this.options;
351
- if (Browser.OLD) tbody = $E('tbody').insertTo(greed);
352
-
353
- for (var y=0; y < options.numberOfMonths[1]; y++) {
354
- var row = $E('tr').insertTo(tbody);
355
- for (var x=0; x < options.numberOfMonths[0]; x++) {
356
- $E('td').insertTo(row).insert(this.buildMonth());
357
- }
358
- }
359
-
360
- if (options.showTime) this.buildTime();
361
- this.buildButtons();
362
-
363
- return this;
364
- },
365
-
366
- // builds the monthes swapping buttons
367
- buildSwaps: function() {
368
- var i18n = this.options.i18n;
369
-
370
- this.prevButton = $E('div', {'class': 'right-ui-button right-calendar-prev-button',
371
- html: '&lsaquo;', title: i18n.Prev}).insertTo(this.element);
372
- this.nextButton = $E('div', {'class': 'right-ui-button right-calendar-next-button',
373
- html: '&rsaquo;', title: i18n.Next}).insertTo(this.element);
374
-
375
- if (this.options.listYears) {
376
- this.prevYearButton = $E('div', {'class': 'right-ui-button right-calendar-prev-year-button',
377
- html: '&laquo;', title: i18n.PrevYear}).insertTo(this.prevButton, 'after');
378
- this.nextYearButton = $E('div', {'class': 'right-ui-button right-calendar-next-year-button',
379
- html: '&raquo;', title: i18n.NextYear}).insertTo(this.nextButton, 'before');
380
- }
381
- },
382
-
383
- // builds a month block
384
- buildMonth: function() {
385
- return $E('div', {'class': 'right-calendar-month'}).insert(
386
- '<div class="right-calendar-month-caption"></div>'+
387
- '<table><thead><tr>'+
388
- this.options.dayNames.map(function(name) {return '<th>'+name+'</th>';}).join('')+
389
- '</tr></thead><tbody>'+
390
- '123456'.split('').map(function() {return '<tr><td><td><td><td><td><td><td></tr>'}).join('')+
391
- '</tbody></table>'
392
- );
393
- },
394
-
395
- // builds the time selection block
396
- buildTime: function() {
397
- var options = this.options;
398
- var time_picker = $E('div', {'class': 'right-calendar-time', html: ':'}).insertTo(this.element);
399
-
400
- this.hours = $E('select').insertTo(time_picker, 'top');
401
- this.minutes = $E('select').insertTo(time_picker);
402
-
403
- var minutes_threshold = options.timePeriod < 60 ? options.timePeriod : 60;
404
- var hours_threshold = options.timePeriod < 60 ? 1 : (options.timePeriod / 60).ceil();
405
-
406
- (60).times(function(i) {
407
- var caption = (i < 10 ? '0' : '') + i;
408
-
409
- if (i < 24 && i % hours_threshold == 0) {
410
- if (options.twentyFourHour)
411
- this.hours.insert($E('option', {value: i, html: caption}));
412
- else if (i < 12) {
413
- this.hours.insert($E('option', {value: i, html: i == 0 ? 12 : i}));
414
- }
415
- }
416
-
417
- if (i % minutes_threshold == 0) {
418
- this.minutes.insert($E('option', {value: i, html: caption}));
419
- }
420
- }, this);
421
-
422
- // adding the meridian picker if it's a 12 am|pm picker
423
- if (!options.twentyFourHour) {
424
- this.meridian = $E('select').insertTo(time_picker);
425
-
426
- (options.format.includes(/%P/) ? ['am', 'pm'] : ['AM', 'PM']).each(function(value) {
427
- this.meridian.insert($E('option', {value: value.toLowerCase(), html: value}));
428
- }, this);
429
- }
430
- },
431
-
432
- // builds the bottom buttons block
433
- buildButtons: function() {
434
- if (!this.options.showButtons) return;
435
-
436
- this.nowButton = $E('div', {'class': 'right-ui-button right-calendar-now-button', html: this.options.i18n.Now});
437
- this.doneButton = $E('div', {'class': 'right-ui-button right-calendar-done-button', html: this.options.i18n.Done});
438
-
439
- $E('div', {'class': 'right-ui-buttons right-calendar-buttons'})
440
- .insert([this.doneButton, this.nowButton]).insertTo(this.element);
441
- }
442
-
443
- });
444
-
445
- /**
446
- * This module handles the events connection
447
- *
448
- * Copyright (C) 2009-2010 Nikolay V. Nemshilov
449
- */
450
- Calendar.include({
451
- /**
452
- * Initiates the 'select' event on the object
453
- *
454
- * @param Date date
455
- * @return Calendar this
456
- */
457
- select: function(date) {
458
- this.fire('select', this.date = date);
459
-
460
- if (this.options.hideOnPick)
461
- this.done();
462
-
463
- return this;
464
- },
465
-
466
- /**
467
- * Covers the 'done' event fire
468
- *
469
- * @return Calendar this
470
- */
471
- done: function() {
472
- if (!this.inlined())
473
- this.hide();
474
- return this.fire('done', this.date);
475
- },
476
-
477
- nextDay: function() {
478
- return this.changeDate({'Date': 1});
479
- },
480
-
481
- prevDay: function() {
482
- return this.changeDate({'Date': -1});
483
- },
484
-
485
- nextWeek: function() {
486
- return this.changeDate({'Date': 7});
487
- },
488
-
489
- prevWeek: function() {
490
- return this.changeDate({'Date': -7});
491
- },
492
-
493
- nextMonth: function() {
494
- return this.changeDate({Month: 1});
495
- },
496
-
497
- prevMonth: function() {
498
- return this.changeDate({Month: -1});
499
- },
500
-
501
- nextYear: function() {
502
- return this.changeDate({FullYear: 1});
503
- },
504
-
505
- prevYear: function() {
506
- return this.changeDate({FullYear: -1});
507
- },
508
-
509
- // protected
510
-
511
- // changes the current date according to the hash
512
- changeDate: function(hash) {
513
- var date = new Date(this.date), options = this.options;
514
-
515
- for (var key in hash) {
516
- date['set'+key](date['get'+key]() + hash[key]);
517
- }
518
-
519
- // checking the date range constrains
520
- if (options.minDate && options.minDate > date) date = new Date(options.minDate);
521
- if (options.maxDate && options.maxDate < date) {
522
- date = new Date(options.maxDate);
523
- date.setDate(date.getDate() - 1);
524
- }
525
- return this.update(this.date = date);
526
- },
527
-
528
- connectEvents: function() {
529
- // connecting the monthes swapping
530
- this.prevButton.onClick(this.prevMonth.bind(this));
531
- this.nextButton.onClick(this.nextMonth.bind(this));
532
- if (this.nextYearButton) {
533
- this.prevYearButton.onClick(this.prevYear.bind(this));
534
- this.nextYearButton.onClick(this.nextYear.bind(this));
535
- }
536
-
537
- // connecting the calendar day-cells
538
- this.element.select('div.right-calendar-month table tbody td').each(function(cell) {
539
- cell.onClick(function() {
540
- if (cell.innerHTML != '' && !cell.hasClass('right-calendar-day-disabled')) {
541
- var prev = this.element.first('.right-calendar-day-selected');
542
- if (prev) prev.removeClass('right-calendar-day-selected');
543
- cell.addClass('right-calendar-day-selected');
544
- this.setTime(cell.date);
545
- }
546
- }.bind(this));
547
- }, this);
548
-
549
- // connecting the time picker events
550
- if (this.hours) {
551
- this.hours.onChange(this.setTime.bind(this));
552
- this.minutes.onChange(this.setTime.bind(this));
553
- if (!this.options.twentyFourHour) {
554
- this.meridian.onChange(this.setTime.bind(this));
555
- }
556
- }
557
-
558
- // connecting the bottom buttons
559
- if (this.nowButton) {
560
- this.nowButton.onClick(this.setDate.bind(this, new Date()));
561
- this.doneButton.onClick(this.done.bind(this));
562
- }
563
-
564
- // blocking all the events from the element
565
- this.element.onMousedown(function(e) { e.stopPropagation(); })
566
- .onClick(function(event) {
567
- event.stop();
568
- if (this.timer) {
569
- this.timer.cancel();
570
- this.timer = null;
571
- }
572
- }.bind(this));
573
-
574
- return this;
575
- },
576
-
577
- // sets the date without nucking the time
578
- setTime: function(date) {
579
- // from clicking a day in a month table
580
- if (date instanceof Date) {
581
- this.date.setYear(date.getFullYear());
582
- this.date.setMonth(date.getMonth());
583
- this.date.setDate(date.getDate());
584
- }
585
-
586
- if (this.hours) {
587
- this.date.setHours(this.hours.value.toInt() + (!this.options.twentyFourHour && this.meridian.value == 'pm' ? 12 : 0));
588
- this.date.setMinutes(this.minutes.value);
589
- }
590
-
591
- return this.select(this.date);
592
- }
593
-
594
- });
595
-
596
- /**
597
- * This module handles the calendar assignment to an input field
598
- *
599
- * Copyright (C) 2009-2010 Nikolay V. Nemshilov
600
- */
601
- Calendar.include({
602
- /**
603
- * Assigns the calendar to serve the given input element
604
- *
605
- * If no trigger element specified, then the calendar will
606
- * appear and disappear with the element haveing its focus
607
- *
608
- * If a trigger element is specified, then the calendar will
609
- * appear/disappear only by clicking on the trigger element
610
- *
611
- * @param Element input field
612
- * @param Element optional trigger
613
- * @return Calendar this
614
- */
615
- assignTo: function(input, trigger) {
616
- var input = $(input), trigger = $(trigger);
617
-
618
- if (trigger) {
619
- trigger.onClick(function(e) {
620
- e.stop();
621
- this.showAt(input.focus());
622
- }.bind(this));
623
- } else {
624
- input.on({
625
- focus: this.showAt.bind(this, input),
626
-
627
- click: function(e) {
628
- e.stop();
629
- if (this.element.hidden())
630
- this.showAt(input);
631
- }.bind(this),
632
-
633
- keyDown: function(e) {
634
- if (e.keyCode == 9 && this.element.visible())
635
- this.hide();
636
- }.bind(this)
637
- });
638
- }
639
-
640
- return this;
641
- },
642
-
643
- /**
644
- * Shows the calendar at the given element left-bottom corner
645
- *
646
- * @param Element element or String element id
647
- * @return Calendar this
648
- */
649
- showAt: function(element) {
650
- var element = $(element), dims = element.dimensions();
651
- this.setDate(this.parse(element.value));
652
-
653
- this.element.setStyle({
654
- position: 'absolute',
655
- margin: '0',
656
- left: (dims.left)+'px',
657
- top: (dims.top + dims.height)+'px'
658
- }).insertTo(document.body);
659
-
660
- this.stopObserving('select').stopObserving('done');
661
- this.on(this.doneButton ? 'done' : 'select', function() {
662
- element.value = this.format();
663
- }.bind(this));
664
-
665
- return this.hideOthers().show();
666
- },
667
-
668
- /**
669
- * Toggles the calendar state at the associated element position
670
- *
671
- * @param Element input
672
- * @return Calendar this
673
- */
674
- toggleAt: function(input) {
675
- if (this.element.parentNode && this.element.visible()) {
676
- this.hide();
677
- } else {
678
- this.showAt(input);
679
- }
680
- return this;
681
- },
682
-
683
- // protected
684
-
685
- // hides all the other calendars on the page
686
- hideOthers: function() {
687
- $$('div.right-calendar').each(function(element) {
688
- if (!element.hasClass('right-calendar-inline')) {
689
- if (element != this.element) {
690
- element.hide();
691
- }
692
- }
693
- });
694
-
695
- return this;
696
- }
697
- });
698
-
699
- /**
700
- * This module handles the dates parsing/formatting processes
701
- *
702
- * To format dates and times this scripts use the GNU (C/Python/Ruby) strftime
703
- * function formatting principles
704
- *
705
- * %a - The abbreviated weekday name (``Sun'')
706
- * %A - The full weekday name (``Sunday'')
707
- * %b - The abbreviated month name (``Jan'')
708
- * %B - The full month name (``January'')
709
- * %d - Day of the month (01..31)
710
- * %e - Day of the month without leading zero (1..31)
711
- * %m - Month of the year (01..12)
712
- * %y - Year without a century (00..99)
713
- * %Y - Year with century
714
- * %H - Hour of the day, 24-hour clock (00..23)
715
- * %k - Hour of the day, 24-hour clock without leading zero (0..23)
716
- * %I - Hour of the day, 12-hour clock (01..12)
717
- * %l - Hour of the day, 12-hour clock without leading zer (0..12)
718
- * %p - Meridian indicator (``AM'' or ``PM'')
719
- * %P - Meridian indicator (``pm'' or ``pm'')
720
- * %M - Minute of the hour (00..59)
721
- * %S - Second of the minute (00..60)
722
- * %% - Literal ``%'' character
723
- *
724
- * Copyright (C) 2009-2010 Nikolay V. Nemshilov
725
- */
726
- Calendar.include({
727
-
728
- /**
729
- * Parses out the given string based on the current date formatting
730
- *
731
- * @param String string date
732
- * @return Date parsed date or null if it wasn't parsed
733
- */
734
- parse: function(string) {
735
- var date;
736
-
737
- if (isString(string) && string) {
738
- var tpl = RegExp.escape(this.options.format);
739
- var holders = tpl.match(/%[a-z]/ig).map('match', /[a-z]$/i).map('first').without('%');
740
- var re = new RegExp('^'+tpl.replace(/%p/i, '(pm|PM|am|AM)').replace(/(%[a-z])/ig, '(.+?)')+'$');
741
-
742
- var match = string.trim().match(re);
743
-
744
- if (match) {
745
- match.shift();
746
-
747
- var year = null, month = null, date = null, hour = null, minute = null, second = null, meridian;
748
-
749
- while (match.length) {
750
- var value = match.shift();
751
- var key = holders.shift();
752
-
753
- if (key.toLowerCase() == 'b') {
754
- month = this.options.i18n[key=='b' ? 'monthNamesShort' : 'monthNames'].indexOf(value);
755
- } else if (key.toLowerCase() == 'p') {
756
- meridian = value.toLowerCase();
757
- } else {
758
- value = value.toInt();
759
- switch(key) {
760
- case 'd':
761
- case 'e': date = value; break;
762
- case 'm': month = value-1; break;
763
- case 'y':
764
- case 'Y': year = value; break;
765
- case 'H':
766
- case 'k':
767
- case 'I':
768
- case 'l': hour = value; break;
769
- case 'M': minute = value; break;
770
- case 'S': second = value; break;
771
- }
772
- }
773
- }
774
-
775
- // converting 1..12am|pm into 0..23 hours marker
776
- if (meridian) {
777
- hour = hour == 12 ? 0 : hour;
778
- hour = (meridian == 'pm' ? hour + 12 : hour);
779
- }
780
-
781
- date = new Date(year, month, date, hour, minute, second);
782
- }
783
- } else if (string instanceof Date || Date.parse(string)) {
784
- date = new Date(string);
785
- }
786
-
787
- return (!date || isNaN(date.getTime())) ? new Date : date;
788
- },
789
-
790
- /**
791
- * Formats the current date into a string depend on the current or given format
792
- *
793
- * @param String optional format
794
- * @return String formatted data
795
- */
796
- format: function(format) {
797
- var i18n = this.options.i18n;
798
- var day = this.date.getDay();
799
- var month = this.date.getMonth();
800
- var date = this.date.getDate();
801
- var year = this.date.getFullYear();
802
- var hour = this.date.getHours();
803
- var minute = this.date.getMinutes();
804
- var second = this.date.getSeconds();
805
-
806
- var hour_ampm = (hour == 0 ? 12 : hour < 13 ? hour : hour - 12);
807
-
808
- var values = {
809
- a: i18n.dayNamesShort[day],
810
- A: i18n.dayNames[day],
811
- b: i18n.monthNamesShort[month],
812
- B: i18n.monthNames[month],
813
- d: (date < 10 ? '0' : '') + date,
814
- e: ''+date,
815
- m: (month < 9 ? '0' : '') + (month+1),
816
- y: (''+year).substring(2,4),
817
- Y: ''+year,
818
- H: (hour < 10 ? '0' : '')+ hour,
819
- k: '' + hour,
820
- I: (hour > 0 && (hour < 10 || (hour > 12 && hour < 22)) ? '0' : '') + hour_ampm,
821
- l: '' + hour_ampm,
822
- p: hour < 12 ? 'AM' : 'PM',
823
- P: hour < 12 ? 'am' : 'pm',
824
- M: (minute < 10 ? '0':'')+minute,
825
- S: (second < 10 ? '0':'')+second,
826
- '%': '%'
827
- };
828
-
829
- var result = format || this.options.format;
830
- for (var key in values) {
831
- result = result.replace('%'+key, values[key]);
832
- }
833
-
834
- return result;
835
- }
836
- });
837
-
838
- /**
839
- * Calendar fields autodiscovery via the rel="calendar" attribute
840
- *
841
- * Copyright (C) 2009-2010 Nikolay V. Nemshilov
842
- */
843
-
844
-
845
- (function() {
846
- // shows a calendar by an event
847
- var show_calendar = function(event) {
848
- var calendar = Calendar.find(Event.ext(event));
849
-
850
- if (calendar && Calendar.current != calendar) {
851
- var input = event.target;
852
- var rule = Calendar.Options.cssRule.split('[').last();
853
- var key = rule.split('=').last().split(']').first();
854
- var rel_id_re = new RegExp(key+'\\[(.+?)\\]');
855
- var rel_id = input.get(rule.split('^=')[0]);
856
-
857
- if (rel_id && (rel_id = rel_id.match(rel_id_re))) {
858
- input = $(rel_id[1]);
859
- event.stop();
860
- }
861
-
862
- calendar.showAt(input);
863
- }
864
- };
865
-
866
- // on-click handler
867
- var on_mousedown = function(event) {
868
- show_calendar(event);
869
- };
870
-
871
- var on_click = function(event) {
872
- var target = event.target;
873
- if (Calendar.find(event)) {
874
- if (target.tagName == 'A')
875
- event.stop();
876
- } else if (Calendar.current) {
877
- if (![target].concat(target.parents()).first('hasClass', 'right-calendar')) {
878
- Calendar.current.hide();
879
- }
880
- }
881
- };
882
-
883
- // on-focus handler
884
- var on_focus = function(event) {
885
- show_calendar(event);
886
- };
887
-
888
- // on-blur handler
889
- var on_blur = function(event) {
890
- var calendar = Calendar.find(Event.ext(event));
891
-
892
- if (calendar) {
893
- // We delay hiding of the calendar block to give calendar's onclick handler
894
- // a chance to cancel hiding by killing the timer, as a workaround for IE issues
895
- calendar.timer = (
896
- function() { this.hide(); }.bind(calendar)
897
- ).delay(200);
898
- }
899
- };
900
-
901
- var on_keydown = function(event) {
902
- if (Calendar.current) {
903
- var name;
904
-
905
- switch(event.keyCode) {
906
- case 27: name = 'hide'; break;
907
- case 37: name = 'prevDay'; break;
908
- case 39: name = 'nextDay'; break;
909
- case 38: name = 'prevWeek'; break;
910
- case 40: name = 'nextWeek'; break;
911
- case 34: name = 'nextMonth'; break;
912
- case 33: name = 'prevMonth'; break;
913
- case 13:
914
- Calendar.current.select(Calendar.current.date);
915
- name = 'done';
916
- break;
917
- }
918
-
919
- if (name) {
920
- Calendar.current[name]();
921
- event.stop();
922
- }
923
- }
924
- };
925
-
926
-
927
- document.on({
928
- mousedown: on_mousedown,
929
- click: on_click,
930
- keydown: on_keydown
931
- });
932
-
933
- // the focus and blur events need some extra care
934
- if (Browser.IE) {
935
- // IE version
936
- document.attachEvent('onfocusin', on_focus);
937
- document.attachEvent('onfocusout', on_blur);
938
- } else {
939
- // W3C version
940
- document.addEventListener('focus', on_focus, true);
941
- document.addEventListener('blur', on_blur, true);
942
- }
943
- })();
944
-
945
-
946
- document.write("<style type=\"text/css\">div.right-calendar,div.right-calendar table,div.right-calendar table tr,div.right-calendar table th,div.right-calendar table td,div.right-calendar table tbody,div.right-calendar table thead{background:none;border:none;width:auto;height:auto;margin:0;padding:0}*.right-ui-button{display:inline-block;*display:inline;*zoom:1;height:1em;line-height:1em;padding:.2em .5em;text-align:center;border:1px solid #CCC;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em;cursor:pointer;color:#555;background-color:#FFF}*.right-ui-button:hover{color:#222;border-color:#999;background-color:#CCC}*.right-ui-button-disabled,*.right-ui-button-disabled:hover{color:#888;background:#EEE;border-color:#CCC;cursor:default}*.right-ui-buttons{margin-top:.5em}div.right-calendar{position:absolute;height:auto;border:1px solid #BBB;position:relative;padding:.5em;border-radius:.3em;-moz-border-radius:.3em;-webkit-border-radius:.3em;cursor:default;background-color:#EEE;-moz-box-shadow:.2em .4em .8em #666;-webkit-box-shadow:.2em .4em .8em #666}div.right-calendar-inline{position:relative;display:inline-block;vertical-align:top;*display:inline;*zoom:1;-moz-box-shadow:none;-webkit-box-shadow:none}div.right-calendar-prev-button,div.right-calendar-next-button,div.right-calendar-prev-year-button,div.right-calendar-next-year-button{position:absolute;float:left;width:1em;padding:.15em .4em}div.right-calendar-next-button{right:.5em}div.right-calendar-prev-year-button{left:2.55em}div.right-calendar-next-year-button{right:2.55em}div.right-calendar-month-caption{text-align:center;height:1.2em;line-height:1.2em}table.right-calendar-greed{border-spacing:0px}table.right-calendar-greed td{vertical-align:top;padding-right:.4em}table.right-calendar-greed>tbody>td:last-child{padding:0}div.right-calendar-month table{margin-top:.2em;border-spacing:1px;border-collapse:separate}div.right-calendar-month table th{color:#777;text-align:center}div.right-calendar-month table td{text-align:right;padding:.1em .3em;background-color:#FFF;border:1px solid #CCC;cursor:pointer;color:#555;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em}div.right-calendar-month table td:hover{background-color:#CCC;border-color:#AAA;color:#000}div.right-calendar-month table td.right-calendar-day-blank{background:transparent;cursor:default;border:none}div.right-calendar-month table td.right-calendar-day-selected{background-color:#BBB;border-color:#AAA;color:#222;font-weight:bold;padding:.1em .2em}div.right-calendar-month table td.right-calendar-day-disabled{color:#888;background:#EEE;border-color:#CCC;cursor:default}div.right-calendar-time{border-top:1px solid #ccc;margin-top:.3em;padding-top:.5em;text-align:center}div.right-calendar-time select{margin:0 .4em}div.right-calendar-buttons div.right-ui-button{width:3.2em}div.right-calendar-done-button{position:absolute;right:.5em}</style>");