123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839 |
- /*
- * PHPWind util Library
- * @Copyright : Copyright 2011, phpwind.com
- * @Descript : datePicker 日历组件
- * @Author : jquerytools (http://jquerytools.org/demos/dateinput/)
- * @Modify : chaoren1641@gmail.com
- * @Depend : jquery.js(1.7 or later)
- * $Id: datePicker.js 22586 2012-12-25 10:54:55Z hao.lin $ :
- */
- ;(function($, window, document, undefined) {
- var pluginName = 'datePicker';
- var instances = [];
- // h=72, j=74, k=75, l=76, down=40, left=37, up=38, right=39
- var KEYS = [75, 76, 38, 39, 74, 72, 40, 37], LABELS = {};
- var defaults = {
- format : 'yyyy-mm-dd',
- selectors : true,
- time : false,
- yearRange : [-50, 20],
- lang : 'zh-CN',
- offset : [0, 0],
- speed : 0,
- firstDay : 0, // The first day of the week, Sun = 0, Mon = 1, ...
- min : undefined,
- max : undefined,
- trigger : false,
- css : {
- prefix : 'cal',
- input : 'date',
- // ids
- root : 0,
- head : 0,
- title : 0,
- prev : 0,
- next : 0,
- month : 0,
- year : 0,
- days : 0,
- body : 0,
- weeks : 0,
- today : 0,
- current : 0,
- // classnames
- week : 0,
- off : 0,
- sunday : 0,
- focus : 0,
- disabled : 0,
- trigger : 0
- }
- };
- var localize = function(language, labels) {
- $.each(labels, function(key, val) {
- labels[key] = val.split(",");
- });
- LABELS[language] = labels;
- };
- //多语言配置
- localize("en", {
- months : 'January,February,March,April,May,June,July,August,September,October,November,December',
- shortMonths : 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec',
- days : 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday',
- shortDays : 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'
- });
- localize("zh-CN", {
- months : '一月,二月,三月,四月,五月,六月,七月,八月,九月,十月,十一月,十二月',
- shortMonths : '一,二,三,四,五,六,七,八,九,十,十一,十二',
- days : '周日,周一,周二,周三,周四,周五,周六',
- shortDays : '日,一,二,三,四,五,六'
- });
- //{{{ private functions
- //返回某年某月的天数
- function dayAm(year, month) {
- return 32 - new Date(year, month, 32).getDate();
- }
- function zeropad(val, len) {
- val = '' + val;
- len = len || 2;
- while(val.length < len) {
- val = "0" + val;
- }
- return val;
- }
- // thanks: http://stevenlevithan.com/assets/misc/date.format.js
- var Re = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, tmpTag = $("<a/>");
- //格式化时间
- function format(date, fmt, lang) {
- var d = date.getDate(), D = date.getDay(), m = date.getMonth(), y = date.getFullYear(),
- h = date.getHours(),M = date.getMinutes(),
- flags = {
- d : d,
- dd : zeropad(d),
- ddd : LABELS[lang].shortDays[D],
- dddd : LABELS[lang].days[D],
- m : m + 1,
- mm : zeropad(m + 1),
- mmm : LABELS[lang].shortMonths[m],
- mmmm : LABELS[lang].months[m],
- yy : String(y).slice(2),
- yyyy : y,
- HH: zeropad(h),
- MM : zeropad(M)
- };
- var ret = fmt.replace(Re, function($0) {
- return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
- });
- // a small trick to handle special characters
- return tmpTag.html(ret).html();
- }
- function integer(val) {
- return parseInt(val, 10);
- }
- function isSameDay(d1, d2) {
- return d1.getFullYear() === d2.getFullYear() && d1.getMonth() == d2.getMonth() && d1.getDate() == d2.getDate();
- }
- function parseDate(val) {
- if(!val) {
- return;
- }
- if(val.constructor == Date) {
- return val;
- }
- if( typeof val == 'string') {
- // rfc3339?
- var els = val.split(" ");
- var date,time;
- var y,m,d,h,s;
- date = els[0].split('-');
- if(date.length !== 3) {
- return;
- }
- if(els.length === 2) {
- time = els[1].split(':');
- }else {
- time = '00:00'.split(':');
- }
- y = date[0],m = date[1]-1,d = date[2];
- h = time[0],s = time[1];
- return new Date(y,m,d,h,s,0);
- // invalid offset
- if(!/^-?\d+$/.test(val)) {
- return;
- }
- // convert to integer
- val = integer(val);
- }
- var date = new Date();
- date.setDate(date.getDate() + val);
- return date;
- }
- function Plugin( input, options ) {
- this.options = $.extend( {}, defaults, options) ;
- this.input = input;
- this.init();
- }
- Plugin.prototype.init = function() {
- var options = this.options,input = this.input;
- if(options.time) {
- options.format = 'yyyy-mm-dd HH:MM'
- }
- // CSS prefix
- $.each(options.css, function(key, val) {
- if(!val && key != 'prefix') {
- options.css[key] = (options.css.prefix || '') + (val || key);
- }
- });
- // variables
- var self = this, now = new Date(), css = options.css, labels = LABELS[options.lang], root = $("#" + css.root), title = root.find("#" + css.title), trigger, pm, nm, currYear, currMonth, currDay, value = input.attr("data-value") || options.value || input.val(), min = input.attr("min") || options.min, max = input.attr("max") || options.max, opened;
- // zero min is not undefined
- if(min === 0) {
- min = "0";
- }
- // use sane values for value, min & max
- value = parseDate(value) || now;
- min = parseDate(min || options.yearRange[0] * 365);
- max = parseDate(max || options.yearRange[1] * 365);
- // check that language exists
- if(!labels) {
- throw "不存在的语言: " + options.lang;
- }
- // Replace built-in date input: NOTE: input.attr("type", "text") throws exception by the browser
- if(input.attr("type") === 'date') {
- var tmp = $("<input/>");
- $.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","), function(i, attr) {
- tmp.attr(attr, input.attr(attr));
- });
- input.replaceWith(tmp);
- input = tmp;
- }
- input.addClass(css.input);
- var fire = input.add(self);
- // construct layout
- if(!root.length) {
- // root
- root = $('<div><div><a/><div/><a/></div><div><div/><div/></div></div>').hide().css({
- position : 'absolute'
- }).attr("id", css.root);
- // elements
- root.children().eq(0).attr("id", css.head).end().eq(1).attr("id", css.body).children().eq(0).attr("id", css.days).end().eq(1).attr("id", css.weeks).end().end().end().find("a").eq(0).attr("id", css.prev).end().eq(1).attr("id", css.next);
- // title
- title = root.find("#" + css.head).find("div").attr("id", css.title);
- // year & month selectors
- if(options.selectors) {
- var monthSelector = $("<select/>").attr("id", css.month), yearSelector = $("<select/>").attr("id", css.year);
- title.html(monthSelector.add(yearSelector));
- }
- // day titles
- var days = root.find("#" + css.days);
- // days of the week
- for(var d = 0; d < 7; d++) {
- days.append($("<span/>").text(labels.shortDays[(d + options.firstDay) % 7]));
- }
- var body = root.find("#" + css.body);
- $('<div class="caltime"><button type="button" class="btn btn_submit fr" name="submit">确认</button><input id="calHour" type="number" class="input" min="0" max="23" size="2" value="0"><span>点</span><input id="calMin" class="input" type="number" size="2" min="1" max="59" value="0"><span>分</span></div>').appendTo(body);
- $("body").append(root);
- }
- // trigger icon
- if(options.trigger) {
- trigger = $("<a/>").attr("href", "#").addClass(css.trigger).click(function(e) {
- self.show();
- return e.preventDefault();
- }).insertAfter(input);
- }
- // layout elements
- var weeks = root.find("#" + css.weeks);
- yearSelector = root.find("#" + css.year);
- monthSelector = root.find("#" + css.month);
- //{{{ pick
- function select(date, options, e) {
- if(!date) return;
- // current value
- value = date;
- currYear = date.getFullYear();
- currMonth = date.getMonth();
- currDay = date.getDate();
- if (e.type == "click" && $.browser && !$.browser.msie) {
- input.focus();
- }
- // select
- e = e || $.Event("api");
- e.type = "select";
- fire.trigger(e, [date]);
- if(e.isDefaultPrevented()) {
- return;
- }
- //如果选项有时间,则加上时间
- if(options.time) {
- var timeInput = root.find('input');
- var hour = parseInt(timeInput.eq(0).val(),10);
- var min = parseInt(timeInput.eq(1).val(),10);
- if(isNaN(hour)) {
- hour = 0;
- }
- if(isNaN(min)) {
- min = 0;
- }
- if(hour < 10) {
- hour = '0' + hour;
- }else if(hour < 0 || hour > 23) {
- hour = '00';
- }
- if(min < 10) {
- min = '0' + min;
- }else if(min < 0 || min > 59) {
- min = '00';
- }
- date.setHours(hour);
- date.setMinutes(min);
- }
- // formatting
- var date = format(date, options.format, options.lang);
- input.val(date);
- // store value into input
- input.data("date", date);
- //设置val后,IE导致触发focus事件,导致窗口关闭后再次被打开
- setTimeout(function() {
- self.hide(e);
- },100);
- }
- //}}}
- //{{{ onShow
- function onShow(ev) {
- ev.type = "onShow";
- fire.trigger(ev);
- //快捷键处理
- $(document).bind("keydown.d", function(e) {
- if(e.ctrlKey) {
- return true;
- }
- var key = e.keyCode;
- // backspace clears the value
- if(e.target == input[0]) {//如果是在当前input按back键,清除值并隐藏日历
- if(key == 8 || key == 46) {
- input.val("");
- return self.hide(e);
- }
- }
- // esc key
- if(key == 27) {
- return self.hide(e);
- }
- //如果有time,则不要快捷键
- if(options.time) {
- return;
- }
- if($(KEYS).index(key) >= 0) {
- if(!opened) {
- self.show(e);
- return e.preventDefault();
- }
- var days = $("#" + css.weeks + " a"), el = $("." + css.focus), index = days.index(el);
- el.removeClass(css.focus);
- if(key == 74 || key == 40) {
- index += 7;
- } else if(key == 75 || key == 38) {
- index -= 7;
- } else if(key == 76 || key == 39) {
- index += 1;
- } else if(key == 72 || key == 37) {
- index -= 1;
- }
- if(index > 41) {
- self.addMonth();
- el = $("#" + css.weeks + " a:eq(" + (index - 42) + ")");
- } else if(index < 0) {
- self.addMonth(-1);
- el = $("#" + css.weeks + " a:eq(" + (index + 42) + ")");
- } else {
- el = days.eq(index);
- }
- el.addClass(css.focus);
- return e.preventDefault();
- }
- // pageUp / pageDown
- if(key == 34) {
- return self.addMonth();
- }
- if(key == 33) {
- return self.addMonth(-1);
- }
- // home
- if(key == 36) {
- return self.today();
- }
- // enter
- if(key == 13) {
- if(!$(e.target).is("select")) {
- $("." + css.focus).dblclick();
- }
- }
- return $([16, 17, 18, 9]).index(key) >= 0;
- });
- // 点击外部关闭窗口
- /*$(document).bind("mousedown.d", function(e) {
- var el = e.target;
- if(!$(el).parents("#" + css.root).length && el != input[0] && (!trigger || el != trigger[0])) {
- self.hide(e);
- }
- });*/
- $(document.body).on("mousedown.d", function(e) {
- if(e.target !== input[0] && !$.contains(root[0],e.target)) {
- setTimeout(function(){
- self.hide();
- },100)
- }
- });
- }
- //}}}
- $.extend(self, {
- //{{{ show
- show : function(e) {
- if(input.prop("readonly") || input.prop("disabled") || opened) {
- return;
- }
- // onBeforeShow
- e = e || $.Event();
- e.type = "onBeforeShow";
- fire.trigger(e);
- if(e.isDefaultPrevented()) {
- return;
- }
- $.each(instances, function() {
- this.hide();
- });
- opened = true;
- // 月份下拉菜单
- monthSelector.unbind("change").change(function() {
- self.setValue(yearSelector.val(), $(this).val());
- });
- // 年下拉菜单
- yearSelector.unbind("change").change(function() {
- self.setValue($(this).val(), monthSelector.val());
- });
- // 上一月/下一月按钮
- pm = root.find("#" + css.prev).unbind("click").click(function(e) {
- if(!pm.hasClass(css.disabled)) {
- self.addMonth(-1);
- }
- return false;
- });
- nm = root.find("#" + css.next).unbind("click").click(function(e) {
- if(!nm.hasClass(css.disabled)) {
- self.addMonth();
- }
- return false;
- });
- // 设置日期
- self.setValue(value);
- //是否显示时间选择
- if(options.time) {
- root.find('div.caltime').show();
- }else{
- root.find('div.caltime').hide();
- }
- // show calendar
- var pos = input.offset();
- // iPad position fix
- if(/iPad/i.test(navigator.userAgent)) {
- pos.top -= $(window).scrollTop();
- }
- var top = pos.top + input.outerHeight() + options.offset[0];
- if(top + root.height() > $(window).scrollTop() + $(window).height()) {
- top = pos.top - root.height();
- }
- root.css({
- top : top,
- left : pos.left + options.offset[1]
- });
- if(options.speed) {
- root.show(options.speed, function() {
- onShow(e);
- });
- } else {
- root.show();
- onShow(e);
- }
- return self;
- },
- //}}}
- //{{{ setValue
- setValue : function(year, month, day, hour, minute) {
- var date = integer(month) >= -1 ? new Date(integer(year), integer(month), integer(day || 1)) : year || value;
- if(date < min) {
- date = min;
- } else if(date > max) {
- date = max;
- }
- year = date.getFullYear();
- month = date.getMonth();
- day = date.getDate();
- hour = date.getHours();
- minute = date.getMinutes();
- // roll year & month
- if(month == -1) {
- month = 11;
- year--;
- } else if(month == 12) {
- month = 0;
- year++;
- }
- if(!opened) {
- select(date, options);
- return self;
- }
- currMonth = month;
- currYear = year;
- // variables
- var tmp = new Date(year, month, 1 - options.firstDay), begin = tmp.getDay(), days = dayAm(year, month), prevDays = dayAm(year, month - 1), week;
- // selectors
- if(options.selectors) {
- // month selector
- monthSelector.empty();
- $.each(labels.months, function(i, m) {
- if(min < new Date(year, i + 1, -1) && max > new Date(year, i, 0)) {
- monthSelector.append($("<option/>").html(m).attr("value", i));
- }
- });
- // year selector
- yearSelector.empty();
- var yearNow = now.getFullYear();
- for(var i = yearNow + options.yearRange[0]; i < yearNow + options.yearRange[1]; i++) {
- if(min <= new Date(i + 1, -1, 1) && max > new Date(i, 0, 0)) {
- yearSelector.append($("<option/>").text(i));
- }
- }
- monthSelector.val(month);
- yearSelector.val(year);
- // title
- } else {
- title.html(labels.months[month] + " " + year);
- }
- // populate weeks
- weeks.empty();
- pm.add(nm).removeClass(css.disabled);
- // !begin === "sunday"
- for(var j = !begin ? -7 : 0, a, num; j < (!begin ? 35 : 42); j++) {
- a = $("<a/>");
- if(j % 7 === 0) {
- week = $("<div/>").addClass(css.week);
- weeks.append(week);
- }
- if(j < begin) {
- a.addClass(css.off);
- num = prevDays - begin + j + 1;
- date = new Date(year, month - 1, num);
- } else if(j >= begin + days) {
- a.addClass(css.off);
- num = j - days - begin + 1;
- date = new Date(year, month + 1, num);
- } else {
- num = j - begin + 1;
- date = new Date(year, month, num);
- // current date
- if(isSameDay(value, date)) {
- a.attr("id", css.current).addClass(css.focus);
- // today
- } else if(isSameDay(now, date)) {
- a.attr("id", css.today);
- }
- }
- // disabled
- if(min && date < min) {
- a.add(pm).addClass(css.disabled);
- }
- if(max && date > max) {
- a.add(nm).addClass(css.disabled);
- }
- a.attr("href", "#" + num).text(num).data("date", date);
- week.append(a);
- if(options.selectors) {
- //console.log(year, month, day, hour, minute)
- }
- }
- //时间选择
- //!TODO:chaoren1641增加,有待重构
- if(options.time) {
- //如果有时间选项则点击确定或双击日期输入时间
- // date picking
- weeks.find("a").on('click',function(e) {
- var el = $(this);
- if(!el.hasClass(css.disabled)) {
- $("#" + css.current).removeAttr("id");
- el.attr("id", css.current);
- }
- return false;
- }).off('dblclick').dblclick(function(e) {
- var el = $(this);
- if(!el.hasClass(css.disabled)) {
- select(el.data("date"), options, e);
- //在IE下,重新赋值会引起focus,导致日历控件再次激活打开,所以setTimeout下
- setTimeout(function() {
- self.hide();
- },100);
- }
- return false;
- });
- var body = root.find("#" + css.body);
- body.find('button').off('click.d').on('click.d',function(e) {
- var el = root.find('#' + css.current);
- select(el.data("date"), options, e);
- //在IE下,重新赋值会引起focus,导致日历控件再次激活打开,所以setTimeout下
- setTimeout(function() {
- self.hide();
- },100);
- return false;
- });
- body.find('#calHour').val(hour);
- body.find('#calMin').val(minute);
- }else{
- // date picking
- weeks.find("a").click(function(e) {
- var el = $(this);
- if(!el.hasClass(css.disabled)) {
- $("#" + css.current).removeAttr("id");
- el.attr("id", css.current);
- select(el.data("date"), options, e);
- }
- return false;
- })
- }
- // sunday
- if(css.sunday) {
- weeks.find(css.week).each(function() {
- var beg = options.firstDay ? 7 - options.firstDay : 0;
- $(this).children().slice(beg, beg + 1).addClass(css.sunday);
- });
- }
- return self;
- },
- //}}}
- setMin : function(val, fit) {
- min = parseDate(val);
- if(fit && value < min) {
- self.setValue(min);
- }
- return self;
- },
- setMax : function(val, fit) {
- max = parseDate(val);
- if(fit && value > max) {
- self.setValue(max);
- }
- return self;
- },
- today : function() {
- return self.setValue(now);
- },
- addDay : function(amount) {
- return this.setValue(currYear, currMonth, currDay + (amount || 1));
- },
- addMonth : function(amount) {
- return this.setValue(currYear, currMonth + (amount || 1), currDay);
- },
- addYear : function(amount) {
- return this.setValue(currYear + (amount || 1), currMonth, currDay);
- },
- hide : function(e) {
- if(opened) {
- // onHide
- e = $.Event();
- e.type = "onHide";
- fire.trigger(e);
- $(document).unbind("click.d").unbind("keydown.d");
- // cancelled ?
- if(e.isDefaultPrevented()) {
- return;
- }
- // do the hide
- root.hide();
- opened = false;
- }
- return self;
- },
- getConf : function() {
- return options;
- },
- getInput : function() {
- return input;
- },
- getCalendar : function() {
- return root;
- },
- getValue : function(dateFormat) {
- return dateFormat ? format(value, dateFormat, options.lang) : value;
- },
- isOpen : function() {
- return opened;
- }
- });
- // callbacks
- $.each(['onBeforeShow', 'onShow', 'select', 'onHide'], function(i, name) {
- // configuration
- if($.isFunction(options[name])) {
- $(self).bind(name, options[name]);
- }
- // API methods
- self[name] = function(fn) {
- if(fn) {
- $(self).bind(name, fn);
- }
- return self;
- };
- });
- // show dateinput & assign keyboard shortcuts
- input.bind("focus click", self.show).keydown(function(e) {
- var key = e.keyCode;
- // open dateinput with navigation keyw
- if(!opened && $(KEYS).index(key) >= 0) {
- self.show(e);
- return e.preventDefault();
- }
- // allow tab
- return e.shiftKey || e.ctrlKey || e.altKey || key == 9 ? true : e.preventDefault();
- });
- // initial value
- if(parseDate(input.val())) {
- //!TODO关闭初始化的值,这里会出现BUG
- //select(value, options);
- }
- };
- $.expr[':'].date = function(el) {
- var type = el.getAttribute("type");
- return type && type == 'date' || !!$(el).data("dateinput");
- };
- $.fn[pluginName] = function(options) {
- Wind.css('datePicker');
- return this.each(function() {
- if(!$.data(this, 'plugin_' + pluginName)) {
- var instance = new Plugin($(this), options);
- instances.push(instance);
- $.data(this, 'plugin_' + pluginName, instance);
- }
- });
- };
- /*$.fn.dateinput = function(conf) {
- // already instantiated
- if(this.data("dateinput")) {
- return this;
- }
- // configuration
- conf = $.extend(true, {}, tool.conf, conf);
- // CSS prefix
- $.each(conf.css, function(key, val) {
- if(!val && key != 'prefix') {
- conf.css[key] = (conf.css.prefix || '') + (val || key);
- }
- });
- var els;
- this.each(function() {
- var el = new Dateinput($(this), conf);
- instances.push(el);
- var input = el.getInput().data("dateinput", el);
- els = els ? els.add(input) : input;
- });
- return els ? els : this;
- };*/
- })(jQuery, window ,document);
|