Sencha Touch 自定义Calendar
JS:
Ext.define('Ext.ux.CalendarView', { extend: 'Ext.Container', xtype: 'calendarView', config: { cls: 'calendarView', baseTpl: [ '<div class="time-title">', '<div class="changeMonth prevMonth"></div>', '<div class="time-month"><span>{[this.getTitle()]}</span></div>', '<div class="changeMonth nextMonth"></div>', '</div>', '<table class="month">', '<thead>', '<tr>', '<th>{[this.getWeekTitle(0)]}</td>', '<th>{[this.getWeekTitle(1)]}</td>', '<th>{[this.getWeekTitle(2)]}</td>', '<th>{[this.getWeekTitle(3)]}</td>', '<th>{[this.getWeekTitle(4)]}</td>', '<th>{[this.getWeekTitle(5)]}</td>', '<th>{[this.getWeekTitle(6)]}</td>', '</tr>', '</thead>', '<tbody>', '<tr class="time-block-row">', '<tpl for=".">', '<td class="time-block {[this.getClasses(values)]}" datetime="{[values.date ? values.date.toString() : null]}">', '{day}', '</td>', '<tpl if="this.isEndOfRow(xindex)">', '</tr>', '<tpl if="!this.isEndOfPeriod(xindex)">', '<tr>', '</tpl>', '</tpl>', '</tpl>', '</tr>', '</tbody>', '</table>' ] }, commonTemplateFunctions: { /** * Gets the classes that should be applied to the current day's cell * @method * @private * @param {Object} values * @return {String} */ getClasses: function(values){ var classes = []; if(!values.date){ classes.push('unselected'); } if(values.selected){ classes.push('selected'); } if(values.today){ classes.push('today'); } return classes.join(' '); }, getTitle: function(){ return Ext.Date.format(new Date(this.me._year, this.me._month), 'Y-m'); }, getWeekTitle: function(index){ return this.me.weekTitles[index]; }, /** * Returns true if the specific index is at the end of the row * Used to determine if a row terminating tag is needed * @method * @private * @param {Number} currentIndex * @return {Boolean} */ isEndOfRow: function(currentIndex){ return (currentIndex % 7) === 0 && (currentIndex > 0); }, isEndOfPeriod: function(currentIndex){ return currentIndex % this.me.periodRowDayCount === 0; } }, initialize: function(){ this.element.on({ tap: this.onTimeSlotTap, scope: this, delegate: 'td.time-block' }); this.element.on({ tap: this.changeMonth, scope: this, delegate: 'div.changeMonth' }); this.weekTitles = ['S','M','T','W','T','F','S']; Ext.apply(this.commonTemplateFunctions, {me: this}); this.setTpl(new Ext.XTemplate(this.getBaseTpl().join(''), this.commonTemplateFunctions)); this._date = this.getValue() || new Date(); this._year = this._date.getFullYear(); this._month = this._date.getMonth(); this.controlMonth(); this.callParent(); }, changeMonth: function(e, el){ if(e.getTarget('.prevMonth')){ this.prevMonth(); }else{ this.nextMonth(); } }, onTimeSlotTap: function(e,el){ if(!e.getTarget('.unselected')){ // don't do selection if the cell has 'unselectable' class var target = Ext.fly(e.getTarget()); //this.selectCell(target); var newDate = this.getCellDate(target); var previousValue = this._date; // don't fire the event if the values are the same if(newDate.getTime() !== previousValue.getTime()){ this.setValue(newDate); this.fireEvent('selectionchange', this, newDate, previousValue); } } }, controlMonth: function(){ var date = new Date(this._year, this._month), theDate; this._firstDayInMonth = date.getDay(); this._totalDays = Math.round((new Date(this._year, this._month + 1) - date) / (1000 * 3600 * 24)); this._totalTd = (this._firstDayInMonth + this._totalDays) > 35 ? 42 : 35, i = 0; this._monthDate = []; while(i < this._totalTd){ if(i < this._firstDayInMonth || i > (this._firstDayInMonth + this._totalDays - 1)){ this._monthDate.push({ selected: false, today: false, day: '', date: null }); }else{ theDate = new Date(this._year, this._month, (i - this._firstDayInMonth + 1)); this._monthDate.push({ selected: this.isSameDay(theDate, this._date), today: this.isSameDay(theDate, new Date()), day: i - this._firstDayInMonth + 1, date: theDate }); } i++; } this.setData(this._monthDate); }, /** * 判断是否是相同日期 * */ isSameDay: function(date1, date2){ if(!date1 || !date2){ return false; } return Ext.Date.clearTime(date1, true).getTime() === Ext.Date.clearTime(date2, true).getTime(); }, getCellDate: function(target){ return new Date(target.dom.getAttribute('datetime')); }, nextMonth: function(){ this._month++; if(this._month >= 12){ this._month = this._month - 12; this._year++; } this.controlMonth(); }, prevMonth: function(){ this._month--; if(this._month < 0){ this._month = 11; this._year--; } this.controlMonth(); }, setPage: function(year, month){ var date = new Date(year, month), day = date.getDay(); }, setValue: function(date){ this._date = date; this._year = date.getFullYear(); this._month = date.getMonth(); this.controlMonth(); }, getValue: function(){ return this._date ? new Date(this._date.getFullYear(), this._date.getMonth(), this._date.getDate()) : null; }, setWeekTitles: function(arr){ this.weekTitles = arr; } });
CSS:
.calendarView .time-title{ display: flex; display: -webkit-box; display: -ms-flexbox; } .calendarView .time-month{ -webkit-box-flex: 1; -ms-flex: 1 0 0px; flex: 1 0 0px; display: flex; display: -webkit-box; display: -ms-flexbox; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; color: rgb(43,125,181); } .calendarView .changeMonth{ width: 80px; height: 40px; background-size: 30px 30px; background-position: center center; background-repeat: no-repeat; } .calendarView .prevMonth{ background-image: url(../images/elevatoricon_last.png); } .calendarView .nextMonth{ background-image: url(../images/elevatoricon_next.png); }
.calendarView table.month{ width: 100%; } .calendarView table.month th{ text-align: center; height: 30px; background-color: rgb(225,225,225); } .calendarView table.month td{ text-align: center; height: 35px; } .calendarView table.month td.selected{ color: #ffffff; background: rgb(175,175,175); } .calendarView table.month td.today{ border: 1px solid rgb(43,125,181); }
效果图: