/* RSence * Copyright 2009 Riassence Inc. * http://riassence.com/ * * You should have received a copy of the GNU General Public License along * with this software package. If not, contact licensing@riassence.com */ /*** = Description ** Use HCalendar to display a month calendar that displays days as columns ** and weeks as rows. Its value is a date/time number specified in seconds ** since or before epoch (1970-01-01 00:00:00 UTC). ***/ var//RSence.DateTime HCalendar = HControl.extend({ componentName: 'calendar', weekdaysLocalized: function(){ var _localeStrings = HLocale.dateTime.strings, _outputArray = COMM.Values.clone( _localeStrings.weekDaysShort ); _outputArray.push( _outputArray.shift() ); _outputArray.unshift( _localeStrings.weekShort ); return _outputArray; },//['Wk','Mon','Tue','Wed','Thu','Fri','Sat','Sun'], defaultEvents: { mouseWheel: true, click: true }, /** = Description * Calls HCalendar#nextMonth or HCalendar#prevMonth based on delta * of mouseWheel. * **/ mouseWheel: function(_delta){ if ( _delta < 0 ) { this.nextMonth(); } else { this.prevMonth(); } }, /** = Description * Simple clickthrough **/ click: function(){ return false; }, /** = Description * Refreshes weekdays. * **/ refreshLabel: function(){ if(!this['markupElemIds']){ return; } var _weekdays_localized = this.weekdaysLocalized(), _availWidth = this.rect.width-2, _weekdays_width = Math.floor(_availWidth/8), _leftPlus = (_availWidth % 8)-1, _weekdays_html = [], i = 0, _weekdays_html_pre = ['
'], _weekdays_html_suf = '
'; for(;i<_weekdays_localized.length;i++){ _weekdays_html.push([ _weekdays_html_pre.join(i*_weekdays_width+_leftPlus), _weekdays_localized[i], _weekdays_html_suf ].join('') ); } ELEM.setHTML(this.markupElemIds.label, _weekdays_html.join('')); }, /** = Description * Checks the date range for the month which the date given as input belongs. * * = Parameters * +_date+:: A Date instance to check date range from * * = Returns * Array of [0] first week's date and [1] last week's date. * **/ calendarDateRange: function(_date){ var _date_begin = this.firstDateOfMonth(_date), _date_end = this.lastDateOfMonth(_date), _firstWeeksDate = this.firstDateOfWeek(_date_begin), _lastWeeksDate = this.lastDateOfWeek(_date_end), _week_begin = this.week(_firstWeeksDate), _week_end = this.week(_lastWeeksDate), _weeks = _week_end-_week_begin; if((_weeks===5) && (_firstWeeksDate.getDate() !== 1)){ _lastWeeksDate = new Date( _lastWeeksDate.getTime() + this.msWeek ); } else if((_weeks===5) && (_firstWeeksDate.getDate() === 1)){ _firstWeeksDate = new Date( _firstWeeksDate.getTime() - this.msWeek ); } else if(_weeks===4){ _firstWeeksDate = new Date( _firstWeeksDate.getTime() - this.msWeek ); _lastWeeksDate = new Date( _lastWeeksDate.getTime() + this.msWeek ); } return [ _firstWeeksDate, _lastWeeksDate ]; }, /** = Description * Refreshes the calendar. * **/ refreshValue: function(){ var _date = this.date(); this.drawCalendar(_date); }, /** = Description * Draws the next month on calendar. * **/ nextMonth: function(){ var _date = new Date( this.viewMonth[0], this.viewMonth[1]+1, 1 ); this.drawCalendar( new Date(_date.getTime() - this.tzMs(_date)) ); }, /** = Description * Draws the previous month on calendar. * **/ prevMonth: function(){ var _date = new Date( this.viewMonth[0], this.viewMonth[1]-1, 1 ); this.drawCalendar( new Date(_date.getTime() - this.tzMs(_date)) ); }, viewMonth: [1970,0], monthMenu: function(){ if(!HPopupMenu){ console.log('HPopupMenu not included; cannot continue'); return; } var _calendar = this, _menu = HMiniMenu.extend({ refreshValue: function(){ this.base(); if( this._killAfterRefresh ){ this._killAfterRefresh = false; var _menu = this; _calendar.setValue( _calendar.setMonth( this.value ) ); if( _calendar.month() !== this.value ){ _calendar.setValue( _calendar.setMday( 30 ) ); _calendar.setValue( _calendar.setMonth( this.value ) ); } if( _calendar.month() !== this.value ){ _calendar.setValue( _calendar.setMday( 29 ) ); _calendar.setValue( _calendar.setMonth( this.value ) ); } if( _calendar.month() !== this.value ){ _calendar.setValue( _calendar.setMday( 28 ) ); _calendar.setValue( _calendar.setMonth( this.value ) ); } COMM.Queue.push( function(){_menu.die();} ); } }, _killAfterRefresh: false, menuHide: function(){ this.base(); var _menu = this; _menu._killAfterRefresh = true; COMM.Queue.push( function(){_menu._killAfterRefresh && _menu.refreshValue();} ); return true; } }).nu( [24, 0, Math.round(this.rect.width*0.66)-24, 20 ], this, { value: this.month(), initialVisibility: true } ), _monthValues = [], i = 0, _monthNames = HLocale.dateTime.strings.monthsLong; for(;i<_monthNames.length;i++){ _monthValues.push( [ i, _monthNames[i] ] ); } _menu.setListItems( _monthValues ); }, yearMenu: function(){ var _calendar = this, _year = HNumericTextControl.extend({ refreshValue: function(){ this.base(); _calendar.setValue( _calendar.setYear( this.value ) ); }, textBlur: function(){ this.base(); COMM.Queue.push( function(){_year.die();} ); }, textEnter: function(){ this.base(); if( ( EVENT.status[ EVENT.keysDown ].indexOf( 13 ) !== -1 ) || ( EVENT.status[ EVENT.keysDown ].length === 0 ) ){ ELEM.get( this.markupElemIds.value ).blur(); } } }).nu( HRect.nu(this.rect.width/2,0,this.rect.width-32,20), this, { value: this.year(), minValue: -38399, maxValue: 38400, focusOnCreate: true, refreshOnInput: false } ); }, /** = Description * Draws the calendar with the date open given as input. * * = Parameters * +_date+:: The date on which calendar UI is opened at. * **/ drawCalendar: function(_date){ _date = (_date instanceof Date)?_date:this.date(); var _calendarDateRange = this.calendarDateRange(_date), _monthFirst = this.firstDateOfMonth(_date), _monthLast = this.lastDateOfMonth(_date), _firstDate = _calendarDateRange[0], _lastDate = _calendarDateRange[1], _availWidth = this.rect.width-2, _availHeight = this.rect.height-36, _leftPlus = (_availWidth%8)-2, _topPlus = _availHeight%6, _column_width = Math.floor(_availWidth/8), _row_height = Math.floor(_availHeight/6), _week_html_pre = ['
'], _week_html_suf = '
', _col_html_pre = [''], _col_html_suf = '', _col_week_pre = '
', _col_week_suf = '
', _month_html = [], _week_html, _col_html, _row = 0, _col, _colMs, _colSecs, _colDate, _monthYearHTML, _extraCssClass; for(; _row<6; _row++){ _week_html = []; for(_col = 0; _col<8; _col++){ _colDate = new Date(_firstDate.getTime()+((_row*this.msWeek)+((_col-1)*this.msDay))); _colMs = _colDate.getTime(); if(_col===0){ _col_html = [ _col_week_pre, this.week(_colDate), _col_week_suf ].join(''); } else { _colSecs = Math.round(_colMs/1000); if((this.value >= _colSecs) && (this.value < (_colSecs+86400))){ _extraCssClass = '_'+'sel'; } else{ _extraCssClass = (_colDate<_monthFirst || _colDate > _monthLast)?'_'+'no':'_'+'yes'; } _col_html = [ _col_html_pre[0], _colSecs, _col_html_pre[1], _extraCssClass, _col_html_pre[2], (_col*_column_width+_leftPlus), _col_html_pre[3], this.mday(_colDate), _col_html_suf ].join(''); } _week_html.push(_col_html); } _month_html.push([ _week_html_pre.join(_row*_row_height+_topPlus), _week_html.join(''), _week_html_suf ].join('') ); } ELEM.setHTML( this.markupElemIds.value, _month_html.join('') ); _monthYearHTML = [ '', this.monthName(_date), ' ', this.year(_date), '' ].join(''); ELEM.setHTML( this.markupElemIds.state, _monthYearHTML ); this.viewMonth = [_monthFirst.getUTCFullYear(),_monthFirst.getUTCMonth()]; } }); HCalendar.implement(HDateTime);