You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2965 lines
88 KiB
2965 lines
88 KiB
;(function(root, factory) {
|
|
if (typeof define === 'function' && define.amd) {
|
|
define([], factory);
|
|
} else if (typeof exports === 'object') {
|
|
module.exports = factory();
|
|
} else {
|
|
root.Calendar = factory();
|
|
}
|
|
}(this, function() {
|
|
"use strict";
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
|
|
/**
|
|
* Calendar 类
|
|
*/
|
|
var Calendar =
|
|
/*#__PURE__*/
|
|
function () {
|
|
/**
|
|
* 构造函数
|
|
* ========================================================================
|
|
* @constructor
|
|
* @param {Object} [options] - 日历控件的配置参数
|
|
* @param [options.parent] - 日历显示的位置(DOM 节点 ID)
|
|
* @param [options.time] - 日历初始化显示的时间
|
|
* @param [options.viewMode] - 日历的试图模式:0 - 日期试图(默认值)
|
|
* 1 - 月份试图
|
|
* 2 - 年代试图
|
|
* @param [options.pickMode] - 日历的日期选择模式: single - 单选模式(默认值)
|
|
* multiple - 多选模式
|
|
* range - 范围选择模式
|
|
* week - 星期选择模式
|
|
* @param [options.hasSwitcher] - 是否显示上下切换按钮(默认值:true)
|
|
* @param [options.hasFooter] - 是否显示日历页脚(默认值:true)
|
|
* @param [options.hasClock] - 是否显示当前时间(默认值:true)
|
|
* @param [options.onDatePick] - 选择日期后的自定义事件处理器
|
|
* @param [options.onMonthPick] - 选择月份后的自定义事件处理器
|
|
* @param [options.onYearPick] - 选择年份后的自定义事件处理器
|
|
* @param [options.onTodayPick] - 点击当前日期的自定义事件处理器
|
|
* @param [options.MONTHS] - 月份常量(格式:去年11/12月 + 今天月份 + 明年1/2月)
|
|
* @param [options.DAYS] - 星期常量(周日为一周的第一天,周六为一周的最后一天)
|
|
* @param [options.DATES] - 月份天数常量(2月为28天,闰年则 28 + 1)
|
|
* @param [options.STYLES] - 日历控件的样式常量
|
|
* @returns {Calendar}
|
|
*/
|
|
function Calendar(options) {
|
|
_classCallCheck(this, Calendar);
|
|
|
|
/**
|
|
* Calendar 控件的配置属性
|
|
* ========================================================================
|
|
*/
|
|
this.attributes = {
|
|
// 日历显示的位置(DOM 节点 ID)
|
|
parent: '',
|
|
// 日历初始化显示的时间
|
|
time: '',
|
|
// 日历的试图模式:
|
|
// 0 - 日期试图(默认值)
|
|
// 1 - 月份试图
|
|
// 2 - 年代试图
|
|
viewMode: 0,
|
|
// 日历的日期选择模式
|
|
// single - 单选模式(默认值)
|
|
// multiple - 多选模式
|
|
// range - 范围选择模式
|
|
// week - 星期选择模式
|
|
pickMode: 'single',
|
|
// 是否显示上下切换按钮(默认值:true)
|
|
hasSwitcher: true,
|
|
// 是否显示日历页脚(默认值:true)
|
|
hasFooter: true,
|
|
// 是否显示当前时间(默认值:true)
|
|
hasClock: true,
|
|
// 选择日期后的自定义事件处理器
|
|
// time - 选中的日期时间范围
|
|
// $el - 点击的 DOM 节点
|
|
// calendar - 日历控件的实例
|
|
// onDatePick: function (time, $el, calendar) {
|
|
// console.log('选择时间:' + time)
|
|
// console.log('选择的 DOM 节点:' + $el)
|
|
// console.log('日历实例:' + calendar)
|
|
// },
|
|
onDatePick: null,
|
|
// 选择月份后的自定义事件处理器
|
|
// time - 选中的日期时间
|
|
// $el - 点击的 DOM 节点
|
|
// calendar - 日历控件的实例
|
|
// onMonthPick: function (time, $el, calendar) {
|
|
// console.log('选择时间:', time)
|
|
// console.log('选择DOM:', $el)
|
|
// console.log('日历实例:', calendar)
|
|
// }
|
|
onMonthPick: null,
|
|
// 选择年份后的自定义事件处理器
|
|
// time - 选中的日期时间
|
|
// $el - 点击的 DOM 节点
|
|
// calendar - 日历控件的实例
|
|
// onYearPick: function (time, $el, calendar) {
|
|
// console.log('选择时间:', time)
|
|
// console.log('选择DOM:', $el)
|
|
// console.log('日历实例:', calendar)
|
|
// }
|
|
onYearPick: null,
|
|
// 点击当前日期的自定义事件处理器
|
|
// time - 选中的日期时间
|
|
// $el - 点击的 DOM 节点
|
|
// calendar - 日历控件的实例
|
|
// onTodayPick: function (time, $el, calendar) {
|
|
// console.log('选择时间:', time)
|
|
// console.log('选择的 DOM 节点:', $el)
|
|
// console.log('日历实例:', calendar)
|
|
// }
|
|
onTodayPick: null,
|
|
// 月份常量
|
|
MONTHS: [],
|
|
// 星期常量
|
|
DAYS: [],
|
|
// 月份天数常量
|
|
DATES: [],
|
|
// 日历控件的样式常量
|
|
STYLES: {}
|
|
/**
|
|
* Calendar 控件相关的 DOM 节点属性
|
|
* ========================================================================
|
|
*/
|
|
|
|
};
|
|
this.elements = {
|
|
// 显示日历控件的父节点
|
|
parent: null,
|
|
// 日历控件的根节点
|
|
wrap: null,
|
|
// 日历控件的头部节点
|
|
header: null,
|
|
// 日历控件的标题节点
|
|
title: null,
|
|
// 日历控件的切换器节点
|
|
switcher: null,
|
|
// 日历控件向上切换按钮节点
|
|
prev: null,
|
|
// 日历控件向下切换按钮节点
|
|
next: null,
|
|
// 日历控件的主体内容节点
|
|
body: null,
|
|
// 日历控件的星期栏节点
|
|
week: null,
|
|
// 日历控件的日期显示节点
|
|
dates: null,
|
|
// 日历控件的月份显示节点
|
|
months: null,
|
|
// 日历控件的年代显示节点
|
|
years: null,
|
|
// 日历控件的页脚节点
|
|
footer: null,
|
|
// 日历控件的当前日期显示节点
|
|
today: null,
|
|
// 日历控件的当前时间显示节点
|
|
time: null
|
|
/**
|
|
* Calendar 控件相关的数据属性
|
|
* ========================================================================
|
|
*/
|
|
|
|
};
|
|
this.data = {
|
|
// 日历可以显示的最小年份
|
|
minYear: 0,
|
|
// 日历可以显示的最大年份
|
|
maxYear: 0,
|
|
// 当前选中日期的年份
|
|
year: 0,
|
|
// 当前选中日期的月份
|
|
month: 0,
|
|
// 选中的日期信息
|
|
date: {
|
|
// 年份
|
|
year: 0,
|
|
// 月份
|
|
month: 0,
|
|
// 日期
|
|
date: 0,
|
|
// 星期几
|
|
day: 0,
|
|
// 日期的英文表示(格式:2019-6-2)
|
|
text: '',
|
|
// 日期的完整中文表示(格式:2019年6月2日 星期日)
|
|
fullText: ''
|
|
},
|
|
// 多选(multiple/range/week)模式下,选中的日期数据
|
|
picked: [] // 执行初始化操作
|
|
// 绘制界面
|
|
// 绑定事件处理器
|
|
|
|
};
|
|
this.initialize(options).render().addEventListeners();
|
|
return this;
|
|
}
|
|
/**
|
|
* 初始化方法
|
|
* ========================================================================
|
|
* 1. 初始化配置信息;
|
|
* 2. 初始化数据信息;
|
|
* 3. 初始化 DOM 信息(创建控件相关的 DOM 节点);
|
|
* ========================================================================
|
|
* @param {Object} options - 配置信息
|
|
* @see this.attributes
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
|
|
_createClass(Calendar, [{
|
|
key: "initialize",
|
|
value: function initialize(options) {
|
|
var year = Calendar.getYear().value;
|
|
var pickMode;
|
|
var time;
|
|
var month;
|
|
var monthText;
|
|
var dateRanges;
|
|
var startDate;
|
|
var endDate; // 初始化配置
|
|
|
|
this.set(Calendar.defaults).set(options);
|
|
time = this.get('time');
|
|
pickMode = this.get('pickMode');
|
|
month = Calendar.getMonth(time);
|
|
monthText = month.text; // 初始化数据
|
|
|
|
this.setYear(time).setMonth(time).setDate(time)._setYears(time); // 初始化(多选模式)选中的时间
|
|
|
|
|
|
switch (pickMode) {
|
|
case 'multiple':
|
|
this.data.picked.push(this.getDate().text);
|
|
break;
|
|
|
|
case 'range':
|
|
startDate = monthText + '-' + 1;
|
|
endDate = monthText + '-' + this.get('DATES')[month.value - 1]; // 默认选中整个月
|
|
|
|
this.data.picked = [startDate, endDate];
|
|
break;
|
|
|
|
case 'week':
|
|
dateRanges = Calendar.getWeekRanges(time);
|
|
startDate = dateRanges[0];
|
|
endDate = dateRanges[dateRanges.length - 1]; // 默认选中配置日期所在的那个星期
|
|
|
|
this.data.picked = [startDate, endDate];
|
|
break;
|
|
} // 设置日历控件可以显示的年份范围
|
|
|
|
|
|
this.data.minYear = year - 100;
|
|
this.data.maxYear = year + 100; // 创建控件相关的 DOM 节点
|
|
|
|
this._createElements();
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制日历控件界面的方法
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "render",
|
|
value: function render() {
|
|
var elements = this.getEls();
|
|
var $wrap = elements.wrap;
|
|
var $header = elements.header;
|
|
var $switcher = elements.switcher;
|
|
var $body = elements.body;
|
|
var $footer = elements.footer;
|
|
var $fragment = document.createDocumentFragment(); // 绘制头部
|
|
|
|
this._renderTitle();
|
|
|
|
$header.appendChild(elements.title); // 配置了显示上下切换按钮
|
|
|
|
if (this.get('hasSwitcher')) {
|
|
$switcher.appendChild(elements.prev);
|
|
$switcher.appendChild(elements.next);
|
|
$header.appendChild($switcher);
|
|
} // 绘制星期栏
|
|
|
|
|
|
this._renderDays();
|
|
|
|
$body.appendChild(elements.week); // 绘制日期
|
|
|
|
this._renderDates();
|
|
|
|
$body.appendChild(elements.dates); // 绘制月份
|
|
|
|
this._renderMonths();
|
|
|
|
$body.appendChild(elements.months); // 绘制年代
|
|
|
|
this._renderYears();
|
|
|
|
$body.appendChild(elements.years); // 配置了显示页脚
|
|
|
|
if (this.get('hasFooter')) {
|
|
// 绘制页脚
|
|
this._renderFooter();
|
|
|
|
$footer.appendChild(elements.today); // 配置了显示当前时间
|
|
|
|
if (this.get('hasClock')) {
|
|
$footer.appendChild(elements.time);
|
|
}
|
|
} // 将主体模块绘制出来
|
|
|
|
|
|
$wrap.appendChild($header);
|
|
$wrap.appendChild($body); // 配置了显示页脚
|
|
|
|
if (this.get('hasFooter')) {
|
|
$wrap.appendChild($footer);
|
|
} // 将控件零时保存在文档碎片中
|
|
|
|
|
|
$fragment.appendChild($wrap); // 一次性绘制出整个日历控件
|
|
|
|
elements.parent.appendChild($fragment);
|
|
return this;
|
|
}
|
|
/**
|
|
* 给日历控件相关的 DOM 节点绑定事件处理器
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "addEventListeners",
|
|
value: function addEventListeners() {
|
|
var DOT = '.';
|
|
var STYLES = this.get('STYLES');
|
|
var CLICK = 'click';
|
|
var selectorTitle = DOT + STYLES.TITLE;
|
|
var selectorPrev = DOT + STYLES.PREV;
|
|
var selectorNext = DOT + STYLES.NEXT;
|
|
var selectorDate = DOT + STYLES.DATE;
|
|
var selectorMonth = DOT + STYLES.MONTH;
|
|
var selectorYear = DOT + STYLES.YEAR;
|
|
var selectorToday = DOT + STYLES.TODAY;
|
|
var Delegate = Calendar.Delegate;
|
|
var $wrap = this.getEls().wrap; // 绑定点击标题的事件处理器
|
|
|
|
Delegate.on($wrap, selectorTitle, CLICK, this._titleClick, this);
|
|
|
|
if (this.get('hasSwitcher')) {
|
|
// 绑定点击向上按钮的事件处理器
|
|
Delegate.on($wrap, selectorPrev, CLICK, this._prevClick, this); // 绑定点击向下按钮的事件处理器
|
|
|
|
Delegate.on($wrap, selectorNext, CLICK, this._nextClick, this);
|
|
} // 绑定点击日期的事件处理器
|
|
|
|
|
|
Delegate.on($wrap, selectorDate, CLICK, this._dateClick, this); // 绑定点击月份的事件处理器
|
|
|
|
Delegate.on($wrap, selectorMonth, CLICK, this._monthClick, this); // 绑定点击年份的事件处理器
|
|
|
|
Delegate.on($wrap, selectorYear, CLICK, this._yearClick, this);
|
|
|
|
if (this.get('hasClock')) {
|
|
// 绑定点击今天的事件处理器
|
|
Delegate.on($wrap, selectorToday, CLICK, this._todayClick, this);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 重启日历控件
|
|
* ========================================================================
|
|
* 1. 销毁日历控件:
|
|
* 1.1 移除所有的绑定的事件处理器
|
|
* 1.2 隐藏控件
|
|
* 1.3 移除所有 DOM 节点
|
|
* 1.4 重置所有属性
|
|
* 2. 初始化控件
|
|
* 3. 绘制控件
|
|
* 4. 绑定事件处理起
|
|
* ========================================================================
|
|
* @param {Object} options - 配置信息
|
|
* @see this.attributes
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "reload",
|
|
value: function reload(options) {
|
|
this.destroy().initialize(options).render().addEventListeners();
|
|
return this;
|
|
}
|
|
/**
|
|
* 销毁日历控件
|
|
* ========================================================================
|
|
* 1 移除所有的绑定的事件处理器
|
|
* 2 隐藏控件
|
|
* 3 移除所有 DOM 节点
|
|
* 4 重置所有属性
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "destroy",
|
|
value: function destroy() {
|
|
this.removeEventListeners().hide().remove().reset();
|
|
return this;
|
|
}
|
|
/**
|
|
* 移除所有绑定的事件处理器
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "removeEventListeners",
|
|
value: function removeEventListeners() {
|
|
var CLICK = 'click';
|
|
var Delegate = Calendar.Delegate;
|
|
var $wrap = this.getEls().wrap;
|
|
Delegate.off($wrap, CLICK, this._titleClick);
|
|
|
|
if (this.get('hasSwitcher')) {
|
|
Delegate.off($wrap, CLICK, this._prevClick);
|
|
Delegate.off($wrap, CLICK, this._nextClick);
|
|
}
|
|
|
|
Delegate.off($wrap, CLICK, this._dateClick);
|
|
Delegate.off($wrap, CLICK, this._monthClick);
|
|
Delegate.off($wrap, CLICK, this._yearClick);
|
|
|
|
if (this.get('hasClock')) {
|
|
Delegate.off($wrap, CLICK, this._todayClick);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 移除所有 DOM 节点
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "remove",
|
|
value: function remove() {
|
|
var elements = this.getEls();
|
|
elements.parent.removeChild(elements.wrap);
|
|
return this;
|
|
}
|
|
/**
|
|
* 重置所有属性
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "reset",
|
|
value: function reset() {
|
|
this.attributes = {
|
|
parent: '',
|
|
time: '',
|
|
viewMode: 0,
|
|
pickMode: 'single',
|
|
hasSwitcher: true,
|
|
hasFooter: true,
|
|
hasClock: true,
|
|
MONTHS: [],
|
|
DAYS: [],
|
|
DATES: [],
|
|
STYLES: {}
|
|
};
|
|
this.elements = {
|
|
parent: null,
|
|
wrap: null,
|
|
header: null,
|
|
title: null,
|
|
switcher: null,
|
|
prev: null,
|
|
next: null,
|
|
body: null,
|
|
week: null,
|
|
dates: null,
|
|
months: null,
|
|
years: null,
|
|
footer: null,
|
|
today: null,
|
|
time: null,
|
|
year: null,
|
|
month: null,
|
|
date: null
|
|
};
|
|
this.data = {
|
|
minYear: 0,
|
|
maxYear: 0,
|
|
years: {
|
|
start: 0,
|
|
end: 0
|
|
},
|
|
year: 0,
|
|
month: 0,
|
|
date: {
|
|
year: 0,
|
|
month: 0,
|
|
date: 0,
|
|
day: 0,
|
|
text: '',
|
|
fullText: ''
|
|
},
|
|
picked: []
|
|
};
|
|
return this;
|
|
}
|
|
/**
|
|
* 获取配置信息
|
|
* ========================================================================
|
|
* @param {String} attr - 配置属性名称
|
|
* @returns {*} - 返回对应属性的值
|
|
*/
|
|
|
|
}, {
|
|
key: "get",
|
|
value: function get(attr) {
|
|
return this.attributes[attr];
|
|
}
|
|
/**
|
|
* 设置配置信息
|
|
* ========================================================================
|
|
* @param {Object} [options] - 配置信息对象
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "set",
|
|
value: function set() {
|
|
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
Object.assign(this.attributes, options);
|
|
return this;
|
|
}
|
|
/**
|
|
* 获取日历控件所有相关的 DOM 节点的对象
|
|
* ========================================================================
|
|
* @see Calendar.elements
|
|
* @returns {Object}
|
|
*/
|
|
|
|
}, {
|
|
key: "getEls",
|
|
value: function getEls() {
|
|
return this.elements;
|
|
}
|
|
/**
|
|
* 获取日历控件当前显示的年份信息
|
|
* ========================================================================
|
|
* @returns {Number} - 返回日历控件当前显示的年份
|
|
*/
|
|
|
|
}, {
|
|
key: "getYear",
|
|
value: function getYear() {
|
|
return this.data.year;
|
|
}
|
|
/**
|
|
* 设置日历控件当前的年份
|
|
* ========================================================================
|
|
* @param {String|Number} [time] - 表示年份的字符串或数字(默认值:今年)
|
|
* 字符串格式:'2019'、'2019-2' 或 '2019-2-2'
|
|
* 数字格式: 1546300800000
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "setYear",
|
|
value: function setYear(time) {
|
|
this.data.year = Calendar.getYear(time).value;
|
|
return this;
|
|
}
|
|
/**
|
|
* 获得日历控件当前显示的月份信息
|
|
* ========================================================================
|
|
* @returns {Number} - 返回日历控件当前显示的月份
|
|
*/
|
|
|
|
}, {
|
|
key: "getMonth",
|
|
value: function getMonth() {
|
|
return this.data.month;
|
|
}
|
|
/**
|
|
* 设置日历控件当前显示的月份
|
|
* ========================================================================
|
|
* @param {String|Number} [time] - 表示月份的字符串或数字(默认值:本月)
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "setMonth",
|
|
value: function setMonth(time) {
|
|
this.data.month = Calendar.getMonth(time).value;
|
|
return this;
|
|
}
|
|
/**
|
|
* 获取日历控件当前选中的日期
|
|
* ========================================================================
|
|
* @returns {Object} - 返回日历控件当前选中的日期
|
|
*/
|
|
|
|
}, {
|
|
key: "getDate",
|
|
value: function getDate() {
|
|
return this.data.date;
|
|
}
|
|
/**
|
|
* 设置日历控件当前选中的日期
|
|
* ========================================================================
|
|
* @param {String|Number} [time] - 表示日期的字符串或者数字(默认值:今天)
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "setDate",
|
|
value: function setDate(time) {
|
|
this.data.date = Calendar.getDate(time);
|
|
return this;
|
|
}
|
|
/**
|
|
* 获取日历控件当前显示的年份所在的年代信息
|
|
* ========================================================================
|
|
* @returns {Object} - 返回当前所在年代信息
|
|
*/
|
|
|
|
}, {
|
|
key: "getYears",
|
|
value: function getYears() {
|
|
return this.data.years;
|
|
}
|
|
/**
|
|
* 获取日历控件在多选(multiple/range/week)模式下选中的日期信息
|
|
* ========================================================================
|
|
* @returns {Array} - 返回选中的日期信息
|
|
*/
|
|
|
|
}, {
|
|
key: "getPicked",
|
|
value: function getPicked() {
|
|
return this.data.picked;
|
|
}
|
|
/**
|
|
* 根据试图显示模式
|
|
* ========================================================================
|
|
* 1. 切换日历控件的显示模式
|
|
* 2. 更新显示内容
|
|
* ========================================================================
|
|
* @param {Number} viewMode - 显示模式的值:
|
|
* 0 - 日期显示模式(默认值)
|
|
* 1 - 月份显示模式
|
|
* 2 - 年代显示模式
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "update",
|
|
value: function update() {
|
|
var viewMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
this.updateViewMode(viewMode).updateView();
|
|
return this;
|
|
}
|
|
/**
|
|
* 更新试图显示模式的配置信息
|
|
* ========================================================================
|
|
* @param {Number} viewMode - 显示模式的值(默认值:0)
|
|
* @see this.update
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "updateViewMode",
|
|
value: function updateViewMode() {
|
|
var viewMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
var mode = viewMode;
|
|
|
|
if (mode > 2) {
|
|
mode = 2;
|
|
} else {
|
|
if (mode < 0) {
|
|
mode = 0;
|
|
}
|
|
}
|
|
|
|
this.set({
|
|
viewMode: mode
|
|
});
|
|
return this;
|
|
}
|
|
/**
|
|
* 更新日历控件的显示内容
|
|
* ========================================================================
|
|
* 1. 更新标题内容
|
|
* 1.1 日期显示模式:显示年份和月份
|
|
* 1.2 月份显示模式:显示年份
|
|
* 1.3 年份显示模式:显示年代区间信息
|
|
* 2. 更细主体内容
|
|
* 2.1 日期显示模式:隐藏年份和月份的 DOM 节点,显示星期栏和日期信息
|
|
* 2.2 月份显示模式:隐藏年份、星期栏以及日期信息
|
|
* 2.3 年份显示模式:隐藏月份 DOM 节点、星期栏以及日期信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "updateView",
|
|
value: function updateView() {
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_HIDDEN = STYLES.HIDDEN;
|
|
var DOM = Calendar.DOM;
|
|
var addClass = DOM.addClass;
|
|
var removeClass = DOM.removeClass;
|
|
var elements = this.getEls();
|
|
var $week = elements.week;
|
|
var $dates = elements.dates;
|
|
var $months = elements.months;
|
|
var $years = elements.years;
|
|
|
|
this._renderTitle();
|
|
|
|
switch (this.get('viewMode')) {
|
|
// 日期显示模式
|
|
case 0:
|
|
addClass($months, CLS_HIDDEN);
|
|
addClass($years, CLS_HIDDEN);
|
|
removeClass($week, CLS_HIDDEN);
|
|
removeClass($dates, CLS_HIDDEN); // 重新绘制日期
|
|
|
|
this._repaintDates();
|
|
|
|
break;
|
|
// 月份显示模式
|
|
|
|
case 1:
|
|
addClass($week, CLS_HIDDEN);
|
|
addClass($dates, CLS_HIDDEN);
|
|
addClass($years, CLS_HIDDEN);
|
|
removeClass($months, CLS_HIDDEN); // 重新绘制月份
|
|
|
|
this._repaintMonths();
|
|
|
|
break;
|
|
// 年份显示模式
|
|
|
|
case 2:
|
|
addClass($week, CLS_HIDDEN);
|
|
addClass($dates, CLS_HIDDEN);
|
|
addClass($months, CLS_HIDDEN);
|
|
removeClass($years, CLS_HIDDEN); // 重新绘制年份
|
|
|
|
this._repaintYears();
|
|
|
|
break;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 向上翻页
|
|
* ========================================================================
|
|
* 1. 日期显示模式:向上翻页,显示上一个月份的日期信息
|
|
* 2. 月份显示模式:向上翻页,显示上一年的月份信息
|
|
* 3. 年份显示模式:向上翻页,显示上一个年代(10前)的年份信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "prev",
|
|
value: function prev() {
|
|
var years = this.getYears();
|
|
var startYear = years.start;
|
|
var year = this.getYear();
|
|
var month = this.getMonth();
|
|
var minYear = this.data.minYear;
|
|
var time; // 针对显示模式,处理相应的翻页逻辑
|
|
|
|
switch (this.get('viewMode')) {
|
|
// 日期显示模式
|
|
case 0:
|
|
// 切换月份
|
|
month -= 1; // 到了上一年,切换年份
|
|
|
|
if (month < 1) {
|
|
month = 12;
|
|
year -= 1; // 确保不小于最小可以显示的年份
|
|
|
|
if (year < minYear) {
|
|
year = minYear;
|
|
}
|
|
}
|
|
|
|
time = year + '-' + month + '-1';
|
|
this.setYear(time).setMonth(time);
|
|
break;
|
|
|
|
case 1:
|
|
// 切换年份
|
|
year -= 1;
|
|
|
|
if (year < minYear) {
|
|
year = minYear;
|
|
}
|
|
|
|
this.setYear(year + '-1-1');
|
|
break;
|
|
|
|
case 2:
|
|
// 切换年代
|
|
startYear -= 10;
|
|
|
|
if (startYear < minYear) {
|
|
startYear = minYear + 9;
|
|
}
|
|
|
|
this._setYears(startYear.toString());
|
|
|
|
break;
|
|
} // 更新显示内容
|
|
|
|
|
|
this.updateView();
|
|
return this;
|
|
}
|
|
/**
|
|
* 向下翻页
|
|
* ========================================================================
|
|
* 1. 日期显示模式:向下翻页,显示下一个月份的日期信息
|
|
* 2. 月份显示模式:向下翻页,显示下一年的月份信息
|
|
* 3. 年份显示模式:向下翻页,显示下一个年代(10后)的年份信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "next",
|
|
value: function next() {
|
|
var years = this.getYears();
|
|
var startYear = years.start;
|
|
var year = this.getYear();
|
|
var month = this.getMonth();
|
|
var maxYear = this.data.maxYear;
|
|
var time;
|
|
|
|
switch (this.get('viewMode')) {
|
|
case 0:
|
|
month += 1;
|
|
|
|
if (month > 12) {
|
|
month = 1;
|
|
year += 1;
|
|
|
|
if (year > maxYear) {
|
|
year = maxYear;
|
|
}
|
|
}
|
|
|
|
time = year + '-' + month + '-1';
|
|
this.setYear(time).setMonth(time);
|
|
break;
|
|
|
|
case 1:
|
|
year += 1;
|
|
|
|
if (year > maxYear) {
|
|
year = maxYear;
|
|
}
|
|
|
|
this.setYear(year + '-1-1');
|
|
break;
|
|
|
|
case 2:
|
|
startYear += 10;
|
|
|
|
if (startYear > maxYear) {
|
|
startYear = maxYear - 9;
|
|
}
|
|
|
|
this._setYears(startYear.toString());
|
|
|
|
break;
|
|
}
|
|
|
|
this.updateView();
|
|
return this;
|
|
}
|
|
/**
|
|
* 选择日期
|
|
* ========================================================================
|
|
* 1. 选择了选中状态的日期:
|
|
* 1.1 星期区间和单选模式:不做任何处理
|
|
* 1.2 多选模式:取消选中 DOM 节点的选中状态,并且将选中的日期在选中信息移除
|
|
* 1.3 日期区间选择模式下:取消之前选中区间的选中样式,将当前选中的日期 DOM 节点
|
|
* 设置为选中状态。移除之前选中日期信息,并将选中日期信息保存起来
|
|
* 2. 选择了未选中状态的日期:
|
|
* 2.1 单选模式:获取选中日期信息,并用这个信息替换之前选中的信息。移除之前选中样
|
|
* 式,并设置当前选中日期的选中样式
|
|
* 2.2 多选模式:获取选中的日期信息,然后保存到选中信息中,最后设置选中日期的样式
|
|
* 2.3 日期区间选择模式下:
|
|
* 2.4 星期区间选择模式:获取当前选择日期的星期区间信息,移除之前保存的区间信息将
|
|
* 新的区间信息保存起来,移除之前的区间选中样式,并设置当前选中区间的选中样式
|
|
* ========================================================================
|
|
* @param {HTMLElement} $date - 选中的日期 DOM 节点
|
|
* @returns {*}
|
|
*/
|
|
|
|
}, {
|
|
key: "pickDate",
|
|
value: function pickDate($date) {
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_PICKED = STYLES.PICKED;
|
|
var DOM = Calendar.DOM;
|
|
var hasClass = DOM.hasClass;
|
|
var addClass = DOM.addClass;
|
|
var removeClass = DOM.removeClass;
|
|
var isFunction = Calendar.Utils.isFunction;
|
|
var pickMode = this.get('pickMode');
|
|
var elements = this.getEls();
|
|
var time = $date.getAttribute('data-date');
|
|
var callback = this.get('onDatePick');
|
|
var $picked = null;
|
|
var pickedDates; // 选择了选中状态的日期
|
|
|
|
if (hasClass($date, CLS_PICKED)) {
|
|
switch (pickMode) {
|
|
// 单选/星期选择模式
|
|
case 'single':
|
|
case 'week':
|
|
return false;
|
|
// 多选模式
|
|
|
|
case 'multiple':
|
|
// 取消选中样式
|
|
removeClass($date, CLS_PICKED); // 移除选中的日期信息
|
|
|
|
this._removePicked(time); // 设置最后一个选中的时间为当前选中日期
|
|
|
|
|
|
pickedDates = this.getPicked();
|
|
this.setDate(pickedDates[pickedDates.length - 1]);
|
|
|
|
if (isFunction(callback)) {
|
|
callback(pickedDates, $date, this);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'range':
|
|
// 清除之前选中的数据
|
|
this.data.picked = []; // 将当前选中的日期数据保存起来
|
|
|
|
this.data.picked.push(time);
|
|
this.setDate(time); // 绘制选中样式
|
|
|
|
elements.date = $date;
|
|
|
|
this._updateDateRanges();
|
|
|
|
if (isFunction(callback)) {
|
|
callback(this.getPicked(), $date, this);
|
|
}
|
|
|
|
break;
|
|
}
|
|
} else {
|
|
this.setYear(time).setMonth(time); // 选择了未选中状态的日期
|
|
|
|
switch (pickMode) {
|
|
case 'single':
|
|
$picked = elements.date; // 移除之前选中日期的选中样式
|
|
|
|
if ($picked) {
|
|
removeClass($picked, CLS_PICKED);
|
|
} // 设置当前选中日期的选中样式
|
|
|
|
|
|
addClass($date, CLS_PICKED);
|
|
elements.date = $date;
|
|
this.setDate(time);
|
|
|
|
if (isFunction(callback)) {
|
|
callback(time, $date, this);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'multiple':
|
|
// 保存选中的日期,并对选中时间排序
|
|
this.data.picked.push(time);
|
|
this.data.picked.sort(); // 设置最晚的那个日期为当前选中日期
|
|
|
|
pickedDates = this.getPicked();
|
|
this.setDate(pickedDates[pickedDates.length - 1]);
|
|
addClass($date, CLS_PICKED);
|
|
|
|
if (isFunction(callback)) {
|
|
callback(this.getPicked(), $date, this);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'range':
|
|
// 根据已经选中的日期长度,处理数据的保存
|
|
switch (this.data.picked.length) {
|
|
case 0:
|
|
case 1:
|
|
// 保存选中的日期
|
|
this.data.picked.push(time); // 如果选择两个不同的日期,则完成了范围选择,需要对日期排序
|
|
|
|
if (this.data.picked.length === 2) {
|
|
this.data.picked.sort();
|
|
} // 设置选中日期范围的最后一天为当前选中日期
|
|
|
|
|
|
pickedDates = this.getPicked();
|
|
this.setDate(pickedDates[pickedDates.length - 1]);
|
|
elements.date = $date;
|
|
|
|
this._updateDateRanges();
|
|
|
|
if (isFunction(callback)) {
|
|
callback(pickedDates, $date, this);
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
// 之前已经选中了一个日期范围,现在需要清除之前的数据
|
|
this.data.picked = []; // 保存第一个日期点
|
|
|
|
this.data.picked.push(time);
|
|
elements.date = $date;
|
|
|
|
this._updateDateRanges();
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case 'week':
|
|
// 获得当前选中日期的星期范围
|
|
var ranges = Calendar.getWeekRanges(time); // 清除之前的数据,保存现在的星期日期范围
|
|
|
|
this.data.picked = [ranges[0], ranges[ranges.length - 1]];
|
|
this.setDate(ranges[ranges.length - 1]);
|
|
elements.date = $date;
|
|
|
|
this._updateWeekRanges();
|
|
|
|
if (isFunction(callback)) {
|
|
callback(this.getPicked(), $date, this);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 选择月份
|
|
* ========================================================================
|
|
* 1. 选择了已选中状态的月份:直接切换试图模式到日期试图模式
|
|
* 2. 选择了未选中状态的月份:移除之前选中的月份的选中样式,并当前选中的月份的选中
|
|
* 样式。然后更新选中年份和月份的数据,并切换到日期试图模式
|
|
* ========================================================================
|
|
* @param {HTMLElement} $month - 选中的月份 DOM 节点
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "pickMonth",
|
|
value: function pickMonth($month) {
|
|
var CLS_PICKED = this.get('STYLES').PICKED;
|
|
var DOM = Calendar.DOM;
|
|
var elements = this.getEls();
|
|
var $picked = elements.month;
|
|
var time = $month.getAttribute('data-month');
|
|
var callback = this.get('onMonthPick'); // 点击已经选中的年份
|
|
|
|
if (DOM.hasClass($month, CLS_PICKED)) {
|
|
// 切换到月份试图模式
|
|
this.update();
|
|
} else {
|
|
// 移除之前选中的年份选中样式
|
|
if ($picked) {
|
|
DOM.removeClass($picked, CLS_PICKED);
|
|
} // 设置选中样式
|
|
|
|
|
|
DOM.addClass($month, CLS_PICKED);
|
|
elements.month = $month;
|
|
|
|
this.setYear(time).setMonth(time)._setYears(time).update();
|
|
}
|
|
|
|
if (Calendar.Utils.isFunction(callback)) {
|
|
callback(time, $month, this);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 选择年份
|
|
* ========================================================================
|
|
* 1. 选择了已选中状态的年份:更新选中的年份信息,并切换到月份试图模式
|
|
* 2. 选择了未选中状态的年份:移除之前选中的年份的选中样式,将当前选中的年份设为选中
|
|
* 样式,并切换到月份试图模式
|
|
* ========================================================================
|
|
* @param {HTMLElement} $year - 选中的年份 DOM 节点
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "pickYear",
|
|
value: function pickYear($year) {
|
|
var CLS_PICKED = this.get('STYLES').PICKED;
|
|
var DOM = Calendar.DOM;
|
|
var elements = this.getEls();
|
|
var $picked = elements.year;
|
|
var time = $year.getAttribute('data-year');
|
|
var callback = this.get('onYearPick'); // 点击已经选中的月份
|
|
|
|
if (DOM.hasClass($year, CLS_PICKED)) {
|
|
// 切换到日期试图模式
|
|
this.setYear(time).update(1);
|
|
} else {
|
|
// 移除之前选中的年份选中样式
|
|
if ($picked) {
|
|
DOM.removeClass($picked, CLS_PICKED);
|
|
} // 设置选中样式
|
|
|
|
|
|
DOM.addClass($year, CLS_PICKED);
|
|
elements.year = $year; // 更新年份并切换到月份试图
|
|
|
|
this.setYear(time)._setYears(time).update(1);
|
|
}
|
|
|
|
if (Calendar.Utils.isFunction(callback)) {
|
|
callback(time, $year, this);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 选择今天
|
|
* ========================================================================
|
|
* 将今天的年份、月份以及日期信息设置为当前选中日期,并切换到日期试图模式
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "pickToday",
|
|
value: function pickToday() {
|
|
var time = Calendar.getToday().value;
|
|
var callback = this.get('onTodayPick');
|
|
|
|
this.setYear(time).setMonth(time).setDate(time)._setYears(time).update();
|
|
|
|
if (Calendar.Utils.isFunction(callback)) {
|
|
callback(time, this.getEls().dates.querySelector('[data-date=' + time + ']'), this);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 隐藏日历控件
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "hide",
|
|
value: function hide() {
|
|
var CLS_HIDDEN = this.get('STYLES').HIDDEN;
|
|
var $wrap = this.getEls().wrap;
|
|
Calendar.DOM.addClass($wrap, CLS_HIDDEN);
|
|
return this;
|
|
}
|
|
/**
|
|
* 显示日历控件
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "show",
|
|
value: function show() {
|
|
var CLS_HIDDEN = this.get('STYLES').HIDDEN;
|
|
var $wrap = this.getEls().wrap;
|
|
Calendar.DOM.removeClass($wrap, CLS_HIDDEN);
|
|
return this;
|
|
}
|
|
/**
|
|
* 隐藏/显示之间切换
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
*/
|
|
|
|
}, {
|
|
key: "toggle",
|
|
value: function toggle() {
|
|
var CLS_HIDDEN = this.get('STYLES').HIDDEN;
|
|
var $wrap = this.getEls().wrap;
|
|
|
|
if (Calendar.DOM.hasClass($wrap, CLS_HIDDEN)) {
|
|
this.show();
|
|
} else {
|
|
this.hide();
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 设置当前的年代信息
|
|
* ========================================================================
|
|
* @param {String|Number} [time] - 表示年份的字符串或者数字(默认值:今年)
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_setYears",
|
|
value: function _setYears(time) {
|
|
this.data.years = Calendar.getYears(time);
|
|
return this;
|
|
}
|
|
/**
|
|
* (多选模式)移除选中的日期
|
|
* ========================================================================
|
|
* @param {String|Number} time - 表示日期的字符串或者数字
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_removePicked",
|
|
value: function _removePicked(time) {
|
|
var pickedDates = this.getPicked();
|
|
var index = pickedDates.indexOf(time);
|
|
|
|
if (index > -1) {
|
|
pickedDates.splice(index, 1);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制日历控件的各个主要 DOM 节点
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_createElements",
|
|
value: function _createElements() {
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_WRAP = STYLES.WRAP;
|
|
var CLS_WRAP_WITHOUT_FOOTER = STYLES.WRAP_WITHOUT_FOOTER;
|
|
var CLS_HEADER = STYLES.HEADER;
|
|
var CLS_TITLE = STYLES.TITLE;
|
|
var CLS_SWITCHER = STYLES.SWITCHER;
|
|
var CLS_PREV = STYLES.PREV;
|
|
var CLS_ICON_PREV = STYLES.ICON_PREV;
|
|
var CLS_NEXT = STYLES.NEXT;
|
|
var CLS_ICON_NEXT = STYLES.ICON_NEXT;
|
|
var CLS_BODY = STYLES.BODY;
|
|
var CLS_WEEK = STYLES.WEEK;
|
|
var CLS_DATES = STYLES.DATES;
|
|
var CLS_MONTHS = STYLES.MONTHS;
|
|
var CLS_YEARS = STYLES.YEARS;
|
|
var CLS_FOOTER = STYLES.FOOTER;
|
|
var CLS_FOOTER_DATE = STYLES.FOOTER_DATE;
|
|
var CLS_TODAY = STYLES.TODAY;
|
|
var CLS_FOOTER_TIME = STYLES.FOOTER_TIME;
|
|
var CLS_TIME = STYLES.TIME;
|
|
var CLS_TEXT = STYLES.TEXT;
|
|
var CLS_HIDDEN = STYLES.HIDDEN;
|
|
var SPACE = ' ';
|
|
var hasFooter = this.get('hasFooter');
|
|
var elements = this.getEls();
|
|
var createElement = Calendar.DOM.createElement;
|
|
var wrapClassName = CLS_WRAP;
|
|
var weekClassName = CLS_WEEK;
|
|
var datesClassName = CLS_DATES;
|
|
var monthsClassName = CLS_MONTHS;
|
|
var yearsClassName = CLS_YEARS;
|
|
|
|
switch (this.get('viewMode')) {
|
|
case 0:
|
|
monthsClassName += SPACE + CLS_HIDDEN;
|
|
yearsClassName += SPACE + CLS_HIDDEN;
|
|
break;
|
|
|
|
case 1:
|
|
weekClassName += SPACE + CLS_HIDDEN;
|
|
datesClassName += SPACE + CLS_HIDDEN;
|
|
yearsClassName += SPACE + CLS_HIDDEN;
|
|
break;
|
|
|
|
case 2:
|
|
weekClassName += SPACE + CLS_HIDDEN;
|
|
datesClassName += SPACE + CLS_HIDDEN;
|
|
monthsClassName += SPACE + CLS_HIDDEN;
|
|
break;
|
|
}
|
|
|
|
if (!hasFooter) {
|
|
wrapClassName += SPACE + CLS_WRAP_WITHOUT_FOOTER;
|
|
}
|
|
|
|
elements.parent = document.getElementById(this.get('parent')); // wrap
|
|
|
|
elements.wrap = createElement('div', {
|
|
id: Calendar.Utils.guid('calendar'),
|
|
className: wrapClassName
|
|
}); // header
|
|
|
|
elements.header = createElement('div', {
|
|
className: CLS_HEADER
|
|
});
|
|
elements.title = createElement('h4', {
|
|
className: CLS_TITLE
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
})]); // 配置了显示上下切换按钮
|
|
|
|
if (this.get('hasSwitcher')) {
|
|
elements.switcher = createElement('div', {
|
|
className: CLS_SWITCHER
|
|
});
|
|
elements.prev = createElement('div', {
|
|
className: CLS_PREV
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [createElement('i', {
|
|
className: CLS_ICON_PREV
|
|
})])]);
|
|
elements.next = createElement('div', {
|
|
className: CLS_NEXT
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [createElement('i', {
|
|
className: CLS_ICON_NEXT
|
|
})])]);
|
|
} // body
|
|
|
|
|
|
elements.body = createElement('div', {
|
|
className: CLS_BODY
|
|
});
|
|
elements.week = createElement('div', {
|
|
className: weekClassName
|
|
});
|
|
elements.dates = createElement('div', {
|
|
className: datesClassName
|
|
});
|
|
elements.months = createElement('div', {
|
|
className: monthsClassName
|
|
});
|
|
elements.years = createElement('div', {
|
|
className: yearsClassName
|
|
}); // 配置了显示页脚
|
|
|
|
if (hasFooter) {
|
|
// footer
|
|
elements.footer = createElement('div', {
|
|
className: CLS_FOOTER
|
|
});
|
|
elements.today = createElement('div', {
|
|
className: CLS_FOOTER_DATE
|
|
}, [createElement('p', {
|
|
className: CLS_TODAY
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
})])]); // 配置了显示当前时间
|
|
|
|
if (this.get('hasClock')) {
|
|
elements.time = createElement('div', {
|
|
className: CLS_FOOTER_TIME
|
|
}, [createElement('p', {
|
|
className: CLS_TIME
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
})])]);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制日历控件的标题
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_renderTitle",
|
|
value: function _renderTitle() {
|
|
var $title = this.getEls().title.querySelector('.' + this.get('STYLES').TEXT);
|
|
var years = this.getYears();
|
|
var year = this.getYear();
|
|
var value = '';
|
|
|
|
switch (this.get('viewMode')) {
|
|
case 0:
|
|
// 显示完整的年月时间
|
|
value = Calendar.getMonth(year + '-' + this.getMonth() + '-1').fullText;
|
|
break;
|
|
|
|
case 1:
|
|
// 显示年份时间
|
|
value = Calendar.getYear(year + '-1-1').fullText;
|
|
break;
|
|
|
|
case 2:
|
|
// 显示年代范围格式时间
|
|
value = years.start + ' - ' + years.end;
|
|
break;
|
|
}
|
|
|
|
$title.innerHTML = value;
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制日历控件的星期栏
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_renderDays",
|
|
value: function _renderDays() {
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_DAY = STYLES.DAY;
|
|
var CLS_WEEKEND = STYLES.WEEKEND;
|
|
var CLS_TEXT = STYLES.TEXT;
|
|
var DAYS = this.get('DAYS');
|
|
var createElement = Calendar.DOM.createElement;
|
|
var fragment = document.createDocumentFragment();
|
|
DAYS.forEach(function (day, i) {
|
|
var className = i === 0 || i === DAYS.length - 1 ? CLS_DAY + ' ' + CLS_WEEKEND : CLS_DAY; // 先将创建的星期几的 DOM 节点保存到文档碎片
|
|
|
|
fragment.appendChild(createElement('div', {
|
|
className: className
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [day])]));
|
|
}); // 然后一次性添加到页面,性能会更好
|
|
|
|
this.getEls().week.appendChild(fragment);
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制日历控件的日期信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_renderDates",
|
|
value: function _renderDates() {
|
|
var DATES = this.get('DATES');
|
|
var isLeapYear = Calendar.isLeapYear; // fragments
|
|
|
|
var fragment = document.createDocumentFragment(); // current month
|
|
|
|
var year = this.getYear();
|
|
var month = this.getMonth();
|
|
var days = DATES[month - 1];
|
|
var firstDateDay = Calendar.getDay(year + '-' + month + '-' + 1).value; // prev month
|
|
|
|
var prevYear = month - 2 < 0 ? year - 1 : year;
|
|
var prevMonth = month - 2 < 0 ? 12 : month - 1;
|
|
var prevDays = DATES[prevMonth - 1]; // next month
|
|
|
|
var nextYear = month === 12 ? year + 1 : year;
|
|
var nextMonth = month === 12 ? 1 : month + 1;
|
|
var nextDays; // 如果当前是闰年,上个月是二月份,则闰年二月为29天
|
|
|
|
if (isLeapYear(year) && prevMonth === 2) {
|
|
prevDays += 1;
|
|
} else {
|
|
// 如果当前是闰年,当前月份是二月,则本月有29天
|
|
if (isLeapYear(year) && month === 2) {
|
|
days += 1;
|
|
}
|
|
}
|
|
|
|
nextDays = 42 - (firstDateDay + days); // 绘制上个月月底的最后几天
|
|
|
|
if (firstDateDay !== 0) {
|
|
fragment.appendChild(this._getDatesFragment({
|
|
year: prevYear,
|
|
month: prevMonth,
|
|
start: prevDays - (firstDateDay - 1),
|
|
end: prevDays,
|
|
isPrev: true,
|
|
isNext: false
|
|
}));
|
|
} // 绘制本月的日期
|
|
|
|
|
|
fragment.appendChild(this._getDatesFragment({
|
|
year: year,
|
|
month: month,
|
|
start: 1,
|
|
end: days,
|
|
isPrev: false,
|
|
isNext: false
|
|
})); // 绘制下个月月头的几天
|
|
|
|
if (nextDays > 0) {
|
|
fragment.appendChild(this._getDatesFragment({
|
|
year: nextYear,
|
|
month: nextMonth,
|
|
start: 1,
|
|
end: nextDays,
|
|
isPrev: false,
|
|
isNext: true
|
|
}));
|
|
}
|
|
|
|
this.getEls().dates.appendChild(fragment);
|
|
return this;
|
|
}
|
|
/**
|
|
* 重绘日历控件的日期信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_repaintDates",
|
|
value: function _repaintDates() {
|
|
var CLS_HIDDEN = this.get('STYLES').HIDDEN;
|
|
var DOM = Calendar.DOM;
|
|
var $dates = this.getEls().dates;
|
|
DOM.addClass($dates, CLS_HIDDEN);
|
|
$dates.innerHTML = '';
|
|
DOM.removeClass($dates, CLS_HIDDEN);
|
|
|
|
this._renderDates();
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 获得绘制日期信息时的文档碎片
|
|
* ========================================================================
|
|
* @param {Object} options - 参数对象
|
|
* @param {Number} options.year - 年份
|
|
* @param {Number} options.month - 月份
|
|
* @param {Number} options.start - 开始的日期
|
|
* @param {Number} options.end - 结束的日期
|
|
* @param {Boolean} options.isPrev - 是否为上个月的日期
|
|
* @param {Boolean} options.isNext - 是否为下个月的日期
|
|
* @returns {DocumentFragment}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_getDatesFragment",
|
|
value: function _getDatesFragment(options) {
|
|
var _this = this;
|
|
|
|
var year = options.year,
|
|
month = options.month,
|
|
start = options.start,
|
|
end = options.end,
|
|
isPrev = options.isPrev,
|
|
isNext = options.isNext;
|
|
var SPACE = ' ';
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_DATE = STYLES.DATE;
|
|
var CLS_DATE_PREV = STYLES.DATE_PREV;
|
|
var CLS_DATE_NEXT = STYLES.DATE_NEXT;
|
|
var CLS_CURRENT = STYLES.CURRENT;
|
|
var CLS_PICKED = STYLES.PICKED;
|
|
var CLS_PICKED_RANGE = STYLES.PICKED_RANGE;
|
|
var CLS_WEEKEND = STYLES.WEEKEND;
|
|
var CLS_TEXT = STYLES.TEXT;
|
|
var createElement = Calendar.DOM.createElement;
|
|
var isDatesEqual = Calendar.isDatesEqual;
|
|
var fragment = document.createDocumentFragment();
|
|
var elements = this.getEls();
|
|
var date = start;
|
|
var pickMode = this.get('pickMode');
|
|
var pickedDates = this.getPicked();
|
|
|
|
var _loop = function _loop() {
|
|
var fullDate = year + '-' + month + '-' + date;
|
|
var isCurrent = Calendar.isToday(fullDate);
|
|
var day = Calendar.getDay(fullDate);
|
|
var $children = [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [date])];
|
|
var className = '';
|
|
var $date = void 0;
|
|
$date = createElement('div', {
|
|
'data-date': fullDate
|
|
}, $children);
|
|
className += CLS_DATE;
|
|
|
|
if (isPrev) {
|
|
className += SPACE + CLS_DATE_PREV;
|
|
} else {
|
|
if (isNext) {
|
|
className += SPACE + CLS_DATE_NEXT;
|
|
}
|
|
} // 当前(今天)的日期
|
|
|
|
|
|
if (isCurrent) {
|
|
className += SPACE + CLS_CURRENT;
|
|
} // 周末
|
|
|
|
|
|
if (day.value === 0 || day.value === 6) {
|
|
className += SPACE + CLS_WEEKEND;
|
|
}
|
|
|
|
switch (pickMode) {
|
|
// 单选模式
|
|
case 'single':
|
|
var pickedDate = _this.getDate().text;
|
|
|
|
var isPickedDate = isDatesEqual(fullDate, pickedDate);
|
|
|
|
if (isPickedDate) {
|
|
className += SPACE + CLS_PICKED;
|
|
elements.date = $date;
|
|
}
|
|
|
|
break;
|
|
// 多选模式
|
|
|
|
case 'multiple':
|
|
pickedDates.forEach(function (picked) {
|
|
var isPicked = isDatesEqual(fullDate, picked);
|
|
|
|
if (isPicked) {
|
|
className += SPACE + CLS_PICKED;
|
|
}
|
|
});
|
|
break;
|
|
// 区间模式
|
|
|
|
case 'range':
|
|
case 'week':
|
|
var dateRanges = []; // 只有选中了两个节点,才绘制选中日期区间的样式
|
|
|
|
if (pickedDates.length === 2) {
|
|
dateRanges = Calendar.getRanges(pickedDates[0], pickedDates[1]);
|
|
dateRanges.forEach(function (picked, i) {
|
|
var isPicked = isDatesEqual(fullDate, picked);
|
|
|
|
if (!isPicked) {
|
|
return false;
|
|
} // 设置中间日期的样式
|
|
|
|
|
|
if (i !== 0 && i !== dateRanges.length - 1) {
|
|
className += SPACE + CLS_PICKED;
|
|
className += SPACE + CLS_PICKED_RANGE;
|
|
} else {
|
|
if (i === 0 || i === dateRanges.length - 1) {
|
|
className += SPACE + CLS_PICKED;
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
if (pickedDates.length === 1) {
|
|
className += SPACE + CLS_PICKED;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
$date.className = className;
|
|
fragment.appendChild($date);
|
|
};
|
|
|
|
for (; date <= end; date += 1) {
|
|
_loop();
|
|
}
|
|
|
|
return fragment;
|
|
}
|
|
/**
|
|
* 绘制选中的日期区间选中样式
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_updateDateRanges",
|
|
value: function _updateDateRanges() {
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_PICKED = STYLES.PICKED;
|
|
var CLS_PICKED_RANGE = STYLES.PICKED_RANGE;
|
|
var DOM = Calendar.DOM;
|
|
var hasClass = DOM.hasClass;
|
|
var removeClass = DOM.removeClass;
|
|
var addClass = DOM.addClass;
|
|
var elements = this.getEls();
|
|
var $date = this.elements.date;
|
|
var $dates = elements.dates;
|
|
var $pickedDates = $dates.querySelectorAll('.' + CLS_PICKED);
|
|
|
|
switch (this.data.picked.length) {
|
|
case 1:
|
|
// 移除之前的选中样式
|
|
$pickedDates.forEach(function ($picked) {
|
|
removeClass($picked, CLS_PICKED);
|
|
|
|
if (hasClass($picked, CLS_PICKED_RANGE)) {
|
|
removeClass($picked, CLS_PICKED_RANGE);
|
|
}
|
|
}); // 绘制选中的第一个端点的选中样式
|
|
|
|
addClass($date, CLS_PICKED);
|
|
break;
|
|
|
|
case 2:
|
|
var ranges = Calendar.getRanges(this.data.picked[0], this.data.picked[1]);
|
|
ranges.forEach(function (picked, i) {
|
|
var $picked = $dates.querySelector('[data-date="' + picked + '"]'); // 绘制中间区域的选中样式
|
|
|
|
if (i > 0 && i < ranges.length - 1) {
|
|
addClass($picked, CLS_PICKED);
|
|
addClass($picked, CLS_PICKED_RANGE);
|
|
}
|
|
}); // 绘制选中的第二个端点的选中样式
|
|
|
|
addClass($date, CLS_PICKED);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制选中的星期区间
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_updateWeekRanges",
|
|
value: function _updateWeekRanges() {
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_PICKED = STYLES.PICKED;
|
|
var CLS_PICKED_RANGE = STYLES.PICKED_RANGE;
|
|
var DOM = Calendar.DOM;
|
|
var removeClass = DOM.removeClass;
|
|
var addClass = DOM.addClass;
|
|
var elements = this.getEls();
|
|
var $dates = elements.dates;
|
|
var $pickedDates = $dates.querySelectorAll('.' + CLS_PICKED);
|
|
var picked = this.getPicked();
|
|
var ranges = Calendar.getWeekRanges(picked[0]); // 移除之前选中区域的样式
|
|
|
|
$pickedDates.forEach(function ($picked) {
|
|
removeClass($picked, CLS_PICKED_RANGE);
|
|
removeClass($picked, CLS_PICKED);
|
|
}); // 设置新的选中区域的样式
|
|
|
|
ranges.forEach(function (picked, i) {
|
|
var $picked = $dates.querySelector('[data-date="' + picked + '"]'); // 绘制中间区域
|
|
|
|
if (i > 0 && i < ranges.length - 1) {
|
|
addClass($picked, CLS_PICKED);
|
|
addClass($picked, CLS_PICKED_RANGE);
|
|
} else {
|
|
// 绘制两头的节点
|
|
if (i === 0 || i === ranges.length - 1) {
|
|
addClass($picked, CLS_PICKED);
|
|
}
|
|
}
|
|
});
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制日历控件的月份信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_renderMonths",
|
|
value: function _renderMonths() {
|
|
var _this2 = this;
|
|
|
|
var SPACE = ' ';
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_CURRENT = STYLES.CURRENT;
|
|
var CLS_PICKED = STYLES.PICKED;
|
|
var CLS_MONTH = STYLES.MONTH;
|
|
var CLS_MONTH_PREV = STYLES.MONTH_PREV;
|
|
var CLS_MONTH_NEXT = STYLES.MONTH_NEXT;
|
|
var CLS_TEXT = STYLES.TEXT;
|
|
var MONTHS = this.get('MONTHS');
|
|
var DOM = Calendar.DOM;
|
|
var createElement = DOM.createElement;
|
|
var fragment = document.createDocumentFragment();
|
|
var elements = this.getEls();
|
|
var year = this.getYear();
|
|
var today = Calendar.getToday();
|
|
MONTHS.forEach(function (MONTH, i) {
|
|
var pickedDate = _this2.getDate();
|
|
|
|
var className = CLS_MONTH;
|
|
var $month; // 去年的月份
|
|
|
|
if (i < 2) {
|
|
className += SPACE + CLS_MONTH_PREV; // 判断是否被选中了
|
|
|
|
if (year - 1 === pickedDate.year && MONTH === pickedDate.month) {
|
|
className += SPACE + CLS_PICKED;
|
|
} // 创建月份的 DOM 节点
|
|
|
|
|
|
$month = createElement('div', {
|
|
className: className,
|
|
'data-month': year - 1 + '-' + MONTH + '-1'
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [MONTH])]);
|
|
} else {
|
|
// 今年的月份
|
|
if (i >= 2 && i <= 13) {
|
|
// 判断是否为今天
|
|
if (year === today.year && MONTH === today.month) {
|
|
className += ' ' + CLS_CURRENT;
|
|
} // 判断是否被选中了
|
|
|
|
|
|
if (year === pickedDate.year && MONTH === pickedDate.month) {
|
|
className += SPACE + CLS_PICKED;
|
|
} // 创建月份的 DOM 节点
|
|
|
|
|
|
$month = createElement('div', {
|
|
className: className,
|
|
'data-month': year + '-' + MONTH + '-1'
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [year + '-' + MONTH])]);
|
|
} else {
|
|
// 明年的月份
|
|
if (i > 13 && i <= 15) {
|
|
className += SPACE + CLS_MONTH_NEXT; // 判断是否被选中了
|
|
|
|
if (year + 1 === pickedDate.year && MONTH === pickedDate.month) {
|
|
className += SPACE + CLS_PICKED;
|
|
} // 创建月份的 DOM 节点
|
|
|
|
|
|
$month = createElement('div', {
|
|
className: className,
|
|
'data-month': year + 1 + '-' + MONTH + '-1'
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [MONTH])]);
|
|
}
|
|
}
|
|
} // 将所有月份 DOM 节点缓存到文档碎片中
|
|
|
|
|
|
fragment.appendChild($month);
|
|
});
|
|
elements.months.appendChild(fragment);
|
|
return this;
|
|
}
|
|
/**
|
|
* 重绘日历控件的月份信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_repaintMonths",
|
|
value: function _repaintMonths() {
|
|
var CLS_HIDDEN = this.get('STYLES').HIDDEN;
|
|
var DOM = Calendar.DOM;
|
|
var $months = this.getEls().months;
|
|
DOM.addClass($months, CLS_HIDDEN);
|
|
$months.innerHTML = '';
|
|
DOM.removeClass($months, CLS_HIDDEN);
|
|
|
|
this._renderMonths();
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 绘制日历控件的年份信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_renderYears",
|
|
value: function _renderYears() {
|
|
var years = this.getYears();
|
|
var yearsStart = years.start;
|
|
var yearsEnd = years.end;
|
|
var prevStartYear = yearsStart - 3;
|
|
var prevEndYear = yearsStart - 1;
|
|
var nextStartYear = yearsEnd + 1;
|
|
var nextEndYear = yearsEnd + 3;
|
|
var fragment = document.createDocumentFragment();
|
|
fragment.appendChild(this._getYearsFragment({
|
|
start: prevStartYear,
|
|
end: prevEndYear,
|
|
isPrev: true,
|
|
isNext: false
|
|
}));
|
|
fragment.appendChild(this._getYearsFragment({
|
|
start: yearsStart,
|
|
end: yearsEnd,
|
|
isPrev: false,
|
|
isNext: false
|
|
}));
|
|
fragment.appendChild(this._getYearsFragment({
|
|
start: nextStartYear,
|
|
end: nextEndYear,
|
|
isPrev: false,
|
|
isNext: true
|
|
}));
|
|
this.getEls().years.appendChild(fragment);
|
|
return this;
|
|
}
|
|
/**
|
|
* 重绘日历控件的年份信息
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_repaintYears",
|
|
value: function _repaintYears() {
|
|
var CLS_HIDDEN = this.get('STYLES').HIDDEN;
|
|
var DOM = Calendar.DOM;
|
|
var $years = this.getEls().years;
|
|
DOM.addClass($years, CLS_HIDDEN);
|
|
$years.innerHTML = '';
|
|
DOM.removeClass($years, CLS_HIDDEN);
|
|
|
|
this._renderYears();
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 获取绘制年份信息的文档碎片
|
|
* ========================================================================
|
|
* @param {Object} options - 参数对象
|
|
* @param {Number} options.start - 开始年份
|
|
* @param {Number} options.end - 结束年份
|
|
* @param {Boolean} options.isPrev - 是否为上个年代的年份
|
|
* @param {Boolean} options.isNext - 是否为下个年带的年份
|
|
* @returns {DocumentFragment}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_getYearsFragment",
|
|
value: function _getYearsFragment(options) {
|
|
var start = options.start,
|
|
end = options.end,
|
|
isPrev = options.isPrev,
|
|
isNext = options.isNext;
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_YEAR = STYLES.YEAR;
|
|
var CLS_YEAR_PREV = STYLES.YEAR_PREV;
|
|
var CLS_YEAR_NEXT = STYLES.YEAR_NEXT;
|
|
var CLS_CURRENT = STYLES.CURRENT;
|
|
var CLS_PICKED = STYLES.PICKED;
|
|
var CLS_DISABLED = STYLES.DISABLED;
|
|
var CLS_TEXT = STYLES.TEXT;
|
|
var DOM = Calendar.DOM;
|
|
var createElement = DOM.createElement;
|
|
var fragment = document.createDocumentFragment();
|
|
var elements = this.getEls();
|
|
var minYear = this.data.minYear;
|
|
var maxYear = this.data.maxYear;
|
|
var year = start;
|
|
|
|
for (; year <= end; year += 1) {
|
|
var pickedDate = this.getDate();
|
|
var isCurrent = year === Calendar.getToday().year;
|
|
var isPicked = year === pickedDate.year;
|
|
var className = CLS_YEAR;
|
|
var $year = createElement('div', {
|
|
'data-year': year + '-1-1'
|
|
}, [createElement('span', {
|
|
className: CLS_TEXT
|
|
}, [year])]);
|
|
|
|
if (isPrev) {
|
|
className += ' ' + CLS_YEAR_PREV;
|
|
} else {
|
|
if (isNext) {
|
|
className += ' ' + CLS_YEAR_NEXT;
|
|
}
|
|
}
|
|
|
|
if (isCurrent) {
|
|
className += ' ' + CLS_CURRENT;
|
|
}
|
|
|
|
if (isPicked) {
|
|
className += ' ' + CLS_PICKED;
|
|
elements.year = $year;
|
|
}
|
|
|
|
if (year < minYear || year > maxYear) {
|
|
className += ' ' + CLS_DISABLED;
|
|
}
|
|
|
|
$year.className = className;
|
|
fragment.appendChild($year);
|
|
}
|
|
|
|
return fragment;
|
|
}
|
|
/**
|
|
* 绘制日历控件的页脚
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_renderFooter",
|
|
value: function _renderFooter() {
|
|
var STYLES = this.get('STYLES');
|
|
var CLS_TEXT = STYLES.TEXT;
|
|
var elements = this.getEls();
|
|
var $today = elements.today.querySelector('.' + CLS_TEXT);
|
|
var today = Calendar.getToday();
|
|
var timer = null;
|
|
|
|
var renderTime = function renderTime() {
|
|
var $time = elements.time.querySelector('.' + CLS_TEXT);
|
|
var time = new Date();
|
|
var hours = time.getHours();
|
|
var minutes = time.getMinutes();
|
|
var seconds = time.getSeconds();
|
|
|
|
if (timer) {
|
|
clearTimeout(timer);
|
|
}
|
|
|
|
if (hours < 10) {
|
|
hours = '0' + hours;
|
|
}
|
|
|
|
if (minutes < 10) {
|
|
minutes = '0' + minutes;
|
|
}
|
|
|
|
if (seconds < 10) {
|
|
seconds = '0' + seconds;
|
|
}
|
|
|
|
$time.innerHTML = hours + ':' + minutes + ':' + seconds;
|
|
timer = setTimeout(renderTime, 1000);
|
|
};
|
|
|
|
$today.innerHTML = '今天:' + today.text;
|
|
Calendar.DOM.setAttribute($today, 'data-date', today.value);
|
|
|
|
if (this.get('hasClock')) {
|
|
renderTime();
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 点击标题的事件处理器
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_titleClick",
|
|
value: function _titleClick() {
|
|
var viewMode = this.get('viewMode');
|
|
viewMode += 1;
|
|
|
|
if (viewMode > 2) {
|
|
viewMode = 2;
|
|
}
|
|
|
|
this.update(viewMode);
|
|
return this;
|
|
}
|
|
/**
|
|
* 点击向上翻页的事件处理器
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_prevClick",
|
|
value: function _prevClick() {
|
|
this.prev();
|
|
// return this;
|
|
}
|
|
/**
|
|
* 点击向下翻页的事件处理起
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_nextClick",
|
|
value: function _nextClick() {
|
|
this.next();
|
|
// return this;
|
|
}
|
|
/**
|
|
* 点击日期的事件处理器
|
|
* ========================================================================
|
|
* @param {Event} evt - 事件对象
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_dateClick",
|
|
value: function _dateClick(evt) {
|
|
var $el = evt.delegateTarget;
|
|
var time = $el.getAttribute('data-date');
|
|
var picked;
|
|
this.pickDate($el);
|
|
picked = this.getPicked();
|
|
console.log('------------- _dateClick -------------');
|
|
timeclick(time);
|
|
if (this.get('pickMode') === 'single') {
|
|
console.log(time);
|
|
} else {
|
|
console.log(picked);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* 点击月份的事件处理器
|
|
* ========================================================================
|
|
* @param {Event} evt - 事件对象
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_monthClick",
|
|
value: function _monthClick(evt) {
|
|
var $month = evt.delegateTarget;
|
|
var time = $month.getAttribute('data-month');
|
|
this.pickMonth($month);
|
|
console.log('------------- _monthClick -------------');
|
|
console.log(time);
|
|
return this;
|
|
}
|
|
/**
|
|
* 点击年份的事件处理器
|
|
* ========================================================================
|
|
* @param {Event} evt - 事件对象
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_yearClick",
|
|
value: function _yearClick(evt) {
|
|
var $el = evt.delegateTarget;
|
|
var time = $el.getAttribute('data-year');
|
|
this.pickYear($el);
|
|
console.log('------------- _yearClick -------------');
|
|
console.log(time);
|
|
return this;
|
|
}
|
|
/**
|
|
* 点击今天的事件处理器
|
|
* ========================================================================
|
|
* @returns {Calendar}
|
|
* @private
|
|
*/
|
|
|
|
}, {
|
|
key: "_todayClick",
|
|
value: function _todayClick() {
|
|
var elements = this.getEls();
|
|
var time = Calendar.getToday().text;
|
|
this.pickToday(); // 触发日期选择逻辑
|
|
|
|
this.pickDate(elements.dates.querySelector('[data-date="' + time + '"]'));
|
|
console.log('------------- _todayClick -------------');
|
|
console.log(time);
|
|
return this;
|
|
}
|
|
/**
|
|
* 获得年份信息
|
|
* ========================================================================
|
|
* @param {String|Number} [val] - 表示年份的字符串或者数字(默认值:今年)
|
|
* @returns {{value: (Number|{value, text, fullText}), text: string, fullText: string}}
|
|
*/
|
|
|
|
}], [{
|
|
key: "getYear",
|
|
value: function getYear(val) {
|
|
var time = !val ? new Date() : new Date(Calendar.toAllSupported(val));
|
|
var year = time.getFullYear();
|
|
return {
|
|
value: year,
|
|
text: year.toString(),
|
|
fullText: year + '年'
|
|
};
|
|
}
|
|
/**
|
|
* 获取月份信息
|
|
* ========================================================================
|
|
* @param {String|Number} [val] - 表示月份的字符串或者数字(默认值:本月)
|
|
* @returns {{value: number, text: string, fullText: string}}
|
|
*/
|
|
|
|
}, {
|
|
key: "getMonth",
|
|
value: function getMonth(val) {
|
|
var time = !val ? new Date() : new Date(Calendar.toAllSupported(val));
|
|
var year = Calendar.getYear(val);
|
|
var month = time.getMonth();
|
|
month += 1;
|
|
return {
|
|
value: month,
|
|
text: year.text + '-' + month,
|
|
fullText: year.fullText + month + '月'
|
|
};
|
|
}
|
|
/**
|
|
* 获取日期信息
|
|
* ========================================================================
|
|
* @param {String|Number} [val] - 表示日期的字符串或者数字(默认值:今天)
|
|
* @returns {{year: (Number|{value, text}), month: number, date: number, day: number, text: string, fullText: string}}
|
|
*/
|
|
|
|
}, {
|
|
key: "getDate",
|
|
value: function getDate(val) {
|
|
var time = !val ? new Date() : new Date(Calendar.toAllSupported(val));
|
|
var year = Calendar.getYear(val);
|
|
var month = Calendar.getMonth(val);
|
|
var date = time.getDate();
|
|
var day = Calendar.getDay(val);
|
|
var fullDate = year.value + '-' + month.value + '-' + date;
|
|
var text = month.fullText + date + '日';
|
|
return {
|
|
year: year.value,
|
|
month: month.value,
|
|
date: date,
|
|
day: day.value,
|
|
text: fullDate,
|
|
fullText: text + ' ' + day.fullText
|
|
};
|
|
}
|
|
/**
|
|
* 获取星期信息
|
|
* ========================================================================
|
|
* @param {String|Number} [val] - 表示日期的字符串或者数字(默认值:今天)
|
|
* @returns {{value: number, text: string, fullText: string}}
|
|
*/
|
|
|
|
}, {
|
|
key: "getDay",
|
|
value: function getDay(val) {
|
|
var time = !val ? new Date() : new Date(Calendar.toAllSupported(val));
|
|
var day = time.getDay();
|
|
var text = Calendar.defaults.DAYS[day];
|
|
return {
|
|
value: day,
|
|
text: text,
|
|
fullText: '星期' + text
|
|
};
|
|
}
|
|
/**
|
|
* 获取今天的日期信息
|
|
* ========================================================================
|
|
* @returns {{year: (Number|{value, text}), month: number, date: number, day: number, text: string, fullText: string}}
|
|
*/
|
|
|
|
}, {
|
|
key: "getToday",
|
|
value: function getToday() {
|
|
return Calendar.getDate();
|
|
}
|
|
/**
|
|
* 获取年代信息
|
|
* ========================================================================
|
|
* @param {String|Number} [val] - 表示年份的字符串或者数字(默认值:今年)
|
|
* @returns {{start: (number|Number|{value, text}), end: (*|number)}}
|
|
*/
|
|
|
|
}, {
|
|
key: "getYears",
|
|
value: function getYears(val) {
|
|
var year = Calendar.getYear(val).value;
|
|
var numbers = year.toString().split('');
|
|
var lastNumber = parseInt(numbers[numbers.length - 1], 10);
|
|
var yearsStart = 0;
|
|
var yearsEnd = 0;
|
|
|
|
if (lastNumber === 0) {
|
|
yearsStart = year;
|
|
yearsEnd = year + 9;
|
|
} else {
|
|
if (lastNumber === 9) {
|
|
yearsStart = year - 9;
|
|
yearsEnd = year;
|
|
} else {
|
|
yearsStart = year - lastNumber;
|
|
yearsEnd = year + (9 - lastNumber);
|
|
}
|
|
}
|
|
|
|
return {
|
|
start: yearsStart,
|
|
end: yearsEnd
|
|
};
|
|
}
|
|
/**
|
|
* 获取日期所属的整个星期的日期区间信息
|
|
* ========================================================================
|
|
* @param {String} time - 表示日期的字符串
|
|
* @returns {Array}
|
|
*/
|
|
|
|
}, {
|
|
key: "getWeekRanges",
|
|
value: function getWeekRanges(time) {
|
|
var DATES = Calendar.defaults.DATES;
|
|
var isLeapYear = Calendar.isLeapYear;
|
|
var day = Calendar.getDay(time).value;
|
|
var begins = time.split('-');
|
|
var year = parseInt(begins[0], 10);
|
|
var month = parseInt(begins[1], 10);
|
|
var date = parseInt(begins[2], 10);
|
|
var days = DATES[month - 1];
|
|
var startYear = year;
|
|
var startMonth = month;
|
|
var startDate = date - day;
|
|
var endYear = year;
|
|
var endMonth = month;
|
|
var endDate = date + (6 - day);
|
|
var prevMonth = 0; // 闰年2月为29天,默认值为28天,所以需要+1天
|
|
|
|
if (isLeapYear(year) && month === 2) {
|
|
days += 1;
|
|
}
|
|
|
|
if (startDate < 1) {
|
|
// 上一个月
|
|
prevMonth = month - 2;
|
|
startMonth -= 1;
|
|
|
|
if (prevMonth < 0) {
|
|
startYear -= 1;
|
|
startMonth = 12;
|
|
startDate = DATES[11] + startDate;
|
|
} else {
|
|
// 开始日期
|
|
startDate = DATES[prevMonth] + startDate;
|
|
}
|
|
}
|
|
|
|
if (endDate > days) {
|
|
endMonth += 1; // 结束日期
|
|
|
|
endDate = endDate - days;
|
|
|
|
if (prevMonth > 11) {
|
|
endYear += 1;
|
|
endMonth = 1;
|
|
}
|
|
}
|
|
|
|
return Calendar.getRanges(startYear + '-' + startMonth + '-' + startDate, endYear + '-' + endMonth + '-' + endDate);
|
|
}
|
|
/**
|
|
* 获取两个日期之间的所有日期信息
|
|
* ========================================================================
|
|
* @param {String} begin - 表示日期的字符串
|
|
* @param {String} end - 表示日期的字符串
|
|
* @returns {Array}
|
|
*/
|
|
|
|
}, {
|
|
key: "getRanges",
|
|
value: function getRanges(begin, end) {
|
|
var ONE_DAY_TO_SECONDS = 24 * 60 * 60 * 1000;
|
|
var ranges = [];
|
|
var begins = begin.split('-');
|
|
var ends = end.split('-');
|
|
var beginTime = new Date();
|
|
var endTime = new Date();
|
|
var beginNumber;
|
|
var endNumber;
|
|
var timeNumber;
|
|
beginTime.setUTCFullYear(parseInt(begins[0], 10), parseInt(begins[1], 10) - 1, parseInt(begins[2], 10));
|
|
endTime.setUTCFullYear(parseInt(ends[0], 10), parseInt(ends[1], 10) - 1, parseInt(ends[2], 10));
|
|
beginNumber = beginTime.getTime();
|
|
endNumber = endTime.getTime();
|
|
timeNumber = beginNumber;
|
|
|
|
for (; timeNumber <= endNumber; timeNumber += ONE_DAY_TO_SECONDS) {
|
|
ranges.push(Calendar.getDate(timeNumber).text);
|
|
}
|
|
|
|
return ranges;
|
|
}
|
|
/**
|
|
* 判断是否为闰年
|
|
* ========================================================================
|
|
* @param {Number} year - 年份数值
|
|
* @returns {boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: "isLeapYear",
|
|
value: function isLeapYear(year) {
|
|
return (year % 4 === 0 || year % 400 === 0) && year % 100 !== 0;
|
|
}
|
|
/**
|
|
* 判断是否为今天
|
|
* ========================================================================
|
|
* @param {String|Number} time - 表示日期的字符串或者数字
|
|
* @returns {*}
|
|
*/
|
|
|
|
}, {
|
|
key: "isToday",
|
|
value: function isToday(time) {
|
|
return Calendar.isDatesEqual(time);
|
|
}
|
|
/**
|
|
* 判断两个日期是否相等
|
|
* ========================================================================
|
|
* @param {String|Number} dateOne - 表示日期的字符串或者数字
|
|
* @param {String|Number} [dateTwo] - 表示日期的字符串或者数字(默认值:今天)
|
|
* @returns {boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: "isDatesEqual",
|
|
value: function isDatesEqual(dateOne, dateTwo) {
|
|
var getDate = Calendar.getDate;
|
|
return Calendar.isEqual(getDate(dateOne).text, getDate(dateTwo).text);
|
|
}
|
|
/**
|
|
* 判断两个时间是否相等
|
|
* ========================================================================
|
|
* @param {String|Number} timeOne - 表示日期的字符串或者数字
|
|
* @param {String|Number} timeTwo - 表示日期的字符串或者数字
|
|
* @returns {boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: "isEqual",
|
|
value: function isEqual(timeOne, timeTwo) {
|
|
var toAllSupported = Calendar.toAllSupported;
|
|
return new Date(toAllSupported(timeOne)).getTime() === new Date(toAllSupported(timeTwo)).getTime();
|
|
}
|
|
}, {
|
|
key: "toAllSupported",
|
|
value: function toAllSupported(time) {
|
|
var Utils = Calendar.Utils;
|
|
var date = [];
|
|
|
|
if (Utils.isNumber(time)) {
|
|
return time;
|
|
} else {
|
|
if (Utils.isString(time)) {
|
|
if (time.indexOf('-')) {
|
|
date = time.split('-');
|
|
} else {
|
|
if (time.indexOf('/')) {
|
|
date = time.split('/');
|
|
}
|
|
}
|
|
|
|
if (date.length === 1) {
|
|
date.push('1');
|
|
date.push('1');
|
|
} else {
|
|
if (date.length === 2) {
|
|
// 例如:'2019-1'
|
|
if (date[0].length === 4) {
|
|
date.push('1');
|
|
} else {
|
|
// 例如:'1-2019'
|
|
if (data[1].length === 4) {
|
|
date.unshift('1');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return date.join('/');
|
|
}
|
|
}
|
|
}
|
|
}]);
|
|
|
|
return Calendar;
|
|
}();
|
|
/**
|
|
* 日历控件默认的配置信息
|
|
* ========================================================================
|
|
*/
|
|
|
|
|
|
Calendar.defaults = {
|
|
parent: 'calendar',
|
|
time: '',
|
|
// 0 - 日期显示模式(默认值)
|
|
// 1 - 月份显示模式
|
|
// 2 - 年代显示模式
|
|
viewMode: 0,
|
|
// single - 单选(默认值)
|
|
// multiple - 多选
|
|
// range - 范围多选
|
|
// week - 整个星期选择
|
|
pickMode: 'single',
|
|
hasSwitcher: true,
|
|
hasFooter: true,
|
|
hasClock: true,
|
|
onDatePick: null,
|
|
onMonthPick: null,
|
|
onYearPick: null,
|
|
onTodayPick: null,
|
|
MONTHS: [11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2],
|
|
DAYS: ['日', '一', '二', '三', '四', '五', '六'],
|
|
DATES: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
|
|
STYLES: {
|
|
WRAP: 'cal-md',
|
|
WRAP_WITHOUT_FOOTER: 'cal-md-without-footer',
|
|
HEADER: 'cal-hd',
|
|
TITLE: 'cal-title',
|
|
SWITCHER: 'cal-switcher',
|
|
PREV: 'cal-prev',
|
|
ICON_PREV: 'icon-angle-up',
|
|
NEXT: 'cal-next',
|
|
ICON_NEXT: 'icon-angle-down',
|
|
BODY: 'cal-bd',
|
|
WEEK: 'cal-week',
|
|
WEEKEND: 'cal-weekend',
|
|
DAY: 'cal-day',
|
|
DATES: 'cal-dates',
|
|
DATE: 'cal-date',
|
|
DATE_PREV: 'cal-date-prev',
|
|
DATE_NEXT: 'cal-date-next',
|
|
MONTHS: 'cal-months',
|
|
MONTH: 'cal-month',
|
|
MONTH_PREV: 'cal-month-prev',
|
|
MONTH_NEXT: 'cal-month-next',
|
|
YEARS: 'cal-years',
|
|
YEAR: 'cal-year',
|
|
YEAR_PREV: 'cal-year-prev',
|
|
YEAR_NEXT: 'cal-year-next',
|
|
FOOTER: 'cal-ft',
|
|
FOOTER_DATE: 'cal-ft-date',
|
|
TODAY: 'cal-today',
|
|
FOOTER_TIME: 'cal-ft-time',
|
|
TIME: 'cal-time',
|
|
TEXT: 'cal-text',
|
|
CURRENT: 'cal-current',
|
|
PICKED: 'cal-picked',
|
|
PICKED_RANGE: 'cal-picked-range',
|
|
PICKED_POINT: 'cal-picked-point',
|
|
DISABLED: 'cal-disabled',
|
|
HIDDEN: 'cal-hidden'
|
|
}
|
|
/**
|
|
* 常用的工具方法
|
|
* ========================================================================
|
|
*/
|
|
|
|
};
|
|
Calendar.Utils = {
|
|
uuid: 0,
|
|
isString: function isString(o) {
|
|
return typeof o === 'string';
|
|
},
|
|
isNumber: function isNumber(o) {
|
|
return typeof o === 'number';
|
|
},
|
|
isArray: function isArray(o) {
|
|
if (Array.isArray) {
|
|
return Array.isArray(o);
|
|
} else {
|
|
return Object.prototype.toString.apply(o) === '[object Array]';
|
|
}
|
|
},
|
|
isFunction: function isFunction(o) {
|
|
return typeof o === 'function' || Object.prototype.toString.apply(o) === '[object Function]';
|
|
},
|
|
isElement: function isElement(o) {
|
|
return o && o.nodeName && o.tagName && o.nodeType === 1;
|
|
},
|
|
guid: function guid(prefix) {
|
|
var Utils = Calendar.Utils;
|
|
Utils.uuid += 1;
|
|
return prefix ? prefix + '-' + Utils.uuid : 'guid-' + Utils.uuid;
|
|
},
|
|
trim: function trim(str) {
|
|
return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
|
},
|
|
stripTags: function stripTags(str) {
|
|
return str.replace(/<\/?[^>]+(>|$)/g, '');
|
|
}
|
|
/**
|
|
* DOM 操作相关的工具方法
|
|
* ========================================================================
|
|
*/
|
|
|
|
};
|
|
Calendar.DOM = {
|
|
/**
|
|
* 创建 DOM 节点,并添加属性和子节点
|
|
* ========================================================================
|
|
* @param {String} tagName - 标签名称
|
|
* @param {Object} attributes - 属性对象
|
|
* @param {Array} [children] - 子节点数组
|
|
* @returns {HTMLElement}
|
|
*/
|
|
createElement: function createElement(tagName, attributes, children) {
|
|
var Utils = Calendar.Utils;
|
|
var element = document.createElement(tagName);
|
|
|
|
for (var attr in attributes) {
|
|
if (attributes.hasOwnProperty(attr)) {
|
|
Calendar.DOM.setAttribute(element, attr, attributes[attr]);
|
|
}
|
|
}
|
|
|
|
if (Utils.isArray(children)) {
|
|
children.forEach(function (child) {
|
|
var childNode;
|
|
|
|
if (Utils.isElement(child)) {
|
|
childNode = child;
|
|
} else {
|
|
if (Utils.isString(child) || Utils.isNumber(child)) {
|
|
var text = Utils.isString(child) ? Utils.trim(Utils.stripTags(child)) : child.toString();
|
|
childNode = document.createTextNode(text);
|
|
}
|
|
}
|
|
|
|
element.appendChild(childNode);
|
|
});
|
|
}
|
|
|
|
return element;
|
|
},
|
|
|
|
/**
|
|
* 给 DOM 节点设置属性/值
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - DOM 节点
|
|
* @param {String} attr - 属性名称
|
|
* @param {String|Number|Boolean} value - 属性值
|
|
*/
|
|
setAttribute: function setAttribute(el, attr, value) {
|
|
var tagName = el.tagName.toLowerCase();
|
|
|
|
switch (attr) {
|
|
case 'style':
|
|
el.style.cssText = value;
|
|
break;
|
|
|
|
case 'value':
|
|
if (tagName === 'input' || tagName === 'textarea') {
|
|
el.value = value;
|
|
} else {
|
|
el.setAttribute(attr, value);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'className':
|
|
el.className = value;
|
|
break;
|
|
|
|
default:
|
|
el.setAttribute(attr, value);
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 检测 DOM 节点是否包含名为 className 的样式
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - DOM 节点
|
|
* @param {String} className - 样式名称
|
|
* @returns {*}
|
|
*/
|
|
hasClass: function hasClass(el, className) {
|
|
var allClass = el.className;
|
|
|
|
if (!allClass) {
|
|
return false;
|
|
}
|
|
|
|
return allClass.match(new RegExp('(\\s|^)' + className + '(\\s|$)'));
|
|
},
|
|
|
|
/**
|
|
* 给 DOM 节点添加名为 className 的样式
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - DOM 节点
|
|
* @param {String} className - 样式名称
|
|
* @returns {Boolean}
|
|
*/
|
|
addClass: function addClass(el, className) {
|
|
var allClass = el.className;
|
|
|
|
if (Calendar.DOM.hasClass(el, className)) {
|
|
return false;
|
|
}
|
|
|
|
allClass += allClass.length > 0 ? ' ' + className : className;
|
|
el.className = allClass;
|
|
},
|
|
|
|
/**
|
|
* 移除 DOM 节点的 className 样式
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - DOM 节点
|
|
* @param {String} className - 样式名称
|
|
* @returns {Boolean}
|
|
*/
|
|
removeClass: function removeClass(el, className) {
|
|
var allClass = el.className;
|
|
|
|
if (!allClass || !Calendar.DOM.hasClass(el, className)) {
|
|
return false;
|
|
}
|
|
|
|
allClass = Calendar.Utils.trim(allClass.replace(className, ''));
|
|
el.className = allClass;
|
|
}
|
|
};
|
|
/**
|
|
* 代理事件
|
|
* ========================================================
|
|
* 说明:代码修改至 Nicolas Gallagher 的 delegate.js
|
|
* 项目 GitHub 地址:https://github.com/necolas/delegate.js
|
|
* ========================================================
|
|
*/
|
|
|
|
Calendar.Delegate = {
|
|
/**
|
|
* 绑定代理事件
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - 绑定代理事件的 DOM 节点
|
|
* @param {String} selector - 触发 el 代理事件的 DOM 节点的选择器
|
|
* @param {String} type - 事件类型
|
|
* @param {Function} callback - 绑定事件的回调函数
|
|
* @param {Object} [context] - callback 回调函数的 this 上下文(默认值:el)
|
|
* @param {Boolean} [capture] - 是否采用事件捕获(默认值:false - 事件冒泡)
|
|
* @param {Boolean} [once] - 是否只触发一次(默认值:false - 事件冒泡)
|
|
*/
|
|
on: function on(el, selector, type, callback, context, capture,
|
|
/* private */
|
|
once) {
|
|
var Delegate = Calendar.Delegate;
|
|
|
|
var wrapper = function wrapper(e) {
|
|
var delegateTarget = Delegate.getDelegateTarget(el, e.target, selector);
|
|
e.delegateTarget = delegateTarget;
|
|
|
|
if (delegateTarget) {
|
|
if (once === true) {
|
|
Delegate.off(el, type, wrapper);
|
|
}
|
|
|
|
callback.call(context || el, e);
|
|
}
|
|
};
|
|
|
|
if (type === 'mouseenter' || type === 'mouseleave') {
|
|
capture = true;
|
|
}
|
|
|
|
callback._delegateWrapper = callback;
|
|
el.addEventListener(type, wrapper, capture || false);
|
|
return callback;
|
|
},
|
|
|
|
/**
|
|
* 绑定只触发一次的事件
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - 绑定代理事件的 DOM 节点
|
|
* @param {String} selector - 触发 el 代理事件的 DOM 节点的选择器
|
|
* @param {String} type - 事件类型
|
|
* @param {Function} callback - 绑定事件的回调函数
|
|
* @param {Object} [context] - callback 回调函数的 this 上下文(默认值:el)
|
|
* @param {Boolean} [capture] - 是否采用事件捕获(默认值:false - 事件冒泡)
|
|
*/
|
|
once: function once(el, type, selector, callback, context, capture) {
|
|
Calendar.Delegate.on(el, type, selector, callback, context, capture, true);
|
|
},
|
|
|
|
/**
|
|
* 取消事件绑定
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - 取消绑定(代理)事件的 DOM 节点
|
|
* @param {String} type - 事件类型
|
|
* @param {Function} callback - 绑定事件的回调函数
|
|
* @param {Boolean} [capture] - 是否采用事件捕获(默认值:false - 事件冒泡)
|
|
*/
|
|
off: function off(el, type, callback, capture) {
|
|
if (callback._delegateWrapper) {
|
|
callback = callback._delegateWrapper;
|
|
delete callback._delegateWrapper;
|
|
}
|
|
|
|
if (type === 'mouseenter' || type === 'mouseleave') {
|
|
capture = true;
|
|
}
|
|
|
|
el.removeEventListener(type, callback, capture || false);
|
|
},
|
|
|
|
/**
|
|
* 停止事件(阻止默认行为和阻止事件的捕获或冒泡)
|
|
* ========================================================================
|
|
* @param {Event} evt - 事件对象
|
|
*/
|
|
stop: function stop(evt) {
|
|
var Delegate = Calendar.Delegate;
|
|
Delegate.stopPropagation(evt);
|
|
Delegate.preventDefault(evt);
|
|
},
|
|
|
|
/**
|
|
* 终止事件在传播过程的捕获或冒泡
|
|
* ========================================================================
|
|
* @param {Event} evt - 事件对象
|
|
*/
|
|
stopPropagation: function stopPropagation(evt) {
|
|
var event = window.event;
|
|
|
|
if (evt.stopPropagation) {
|
|
evt.stopPropagation();
|
|
} else {
|
|
event.cancelBubble = true;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 阻止事件的默认行为
|
|
* ========================================================================
|
|
* @param {Event} evt - 事件对象
|
|
*/
|
|
preventDefault: function preventDefault(evt) {
|
|
var event = window.event;
|
|
|
|
if (evt.preventDefault) {
|
|
evt.preventDefault();
|
|
} else {
|
|
event.returnValue = false;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 通过 className 获得事件代理节点的事件代理目标节点
|
|
* ========================================================================
|
|
* @param {HTMLElement} el - 绑定事件代理的节点
|
|
* @param target - (触发事件后)事件的目标对象
|
|
* @param selector - 目标节点的类选择器
|
|
* @returns {HTMLElement|Null}
|
|
*/
|
|
getDelegateTarget: function getDelegateTarget(el, target, selector) {
|
|
while (target && target !== el) {
|
|
if (Calendar.DOM.hasClass(target, selector.replace('.', ''))) {
|
|
return target;
|
|
}
|
|
|
|
target = target.parentElement;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}; // 为了处理不兼容 Object.assign
|
|
|
|
if (!Calendar.Utils.isFunction(Object.assign)) {
|
|
// Must be writable: true, enumerable: false, configurable: true
|
|
Object.defineProperty(Object, "assign", {
|
|
value: function assign(target, varArgs) {
|
|
// .length of function is 2
|
|
'use strict';
|
|
|
|
if (target == null) {
|
|
// TypeError if undefined or null
|
|
throw new TypeError('Cannot convert undefined or null to object');
|
|
}
|
|
|
|
var to = Object(target);
|
|
|
|
for (var index = 1; index < arguments.length; index++) {
|
|
var nextSource = arguments[index];
|
|
|
|
if (nextSource != null) {
|
|
// Skip over if undefined or null
|
|
for (var nextKey in nextSource) {
|
|
// Avoid bugs when hasOwnProperty is shadowed
|
|
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
|
to[nextKey] = nextSource[nextKey];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return to;
|
|
},
|
|
writable: true,
|
|
configurable: true
|
|
});
|
|
}
|
|
return Calendar;
|
|
}));
|