/** * ESUI (Enterprise Simple UI) * Copyright 2013 Baidu Inc. All rights reserved. * * @ignore * @file 日历 * @author dbear, otakustay */ define( function (require) { require('./MonthView'); var u = require('underscore'); var moment = require('moment'); var lib = require('./lib'); var ui = require('./main'); var InputControl = require('./InputControl'); var Layer = require('./Layer'); /** * 日历用浮层 * * @extends Layer * @ignore * @constructor */ function CalendarLayer() { Layer.apply(this, arguments); } lib.inherits(CalendarLayer, Layer); CalendarLayer.prototype.render = function (element) { document.body.appendChild(element); element.innerHTML = '<div data-ui-type="MonthView" ' + 'data-ui-child-name="monthView"></div>'; var calendar = this.control; calendar.helper.initChildren(element); var monthView = calendar.getChild('monthView'); monthView.setProperties( { 'rawValue': calendar.rawValue, 'range': calendar.range }); monthView.on('change', syncMonthViewValue, calendar); if (calendar.autoHideLayer) { monthView.on( 'itemclick', u.bind(calendar.layer.toggle, calendar.layer) ); } }; CalendarLayer.prototype.toggle = function () { var element = this.getElement(); if (!element || this.control.helper.isPart(element, 'layer-hidden') ) { // 展示之前先跟main同步 var calendar = this.control; var monthView = calendar.getChild('monthView'); monthView.setProperties( { 'rawValue': calendar.rawValue, 'range': calendar.range } ); this.show(); } else { this.hide(); } }; /** * 日历控件 * * 日历控件是由一个按钮和一个浮层组成的,如果你只需要显示一个月日期的效果, * 请使用{@link MonthView}控件 * * @extends InputControl * @requires MonthView * @constructor */ function Calendar() { InputControl.apply(this, arguments); this.layer = new CalendarLayer(this); } /** * 更新显示 * * @param {MonthView} monthView MonthView控件实例 * @ignore */ function syncMonthViewValue() { var monthView = this.getChild('monthView'); var date = monthView.getRawValue(); if (!date) { return; } this.rawValue = date; updateDisplayText(this); /** * @event change * * 值发生变化时触发 * * @member Calendar */ this.fire('change'); } /** * 更新显示的文字 * * @param {Calendar} calendar 控件实例 * @ignore */ function updateDisplayText(calendar) { // 更新主显示 var textHolder = calendar.helper.getPart('text'); textHolder.innerHTML = u.escape(calendar.getValue()); } Calendar.prototype = { /** * 控件类型,始终为`"Calendar"` * * @type {string} * @readonly * @override */ type: 'Calendar', /** * 初始化参数 * * @param {Object} [options] 构造函数传入的参数 * @protected * @override */ initOptions: function (options) { var now = new Date(); var properties = { range: { begin: new Date(1983, 8, 3), end: new Date(2046, 10, 4) }, /** * @property {string} [dateFormat="YYYY-MM-DD"] * * 输出的日期格式,用于{@link Calendar#getValue}返回时格式化 * * 具体的日期格式参考 * [moment文档](http://momentjs.com/docs/#/displaying/format/) */ dateFormat: 'YYYY-MM-DD', /** * @property {string} [paramFormat="YYYY-MM-DD"] * * 输入的日期格式,用于{@link Calendar#setValue}时格式化 * * 具体的日期格式参考 * [moment文档](http://momentjs.com/docs/#/displaying/format/) */ paramFormat: 'YYYY-MM-DD', /** * @property {Date} [rawValue] * * 控件的原始值,为`Date`类型,默认为当天 * * @override */ rawValue: now, // 是否点击自动关闭弹层 autoHideLayer: false }; if (options.autoHideLayer === 'false') { options.autoHideLayer = false; } u.extend(properties, options); if (lib.isInput(this.main)) { this.helper.extractOptionsFromInput(this.main, properties); } // parseValue 需要用到 paramFormat this.paramFormat = properties.paramFormat; if (properties.value) { properties.rawValue = this.parseValue(properties.value); } // 类型如果是string var range = properties.range; if (typeof range === 'string') { var beginAndEnd = range.split(','); var begin = this.parseValue(beginAndEnd[0]); var end = this.parseValue(beginAndEnd[1]); properties.range = { begin: begin, end: end }; } this.setProperties(properties); }, /** * 初始化DOM结构 * * @protected * @override */ initStructure: function () { // 如果主元素是输入元素,替换成`<div>` // 如果输入了非块级元素,则不负责 if (lib.isInput(this.main)) { this.helper.replaceMain(); } var template = [ '<div class="${classes}" id="${id}">${value}</div>', '<div class="${arrow}"></div>' ]; this.main.innerHTML = lib.format( template.join(''), { classes: this.helper.getPartClassName('text'), id: this.helper.getId('text'), arrow: this.helper.getPartClassName('arrow') } ); }, /** * 初始化事件交互 * * @protected * @override */ initEvents: function () { this.helper.addDOMEvent(this.main, 'click', u.bind(this.layer.toggle, this.layer)); }, /** * 重渲染 * * @method * @protected * @override */ repaint: require('./painters').createRepaint( InputControl.prototype.repaint, { /** * @property {meta.DateRange} range * * 指定控件可选的时间段 */ name: ['rawValue', 'range'], paint: function (calendar, rawValue, range) { if (calendar.disabled || calendar.readOnly) { return; } updateDisplayText(calendar); // if (calendar.layer) { // 更新日历 var monthView = calendar.getChild('monthView'); if (monthView) { monthView.setProperties({ rawValue: rawValue, range: range }); } // } } }, { name: ['disabled', 'hidden', 'readOnly'], paint: function (calendar, disabled, hidden, readOnly) { if (disabled || hidden || readOnly) { calendar.layer.hide(); } } } ), /** * 设置日期可选区间 * * @param {meta.DateRange} range 日期可选区间 */ setRange: function (range) { this.setProperties({ 'range': range }); }, /** * 将值从原始格式转换成字符串,复杂类型的输入控件需要重写此接口 * * @param {Date} rawValue 原始值 * @return {string} * @protected * @override */ stringifyValue: function (rawValue) { return moment(rawValue).format(this.dateFormat) || ''; }, /** * 将字符串类型的值转换成原始格式,复杂类型的输入控件需要重写此接口 * * @param {string} value 字符串值 * @return {Date} * @protected * @override */ parseValue: function (value) { var date = moment(value, this.paramFormat).toDate(); return date; }, /** * 销毁 * * @override */ dispose: function () { if (this.helper.isInStage('DISPOSED')) { return; } if (this.layer) { this.layer.dispose(); this.layer = null; } InputControl.prototype.dispose.apply(this, arguments); } }; lib.inherits(Calendar, InputControl); ui.register(Calendar); return Calendar; } );