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