使用avalon MVVM框架编写日历控件
本教程将介绍avalon的高级特性
- date过滤器的使用, 这个与angular的date过滤器的使用方法差不多,{{xxx|date("yyyy MM d")}}
- $watch监听,相当于把监控属性变成一种事件,当它变化时,就执行它绑定的回调。vm.$watch("firstName", function(){alert("我是回调")})
- 不监听属性或方法的定义,就是$开头,或放在$skipArray数组中。
- if绑定,类似于knockout的if绑定,根据求值表达式的情况决定把当前元素插入DOM树。ms-if=expr
HTML结构
<div ms-controller="datepicker">
<div class="ui-datepicker">
<div class="ui-datepicker-header">
<a href="###" title="Prev" class="ui-datepicker-month ui-datepicker-prev" ms-click="prevMonth">
<
</a>
<a href="###"title="Next" class="ui-datepicker-month ui-datepicker-next" ms-click="nextMonth">
>
</a >
<div class="ui-datepicker-title" >
<select ms-each-month="$months" ms-if="changeMonth" ms-model="currentMonth" >
<option value="{{month}}" ms-selected="currentMonth === month">{{month+1}}月</option>
</select>
<select ms-each-year="candidateYears" ms-if="changeYear" ms-model="currentYear" >
<option value="{{year}}" ms-selected="currentYear === year">{{year}}年</option>
</select>
{{title}}
</div>
</div>
<table ms-click="select">
<thead>
<tr ms-each-date="$weeks">
<th>{{date}}</th>
</tr>
</thead>
<tbody ms-each-week="candidateWeeks">
<tr ms-each-day="week" >
<td><span ms-visible="day" ms-class-selected="isSelected" ms-class-disabled="day && day[3]" ms-class-today="isToday" >{{ day[2] }}</span></td>
</tr>
</tbody>
</table>
</div>
<p><input type="radio" ms-model="changeMonth" />可选择月份</br/>
<input type="radio" ms-model="changeYear" />可选择年份</p>
<div class="font">{{selectedDate | date("yyyy-MM-d")}}</div>
</div>
JS
avalon.ready(function() {
var model = avalon.define("datepicker", function(vm) {
//配置
vm.changeYear = false
vm.changeMonth = false
vm.minDate = new Date(2013, 4, 25)
//当前时间
vm.current = new Date;
vm.currentMonth = vm.current.getMonth();
vm.currentYear = vm.current.getFullYear();
vm.selectedDate = new Date;
//显示顶部的年份与月份
vm.title = {
get: function() {
var format = "";
if (!this.changeYear && this.changeMonth) {
format = "yyyy年";
} else if (this.changeYear && !this.changeMonth) {
format = "MMMM";
} else if (!this.changeYear && !this.changeMonth) {
format = "MMMM yyyy年";
}
return format && avalon.filters.date(this.current, format);
}
};
//星期显示
vm.$weeks = "日一二三四五六".split("");
//月份下拉菜单
vm.$months = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
//当月的日期
function getWeeks() {
var cur = vm.current;
var year = cur.getFullYear();
var month = cur.getMonth();
var date = cur.getDate()
cur.setMonth(month + 1);
cur.setDate(0);
var num = cur.getDate();
var dates = avalon.range(1, num + 1);
dates = dates.map(function(d) {
var timestamp = new Date(year, month + 1, d) - 0
var disabled = false;
if (vm.minDate) {
disabled = timestamp < vm.minDate - 0;
}
if (disabled && vm.maxDate) {
disabled = timestamp > vm.maxDate - 0;
}
return [ year, month, d, disabled];
});
cur.setMonth(month);
cur.setDate(1);
var before = cur.getDay();
var shim = new Array(before);//如果当月的第一天不是星期天,需要补空格
dates = shim.concat(dates);
cur.setDate(date);//还原
var ret = [];
while (dates.length) {//每行七个分组
ret.push(dates.splice(0, 7));
}
return ret;
}
vm.candidateWeeks = getWeeks();
//取得当年的前后20年
function getYears() {
var y = vm.currentYear;
return avalon.range(y - 10, y + 10);
}
vm.candidateYears = getYears();
//点击事件
vm.nextMonth = function() {
var date = vm.current;
var m = date.getMonth();
vm.$fire("currentMonth", m + 1)
};
//点击事件
vm.prevMonth = function() {
var date = vm.current;
var m = date.getMonth();
vm.$fire("currentMonth", m - 1);
};
//侦听
vm.$watch("currentMonth", function(month) {
var date = vm.current;
date.setMonth(month);
vm.currentMonth = month;
vm.candidateWeeks = getWeeks();
vm.title = date - 0;
});
vm.$watch("currentYear", function(year) {
var date = vm.current;
date.setFullYear(year);
vm.currentYear = year;
vm.$fire("currentMonth", date.getMonth());
});
//高亮当前选中的日期
vm.select = function(e) {
var el = e.target;
if (el.tagName === "SPAN" && el.parentNode.tagName === "TD" && !/disabled/.test(el.className)) {
vm.selected = el.innerHTML;
var d = el.$scope.day.slice(0, 3);
vm.selectedDate = new Date(d[0],d[1],d[2]);
}
};
vm.selected = "";
vm.isSelected = function() {
return this.innerHTML === vm.selected;
};
//高亮今天的日期
var today = new Date;
today = [ today.getFullYear(), today.getMonth(), today.getDate() ].join();
vm.isToday = function() {
var day = this.$scope && this.$scope.day;
return day && day.slice(0, 3).join() === today;
};
});
avalon.scan();
});
浙公网安备 33010602011771号