JavaScript 日期选择器

来源:互联网 发布:mayo clinic知乎 编辑:程序博客网 时间:2024/05/22 00:30

效果图如下:



代码:

/** * Created by SharkMarine on 2017/10/31 */(function () {    var item_default;    var selectDate;    var selectNode;//选中的年月日用于滚动    var curMonthDayCount;//某年某月有多少天    var preTouch;    //==========立体效果参数============begin====    var ITEM_SPACE_Y = 40;//子项之间的y间距    var ITEM_SCALE_Y = 0.4;//scaleY    var ITEM_POS_X = 10;//x坐标的缩进    var ITEM_SKEW_X = 40;//倾斜度    var ITEM_OPACITY = 0.5;//透明度    //==========立体效果参数============begin====    DatePicker = cc.Layer.extend({        daySpace: 0,        jsBind: {            _event: {                updateGuildInfo: function (data) {                    var guildid = data.guildid;                    // 玩家被踢出群删除此界面                    if (guildid == jsclient.datepicker.guildid) {                        if (jsclient.datepicker) {                            jsclient.datepicker.removeFromParent(true);                            jsclient.datepicker = null;                        }                    }                }            },            block: {                _layout: [[1, 1], [0.5, 0.5], [0, 0], true]            },            back: {                _layout: [[911 / 1280, 0], [0.5, 0.45], [0, 0]],                close: {                    _click: function (btn) {                        selectNode = null;                        jsclient.datepicker.removeFromParent();                        delete jsclient.datepicker;                    }                },                btn_sure: {                    _click: function (btn) {                        if (jsclient.datepicker) {                            var pDestString = jsclient.datepicker.getSelectDate();                            // 把日期文字写到按钮上                            if (jsclient.datepicker.callback) {                                jsclient.datepicker.callback(pDestString);                            }                            jsclient.datepicker.removeFromParent();                            delete jsclient.datepicker;                        }                    }                },                item_default: {                    _visible: false,                    _run: function () {                        this.ignoreContentAdaptWithSize(true);                        item_default = this;                    }                },                Panel: {                    _run: function () {                        var children = this.getChildren();                        for (var i = 0; i < children.length; i++) {                            var pChild = children[i];                            if (pChild.getName() == "year" || pChild.getName() == "month" || pChild.getName() == "day") {                                pChild.addTouchEventListener(function (sender, type) {                                    switch (type) {                                        case ccui.Widget.TOUCH_BEGAN:                                        case ccui.Widget.TOUCH_MOVED:                                            selectNode = sender;                                            break;                                        case ccui.Widget.TOUCH_ENDED:                                        case ccui.Widget.TOUCH_CANCELED:                                            selectNode = null;                                            break;                                    }                                }, pChild);                            }                        }                    }                }            }        },        ctor: function (callback, guildid) {            this._super();            if (jsclient.datepicker) {                jsclient.datepicker.removeFromParent();            }            selectNode = null;            jsclient.datepicker = this;            jsclient.datepicker.guildid = guildid;            jsclient.datepicker.callback = callback;            var jNode = ccs.load("res/DatePicker.json");            jsclient.datepicker.jNode = jNode.node;            ConnectUI2Logic(jNode.node, this.jsBind);            this.addChild(jNode.node);        },        onEnter: function () {            this._super();            //this.scheduleUpdate();            cc.eventManager.addListener(jsclient.datepicker.getTouchListener(this), -1);            //初始化            this.initScrollItems();        },        initScrollItems: function () {            var Panel = getChildByNameOverWrite(this.jNode, "Panel");            var year = Panel.getChildByName("year");            var month = Panel.getChildByName("month");            var day = Panel.getChildByName("day");            initScrollItem(year);            initScrollItem(month);            initScrollItem(day);            selectDate = jsclient.datepicker.getCurrentDate();            function initScrollItem(target) {                var curDate = new Date();                var suffix;                var pName = target.getName();                var suffixIndex = -1;                var date;                switch (pName) {                    case "year":                        suffix = "年";                        suffixIndex = 0;                        date = curDate.getFullYear();                        break;                    case "month":                        suffix = "月";                        suffixIndex = 1;                        date = curDate.getMonth() + 1;                        break;                    case "day":                        suffix = "日";                        suffixIndex = 2;                        date = curDate.getDate();                        //date = jsclient.datepicker.getPreDate(-8);                        break;                }                // 刷新当前月的天数                if (suffixIndex == 2) {                    curMonthDayCount = jsclient.datepicker.getDayNumForMonth(curDate.getFullYear(),curDate.getMonth()+1);                }                var pSize = target.getContentSize();                //默认初始化8个元素                for (var i = 8; i >= 0; i--) {                    var pItem = item_default.clone();                    pItem.setName("item_" + i);                    var pText = pItem.getChildByName("text");                    var pTag = date + i - 4;                    pText.setString(date + i - 4 + suffix);                    // 验证 月 和 日的合法性,不能为负数                    if (suffixIndex == 1) {                        if (pTag > 12) {                            pTag = pTag % 12;                            pText.setString(pTag + suffix);                        }                        else if (pTag <= 0) {                            pTag = 12 - Math.abs(pTag);                            pText.setString(pTag + suffix);                        }                    }                    else if (suffixIndex == 2) {                        if (pTag > curMonthDayCount) {                            pTag = pTag % curMonthDayCount;                            pText.setString(pTag + suffix);                        }                        else if (pTag <= 0) {                            pTag = curMonthDayCount - Math.abs(pTag);                            pText.setString(pTag + suffix);                        }                    }                    pText.setTag(pTag);                    pItem.setTag(i);                    pItem.visible = true;                    pItem.setPositionY((i - 4) * ITEM_SPACE_Y + pSize.height / 2);                    jsclient.datepicker.setItemCommonAttribute(pSize, pItem, suffixIndex);                    if (i == 4) {                        pText.setColor(cc.color(146, 78, 42));                    }                    else {                        pText.setColor(cc.color(229, 211, 173));                    }                    target.addChild(pItem);                }            }        },        setItemCommonAttribute: function (pSize, pItem, suffixIndex) {            var topY = pSize.height + ITEM_SPACE_Y;            var bottomY = -ITEM_SPACE_Y;            var pText = pItem.getChildByName("text");            var delta = Math.abs(pItem.getPositionY() - pSize.height / 2) / (topY - pSize.height / 2);            pItem.setScaleY(1 - ITEM_SCALE_Y * delta);            pText.setOpacity(255 * (1 - ITEM_OPACITY * delta));            if (suffixIndex == 0) {                pText.setTextHorizontalAlignment(cc.TEXT_ALIGNMENT_LEFT);                pItem.setPositionX(pSize.width / 2 + ITEM_POS_X * delta);                pItem.setSkewX(-ITEM_SKEW_X / 2 + ITEM_SKEW_X * (pItem.getPositionY() - bottomY) / (topY - bottomY));            }            else if (suffixIndex == 1) {                pItem.setPositionX(pSize.width / 2);                pText.setTextHorizontalAlignment(cc.TEXT_ALIGNMENT_CENTER);            }            else if (suffixIndex == 2) {                pItem.setPositionX(pSize.width / 2 - (ITEM_POS_X) * delta);                pText.setTextHorizontalAlignment(cc.TEXT_ALIGNMENT_RIGHT);            }        },        adaptItems: function (target, spaceY, isEnd) {            if (!target) return;            var pSize = target.getContentSize();            var topY = pSize.height + ITEM_SPACE_Y;            var bottomY = -ITEM_SPACE_Y;            var children = target.getChildren();            var selectNode = null;            var suffix;            var pName = target.getName();            var suffixIndex = -1;            switch (pName) {                case "year":                    suffix = "年";                    suffixIndex = 0;                    break;                case "month":                    suffix = "月";                    suffixIndex = 1;                    break;                case "day":                    suffix = "日";                    suffixIndex = 2;                    break;            }            for (var i = children.length - 1; i >= 0; i--) {                var pItem = children[i];                var pText = pItem.getChildByName("text");                var targetPY = pItem.getPositionY() + spaceY;                if (targetPY > topY) {                    targetPY = (bottomY + (targetPY - topY));                    var preItem = target.getChildByTag(((pItem.getTag() + 1) % children.length));                    var pTextTag = preItem.getChildByName("text").getTag() - 1;                    if (suffixIndex == 1) {                        // 月份判断                        if (pTextTag == 0) {                            pTextTag = 12;                        }                    }                    else if (suffixIndex == 2) {                        if (pTextTag <= 0) {                            pTextTag = curMonthDayCount;                        }                    }                    pText.setString(pTextTag + suffix);                    pText.setTag(pTextTag);                }                else if (targetPY < bottomY) {                    targetPY = topY + (targetPY - bottomY);                    var preItem = target.getChildByTag((pItem.getTag() + children.length - 1) % children.length);                    var pTextTag = preItem.getChildByName("text").getTag() + 1;                    if (suffixIndex == 1) {                        // 月份判断                        if (pTextTag > 12) {                            pTextTag = 1;                        }                    }                    else if (suffixIndex == 2) {                        if (pTextTag > curMonthDayCount) {                            pTextTag = 1;                        }                    }                    pText.setString(pTextTag + suffix);                    pText.setTag(pTextTag);                }                pItem.setPositionY(targetPY);                if (isEnd == true) {                    if (!selectNode) {                        selectNode = pItem;                    }                    else {                        if (Math.abs(targetPY - pSize.height / 2) < Math.abs(selectNode.getPositionY() - pSize.height / 2)) {                            selectNode = pItem;                        }                    }                }                jsclient.datepicker.setItemCommonAttribute(pSize, pItem, suffixIndex);            }            if (isEnd && selectNode) {                var isMonthDayCountChanged = false;                var pSpaceY = pSize.height / 2 - selectNode.getPositionY();                // 设置色值                for (var i = 0; i < children.length; i++) {                    var pItem = children[i];                    var pText = pItem.getChildByName("text");                    if (pItem.getName() == selectNode.getName()) {                        pText.setColor(cc.color(146, 78, 42));                        // 更新选中的年月日                        selectDate[suffixIndex] = pText.getTag();                        //当年和月发生变化时刷新day的列表项                        if (suffixIndex < 2) {                            // 判断对应年月下对应的当月的天数                            var pMonthDayCount = curMonthDayCount;                            var curDate = new Date(selectDate[0], selectDate[1], 0);                            pMonthDayCount = jsclient.datepicker.getDayNumForMonth(curDate.getFullYear(), curDate.getMonth()+1);                            // 天数不一样                            if (pMonthDayCount != curMonthDayCount) {                                isMonthDayCountChanged = true;                                curMonthDayCount = pMonthDayCount;                            }                        }                    }                    else {                        pText.setColor(cc.color(229, 211, 173));                    }                }                // 改变年或月后,重置天数显示                if (suffixIndex < 2 && isMonthDayCountChanged) {                    var panelDay = getChildByNameOverWrite(target.getParent(), "day");                    var pDayChildren = panelDay.getChildren();                    var selectIndexForDay = null;                    for (var i = 0; i < pDayChildren.length; i++) {                        var pItem = pDayChildren[i];                        var pText = pItem.getChildByName("text");                        if (pText.getTag() == selectDate[2]) {                            selectIndexForDay = pItem.getTag();                            break;                        }                    }                    if (selectDate[2] > curMonthDayCount) {                        selectDate[2] = curMonthDayCount;                    }                    for (var i = 4; i >= -4; i--) {                        var pIndex = (9 + i + selectIndexForDay) % 9;                        var pItem = panelDay.getChildByTag(pIndex);                        //var pName =pItem.getName();                        var pText = pItem.getChildByName("text");                        var pTag = selectDate[2] + i;                        pText.setString(pTag + "日");                        if (pTag > curMonthDayCount) {                            pTag = pTag % curMonthDayCount;                        }                        else if (pTag <= 0) {                            pTag = curMonthDayCount - Math.abs(pTag);                        }                        pText.setString(pTag + "日");                        pText.setTag(pTag);                    }                }                this.adaptItems(target, pSpaceY);            }        },        getCurrentDate: function () {            var now = new Date();            var year = now.getFullYear();       //年            var month = now.getMonth() + 1;     //月            var day = now.getDate();            //日            var date = [year, month, day];            return date;        },        getDayNumForMonth: function (year, month) {            var curDate = new Date(year, month, 0);            return curDate.getDate();        },        _handlePressLogic: function (touch) {            this._startRecordSlidAction();            this._bePressed = true;        },        _handleMoveLogic: function (spaceY, selectNode) {            if (!selectNode) {                return;            }            this.adaptItems(selectNode, spaceY);        },        _handleReleaseLogic: function (touch) {            this._endRecordSlidAction();            this._bePressed = false;        },        _startRecordSlidAction: function () {            if (this._autoScroll)                this._stopAutoScrollChildren();            this._slidTime = 0.0;        },        _endRecordSlidAction: function () {            if (!this._checkNeedBounce() && this.inertiaScrollEnabled) {                if (this._slidTime <= 0.016)                    return;                var totalDis = 0, dir;                var touchEndPositionInNodeSpace = this.convertToNodeSpace(this._touchEndPosition);                var touchBeganPositionInNodeSpace = this.convertToNodeSpace(this._touchBeganPosition);                switch (this.direction) {                    case ccui.ScrollView.DIR_VERTICAL :                        totalDis = touchEndPositionInNodeSpace.y - touchBeganPositionInNodeSpace.y;                        dir = (totalDis < 0) ? ccui.ScrollView.SCROLLDIR_DOWN : ccui.ScrollView.SCROLLDIR_UP;                        break;                    case ccui.ScrollView.DIR_HORIZONTAL:                        totalDis = touchEndPositionInNodeSpace.x - touchBeganPositionInNodeSpace.x;                        dir = totalDis < 0 ? ccui.ScrollView.SCROLLDIR_LEFT : ccui.ScrollView.SCROLLDIR_RIGHT;                        break;                    case ccui.ScrollView.DIR_BOTH :                        var subVector = cc.pSub(touchEndPositionInNodeSpace, touchBeganPositionInNodeSpace);                        totalDis = cc.pLength(subVector);                        dir = cc.pNormalize(subVector);                        break;                    default:                        dir = cc.p(0, 0);                        break;                }                var orSpeed = Math.min(Math.abs(totalDis) / (this._slidTime), ccui.ScrollView.AUTO_SCROLL_MAX_SPEED);                this._startAutoScrollChildrenWithOriginalSpeed(dir, orSpeed, true, -1000);                this._slidTime = 0;            }        },        update: function (dt) {            if (this._autoScroll)                this._autoScrollChildren(dt);            if (this._bouncing)                this._bounceChildren(dt);            this._recordSlidTime(dt);        },        _stopAutoScrollChildren: function () {            this._autoScroll = false;            this._autoScrollOriginalSpeed = 0;            this._autoScrollAddUpTime = 0;        },        _recordSlidTime: function (dt) {            if (this._bePressed)                this._slidTime += dt;        },        _autoScrollChildren: function (dt) {            var lastTime = this._autoScrollAddUpTime;            this._autoScrollAddUpTime += dt;            if (this._isAutoScrollSpeedAttenuated) {                var nowSpeed = this._autoScrollOriginalSpeed + this._autoScrollAcceleration * this._autoScrollAddUpTime;                if (nowSpeed <= 0) {                    this._stopAutoScrollChildren();                    this._checkNeedBounce();                } else {                    var timeParam = lastTime * 2 + dt;                    var offset = (this._autoScrollOriginalSpeed + this._autoScrollAcceleration * timeParam * 0.5) * dt;                    var offsetX = offset * this._autoScrollDir.x;                    var offsetY = offset * this._autoScrollDir.y;                    if (!this._scrollChildren(offsetX, offsetY)) {                        this._stopAutoScrollChildren();                        this._checkNeedBounce();                    }                }            } else {                if (this._needCheckAutoScrollDestination) {                    var xOffset = this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed;                    var yOffset = this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed;                    var notDone = this._checkCustomScrollDestination(xOffset, yOffset);                    var scrollCheck = this._scrollChildren(xOffset, yOffset);                    if (!notDone || !scrollCheck) {                        this._stopAutoScrollChildren();                        this._checkNeedBounce();                    }                } else {                    if (!this._scrollChildren(this._autoScrollDir.x * dt * this._autoScrollOriginalSpeed,                            this._autoScrollDir.y * dt * this._autoScrollOriginalSpeed)) {                        this._stopAutoScrollChildren();                        this._checkNeedBounce();                    }                }            }        },        getTouchListener: function (target) {            return {                event: cc.EventListener.TOUCH_ONE_BY_ONE,                swallowTouches: false,                status: null,                onTouchBegan: function (touch, event) {                    if (item_default && jsclient.datepicker) {                        jsclient.datepicker._handlePressLogic(touch);                        preTouch = touch.getLocation();                    }                    return true;                },                onTouchMoved: function (touch, event) {                    if (selectNode && preTouch) {                        var spaceY = cc.pSub(touch.getLocation(), preTouch);                        preTouch = touch.getLocation();                        jsclient.datepicker.adaptItems(selectNode, spaceY.y);                    }                },                onTouchEnded: function (touch, event) {                    if (selectNode && preTouch) {                        var spaceY = cc.pSub(touch.getLocation(), preTouch);                        jsclient.datepicker.adaptItems(selectNode, spaceY.y, true);                        preTouch = null;                    }                },                onTouchCancelled: function (touch, event) {                }            };        },        getSelectDate: function () {            var isValidate = true;            if (isNaN(selectDate[0])) {                isValidate = false;            }            if (isNaN(selectDate[1]) || selectDate[1] > 12 || selectDate[1] < 1) {                isValidate = false;            }            if (isNaN(selectDate[2]) || selectDate[2] > curMonthDayCount || selectDate[2] < 1) {                isValidate = false;            }            if (!isValidate) {                selectDate = this.getCurrentDate();            }            // 拼字符串            var pDestString = "" + selectDate[0];            if (selectDate[1] < 10) {                pDestString += "0" + selectDate[1];            }            else {                pDestString += selectDate[1];            }            if (selectDate[2] < 10) {                pDestString += "0" + selectDate[2];            }            else {                pDestString += selectDate[2];            }            return pDestString;        }    });})();

注意问题:JavaScript的setMonth

如果使用不好会导致显示的日期不对,比如说2017-10-31,可能没有31日等。

问题原因:比如说curDate 为:2017-10-31

curDate.setMonth(curDate.getMonth() + 1);curMonthDayCount = jsclient.datepicker.getDayNumForMonth(curDate);
因为今天是10-31,
curDate.setMonth(curDate.getMonth() + 1);
后变为11-31,因为11月没有31号,所以日期变为12-1,导致月份直接+2。

最终导致以下方法获取的当前月的天数错误(实际上获取的是11月份的天数),同理setMonth(*,0);会导致直接跳转到上个月的最大天数,和setMonth(*,31);一样存在边界问题。

getDayNumForMonth: function (date) {    var curDate = new Date(date);    /* 获取当前月份 */    var curMonth = curDate.getMonth();    /*  生成实际的月份: 由于curMonth会比实际月份小1, 故需加1 */    curDate.setMonth(curMonth);    /* 将日期设置为0, 这里为什么要这样设置, 我不知道原因, 这是从网上学来的 */    curDate.setDate(0);    /* 返回当月的天数 */    return curDate.getDate();}