JS制作簡單的日歷控件【JS Date對象操作實例演示】


JS制作簡單的日歷控件【JS Date對象操作實例】

一直對JS 中的Date 對象不是很熟練,缺乏操作實踐,端午節抽空復習了一下,做了一個簡單的日期選擇控件

日歷外觀參考了淘寶旅行中的日期控件,控件只有基本功能,木有做節日顯示:

2012年7月14日 增加了IE6的selectBUG,遮擋問題,修改了兩個日歷能夠同時出現的問題。

使用方法:

只需傳入日期INPUT元素的ID即可,isSelect選項為是否為SELECT下拉選擇年月設置

var myDate1 = new Calender({id:'j_Date1'});
var myDate2 = new Calender({id:'j_Date2',isSelect:!0});

演示如下:

日歷組件示例


支持選擇年月          支持SELECT選擇年月

          


 

 

 

 

 

有興趣的看源代碼吧,詳細源代碼+注釋如下:
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>日歷組件示例</title>
    <style>
        .calendar{font-family:Tahoma; background:#fff; float:left; border-style:solid; border-width:1px; border-color:#85BEE5 #3485C0 #3485C0 #85BEE5; position:relative; padding:10px; }
        .calendar dl,.calendar dd{margin:0; padding:0; width:183px; font-size:12px; line-height:22px;}
        .calendar dt.title-date{ display:block; border-bottom:1px solid #E4E4E4; font-weight:700; position:relative; margin-bottom:5px; padding-bottom:3px;}
        .calendar dt{ float:left; width:25px; margin-left:1px; text-align:center;}
        .calendar dt.title-date{ width:100%;}
        .calendar dd{clear: both;width: 183px;height: 139px;font-weight: 700;background:url(http://images.cnblogs.com/cnblogs_com/NNUF/379856/o_bg.png) no-repeat; margin:0;}
        .prevyear,.nextyear, .prevmonth,.nextmonth{cursor:pointer;height:9px; background:url(http://images.cnblogs.com/cnblogs_com/NNUF/379856/o_nextprv.png) no-repeat; overflow:hidden;position:absolute; top:8px; text-indent:-999px;}
        .prevyear{  left:4px;  width:9px;}
        .prevmonth{ width:5px; background-position:-9px 0; left:20px;}
        .nextyear{  width:9px; background-position:-19px 0; right:5px;}
        .nextmonth{ width:5px; background-position:-14px 0; right:20px;}
        .calendar dd a{float: left;width: 25px;height: 22px; color:blue; overflow: hidden; text-decoration: none;
            margin: 1px 0 0 1px; text-align:center;}
        .calendar dd a.disabled{color:#999;}
        .calendar dd a.tody{ color:red; }
        .calendar dd a.on{background:blue; color:#fff;}
        .calendar dd a.live{cursor:pointer}
        .input{ border:1px solid #ccc; padding:4px; background:url(http://images.cnblogs.com/cnblogs_com/NNUF/379856/o_nextprv.png) no-repeat right -18px;}
    </style>
</head>
<body>
<br/>
<br/>
<h3>支持選擇年月&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;支持SELECT選擇年月</h3>
<div><input type="text" id="j_Date1" class="input">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" id="j_Date2" class="input"></div>
<br/>
<select name="IE6" >
    <option>測試IE6</option>
    <option>2</option>
    <option>3</option>
</select>
<select name="IE6" >
    <option>測試IE6</option>
    <option>2</option>
    <option>3</option>
</select>
<select name="IE6">
    <option>測試IE6</option>
    <option>2</option>
    <option>3</option>
</select>
<select name="IE6" >
    <option>測試IE6</option>
    <option>2</option>
    <option>3</option>
</select>
<select name="IE6" >
    <option>測試IE6</option>
    <option>2</option>
    <option>3</option>
</select>
<select name="IE6">
    <option>測試IE6</option>
    <option>2</option>
    <option>3</option>
</select>
<div></div>
<!--日歷控件JS源碼-->
<script>
/**
 * @namespace _CalF
 * 日歷控件所用便捷函數
 * */
_CalF = {
    // 選擇元素
    $:function(arg,context){
        var tagAll,n,eles=[],i,sub = arg.substring(1);
        context = context||document;
        if(typeof arg =='string'){
            switch(arg.charAt(0)){
                case '#':
                    return document.getElementById(sub);
                    break;
                case '.':
                    if(context.getElementsByClassName) return context.getElementsByClassName(sub);
                    tagAll = _CalF.$('*',context);
                    n = tagAll.length;
                    for(i = 0;i<n;i++){
                        if(tagAll[i].className.indexOf(sub) > -1) eles.push(tagAll[i]);
                    }
                    return eles;
                    break;
                default:
                    return context.getElementsByTagName(arg);
                    break;
            }
        }
    },
    // 綁定事件
    bind:function(node,type,handler){
        node.addEventListener?node.addEventListener(type, handler, false):node.attachEvent('on'+ type, handler);
    },
    // 獲取元素位置
    getPos:function (node) {
        var scrollx = document.documentElement.scrollLeft || document.body.scrollLeft,
                scrollt = document.documentElement.scrollTop || document.body.scrollTop;
        pos = node.getBoundingClientRect();
        return {top:pos.top + scrollt, right:pos.right + scrollx, bottom:pos.bottom + scrollt, left:pos.left + scrollx }
    },
    // 添加樣式名
    addClass:function(c,node){
        node.className = node.className + ' ' + c;
    },
    // 移除樣式名
    removeClass:function(c,node){
        var reg = new RegExp("(^|\\s+)" + c + "(\\s+|$)","g");
        node.className = node.className.replace(reg, '');
    },
    // 阻止冒泡
    stopPropagation:function(event){
        event = event || window.event;
        event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true;
    }
};
/**
 * @name Calender
 * @constructor
 * @created by VVG
 * @http://www.cnblogs.com/NNUF/
 * @mysheller@163.com
 * */
function Calender() {
    this.initialize.apply(this, arguments);
}
Calender.prototype = {
    constructor:Calender,
    // 模板數組
    _template :[
        '<dl>',
        '<dt class="title-date">',
        '<span class="prevyear">prevyear</span><span class="prevmonth">prevmonth</span>',
        '<span class="nextyear">nextyear</span><span class="nextmonth">nextmonth</span>',
        '</dt>',
        '<dt><strong>日</strong></dt>',
        '<dt>一</dt>',
        '<dt>二</dt>',
        '<dt>三</dt>',
        '<dt>四</dt>',
        '<dt>五</dt>',
        '<dt><strong>六</strong></dt>',
        '<dd></dd>',
        '</dl>'],
    // 初始化對象
    initialize :function (options) {
        this.id = options.id; // input的ID
        this.input = _CalF.$('#'+ this.id); // 獲取INPUT元素
        this.isSelect = options.isSelect;   // 是否支持下拉SELECT選擇年月,默認不顯示
        this.inputEvent(); // input的事件綁定,獲取焦點事件
    },
    // 創建日期最外層盒子,並設置盒子的絕對定位
    createContainer:function(){
        // 如果存在,則移除整個日期層Container
        var odiv = _CalF.$('#'+ this.id + '-date');
        if(!!odiv) odiv.parentNode.removeChild(odiv);
        var container = this.container = document.createElement('div');
        container.id = this.id + '-date';
        container.style.position = "absolute";
        container.zIndex = 999;
        // 獲取input表單位置inputPos
        var input = _CalF.$('#' + this.id),
                inputPos = _CalF.getPos(input);
        // 根據input的位置設置container高度
        container.style.left = inputPos.left + 'px';
        container.style.top = inputPos.bottom - 1 + 'px';
        // 設置日期層上的單擊事件,僅供阻止冒泡,用途在日期層外單擊關閉日期層
        _CalF.bind(container, 'click', _CalF.stopPropagation);
        document.body.appendChild(container);
    },
    // 渲染日期
    drawDate:function (odate) { // 參數 odate 為日期對象格式
        var dateWarp, titleDate, dd, year, month, date, days, weekStart,i,l,ddHtml=[],textNode;
        var nowDate = new Date(),nowyear = nowDate.getFullYear(),nowmonth = nowDate.getMonth(),
                nowdate = nowDate.getDate();
        this.dateWarp = dateWarp = document.createElement('div');
        dateWarp.className = 'calendar';
        dateWarp.innerHTML = this._template.join('');
        this.year = year = odate.getFullYear();
        this.month = month = odate.getMonth()+1;
        this.date = date = odate.getDate();
        this.titleDate = titleDate = _CalF.$('.title-date', dateWarp)[0];
        // 是否顯示SELECT
        if(this.isSelect){
            var selectHtmls =[];
            selectHtmls.push('<select>');
            for(i = 2020;i>1970;i--){
                if(i != this.year){
                    selectHtmls.push('<option value ="'+ i +'">'+ i +'</option>');
                }else{
                    selectHtmls.push('<option value ="'+ i +'" selected>'+ i +'</option>');
                }
            }
            selectHtmls.push('</select>');
            selectHtmls.push('');
            selectHtmls.push('<select>');
            for(i = 1;i<13;i++){
                if(i != this.month){
                    selectHtmls.push('<option value ="'+ i +'">'+ i +'</option>');
                }else{
                    selectHtmls.push('<option value ="'+ i +'" selected>'+ i +'</option>');
                }
            }
            selectHtmls.push('</select>');
            selectHtmls.push('');
            titleDate.innerHTML = selectHtmls.join('');
            // 綁定change事件
            this.selectChange();
        }else{
            textNode = document.createTextNode(year + '' + month + '');
            titleDate.appendChild(textNode);
            this.btnEvent();
        }
        // 獲取模板中唯一的DD元素
        this.dd = dd = _CalF.$('dd',dateWarp)[0];
        // 獲取本月天數
        days = new Date(year, month, 0).getDate();
        // 獲取本月第一天是星期幾
        weekStart = new Date(year, month-1,1).getDay();
        // 開頭顯示空白段
        for (i = 0; i < weekStart; i++) {
            ddHtml.push('<a>&nbsp;</a>');
        }
        // 循環顯示日期
        for (i = 1; i <= days; i++) {
            if (year < nowyear) {
                ddHtml.push('<a class="live disabled">' + i + '</a>');
            } else if (year == nowyear) {
                if (month < nowmonth + 1) {
                    ddHtml.push('<a class="live disabled">' + i + '</a>');
                } else if (month == nowmonth + 1) {
                    if (i < nowdate) ddHtml.push('<a class="live disabled">' + i + '</a>');
                    if (i == nowdate) ddHtml.push('<a class="live tody">' + i + '</a>');
                    if (i > nowdate) ddHtml.push('<a class="live">' + i + '</a>');
                } else if (month > nowmonth + 1) {
                    ddHtml.push('<a class="live">' + i + '</a>');
                }
            } else if (year > nowyear) {
                ddHtml.push('<a class="live">' + i + '</a>');
            }
        }
        dd.innerHTML = ddHtml.join('');

        // 如果存在,則先移除
        this.removeDate();
        // 添加
        this.container.appendChild(dateWarp);

        //IE6 select遮罩
        var ie6  = !!window.ActiveXObject && !window.XMLHttpRequest;
        if(ie6) dateWarp.appendChild(this.createIframe());

        // A link事件綁定
        this.linkOn();
        // 區域外事件綁定
        this.outClick();
    },

    createIframe:function(){
        var myIframe =  document.createElement('iframe');
        myIframe.src = 'about:blank';
        myIframe.style.position = 'absolute';
        myIframe.style.zIndex = '-1';
        myIframe.style.left = '-1px';
        myIframe.style.top = 0;
        myIframe.style.border = 0;
        myIframe.style.filter = 'alpha(opacity= 0 )';
        myIframe.style.width = this.container.offsetWidth + 'px';
        myIframe.style.height = this.container.offsetHeight + 'px';
        return myIframe;

    },

    // SELECT CHANGE 事件
    selectChange:function(){
        var selects,yearSelect,monthSelect,that = this;
        selects = _CalF.$('select',this.titleDate);
        yearSelect = selects[0];
        monthSelect = selects[1];
        _CalF.bind(yearSelect, 'change',function(){
            var year = yearSelect.value;
            var month = monthSelect.value;
            that.drawDate(new Date(year, month-1, that.date));
        });
        _CalF.bind(monthSelect, 'change',function(){
            var year = yearSelect.value;
            var month = monthSelect.value;
            that.drawDate(new Date(year, month-1, that.date));
        })
    },
    // 移除日期DIV.calendar
    removeDate:function(){
        var odiv = _CalF.$('.calendar',this.container)[0];
        if(!!odiv) this.container.removeChild(odiv);
    },
    // 上一月,下一月按鈕事件
    btnEvent:function(){
        var prevyear = _CalF.$('.prevyear',this.dateWarp)[0],
                prevmonth = _CalF.$('.prevmonth',this.dateWarp)[0],
                nextyear = _CalF.$('.nextyear',this.dateWarp)[0],
                nextmonth = _CalF.$('.nextmonth',this.dateWarp)[0],
                that = this;
        prevyear.onclick = function(){
            var idate = new Date(that.year-1, that.month-1, that.date);
            that.drawDate(idate);
        };
        prevmonth.onclick = function(){
            var idate = new Date(that.year, that.month-2,that.date);
            that.drawDate(idate);
        };
        nextyear.onclick = function(){
            var idate = new Date(that.year + 1,that.month - 1, that.date);
            that.drawDate(idate);
        };
        nextmonth.onclick = function(){
            var idate = new Date(that.year , that.month, that.date);
            that.drawDate(idate);
        }
    },
    // A 的事件
    linkOn:function(){
        var links = _CalF.$('.live',this.dd),i,l=links.length,that=this;
        for(i = 0;i<l;i++){
            links[i].index = i;
            links[i].onmouseover = function(){
                _CalF.addClass("on",links[this.index]);
            };
            links[i].onmouseout = function(){
                _CalF.removeClass("on",links[this.index]);
            };
            links[i].onclick = function(){
                that.date = this.innerHTML;
                that.input.value = that.year + '-' + that.month + '-' + that.date;
                that.removeDate();
            }
        }
    },
    // 表單的事件
    inputEvent:function(){
        var that = this;
        _CalF.bind(this.input, 'focus',function(){
            that.createContainer();
            that.drawDate(new Date());
        });
    },
    // 鼠標在對象區域外點擊,移除日期層
    outClick:function(){
        var that = this;
        _CalF.bind(document, 'click',function(event){
            event = event || window.event;
            var target = event.target || event.srcElement;
            if(target == that.input)return;
            that.removeDate();
        })
    }
};
var myDate1 = new Calender({id:'j_Date1'});
var myDate2 = new Calender({id:'j_Date2',isSelect:!0});
</script>
</body>
</html>

轉載請注明出處:http://www.cnblogs.com/NNUF/



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM