Javascript UI日期选择器:选择日期将覆盖现有设置

Javascript UI日期选择器:选择日期将覆盖现有设置,javascript,jquery,jquery-ui-datepicker,Javascript,Jquery,Jquery Ui Datepicker,我正在尝试编写一个自定义日期选择器,其中月份和年份范围的默认下拉列表(通过changemount和changeYear选项启用)被自定义下拉列表替换。是这样的: $("#myId").datepicker($.extend({setDate: newDateString},oldSettings)) 小提琴: 在从自定义下拉列表中选择月份或年份时,我希望相应地更改视图中的日期。因此,我从当前月份和年份构造日期字符串(这里,新月份/年份组合的日期默认为1),然后调用 $("#custom-htm

我正在尝试编写一个自定义日期选择器,其中月份和年份范围的默认下拉列表(通过
changemount
changeYear
选项启用)被自定义下拉列表替换。是这样的:

$("#myId").datepicker($.extend({setDate: newDateString},oldSettings))
小提琴:

在从自定义下拉列表中选择月份或年份时,我希望相应地更改视图中的日期。因此,我从当前月份和年份构造日期字符串(这里,新月份/年份组合的日期默认为1),然后调用

$("#custom-html-block .custom-dropdown-option").on("click",function() {
     ...construct newDateString...
     $("#myId").datepicker("setDate",newDateString)
});

$("#another-custom-html-block .custom-dropdown-option").on("click",function() {
     ...construct newDateString...
     $("#myId").datepicker("setDate",newDateString)
});
我希望带有文本foo
span
在以编程方式单击新日期时保持不变


问题是:它会清除自定义下拉列表,而默认下拉列表会再次出现。我试着这样做:

$("#myId").datepicker($.extend({setDate: newDateString},oldSettings))

但它仍然不起作用。如何实现此功能?

您可以设置函数
$.datepicker.\u generateMonthYearHeader
的值,该函数的下半部将是页面中所有datepicker的全局值

样本如下:

$.datepicker._generateMonthYearHeader = function(inst, drawMonth, drawYear, minDate, maxDate,
        secondary, monthNames, monthNamesShort) {


    var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
        changeMonth = this._get(inst, "changeMonth"),
        changeYear = this._get(inst, "changeYear"),
        showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
        html = "<div class='ui-datepicker-title'>",
        monthHtml = "";

    // year selection
    if ( !inst.yearshtml ) {
        inst.yearshtml = "";
        if (secondary || !changeYear) {
            html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
        } else {
            // determine range of years to display
            years = this._get(inst, "yearRange").split(":");
            thisYear = new Date().getFullYear();
            determineYear = function(value) {
                var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
                    (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
                    parseInt(value, 10)));
                return (isNaN(year) ? thisYear : year);
            };
            year = determineYear(years[0]);
            endYear = Math.max(year, determineYear(years[1] || ""));
            year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
            endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
            inst.yearshtml += "<span class = 'dummy'>Foo</span> <select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"
            for (; year <= endYear; year++) {
                inst.yearshtml += "<option value='" + year + "'" +
                    (year === drawYear ? " selected='selected'" : "") +
                    ">" + year + "</option>";
            }
            inst.yearshtml += "</select>";


            html += inst.yearshtml;
            inst.yearshtml = null;
        }
    }
$.datepicker.\u generateMonthYearHeader=函数(inst、drawMonth、drawYear、minDate、maxDate、,
二级,monthNames,Monthnameshort){
年、月、年、今年、确定年、年、年终、,
changeMonth=此项(inst,“changeMonth”),
changeYear=此项(inst,“changeYear”),
showMonthAfterYear=这个。_get(inst,“showMonthAfterYear”),
html=“”,
monthHtml=“”;
//年份选择
如果(!inst.yearshtml){
inst.yearshtml=“”;
如果(二级| |!变更年){
html+=“”+drawYear+“”;
}否则{
//确定要显示的年份范围
年数=此值。_get(inst,“yearRange”).split(“:”);
thisYear=新日期().getFullYear();
DeterminationEAR=函数(值){
var year=(value.match(/c[+\-].*/)?drawYear+parseInt(value.substring(1),10):
(value.match(/[+\-].*/)?今年+parseInt(值,10):
parseInt(值,10));
申报表(isNaN(年度)?本年度:年度);
};
年=确定年(年[0]);
endYear=Math.max(year,determinateyear(years[1]| |“”);
year=(minDate?Math.max(year,minDate.getFullYear()):year);
endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);
inst.yearshtml+=“Foo”

对于(;year一般来说,这就是为什么extend很糟糕。家长(在你的例子中是datepicker)对childs(你的自定义html)一无所知。每次它刷新视图时,你的更改都会丢失。这个问题通常通过组合来解决。目标是创建你自己的小部件(我认为这是jQuery中的术语)将datepicker作为局部变量并控制_generateMonthYearHeader函数调用。理论上很容易说,但在实践中(特别是jQuery)很难实现。更简单的解决方案是代理函数

//preserve _generateHTML because after it finish, html is visible and .ui-datepicker-month and .ui-datepicker-year are in dom tree
fn = $.datepicker._generateHTML; //preserve original function
$.datepicker._generateHTML = function(inst) {
    //call original function
    fn.call(this, inst);
    //do custom changes
    //you'll need better selectors in case of multiple datepicker instances
    $(".ui-datepicker-month").replaceWith("#custom-html-block");
    $(".ui-datepicker-year").replaceWith("#another-custom-html-block");   
}
就我个人而言,我不喜欢这种方法(我更喜欢像我说的那样组合),但在你的例子中,它会更容易实现。其原因是generateMonthYearHeader是从许多不同的函数调用的


p.S.未经测试

您介意提供一个吗?嗯,这是一个庞大的代码,嵌入了大量css和html。如果我过滤掉它们,它将减少我在这里提供的两个内容:(选择日期是否也会导致下拉列表被重置?不,因为下拉列表是在关注文本输入时弹出的,所以当我单击日期时,它会消失。当我再次关注文本输入时,会弹出一个新实例和自定义下拉列表。因此,不,在选择日期时,直到它消失,我似乎不会替换它们。H不过,如果你试图通过左上角和右上角的按钮导航到上个月或下个月,新的月份就来了,下拉列表将更改为默认值。你为什么要从自定义下拉列表开始?你只是想对下拉列表的外观有更多的控制吗?就我所知,这很有魅力。只是编辑,哟你的代码没有改变日期,因为你忘了在
中包含文本foo。这是更新后的提琴:当然,我错过了那部分。我更新了答案,谢谢。但是我再次浏览了答案,它还照顾到了用户通过左上角和右上角的按钮浏览月份的部分。太棒了另外,你能给
if-else
条件添加更多的注释吗?这是从源代码中获取的。我用一个简化版本更新了答案。
//preserve _generateHTML because after it finish, html is visible and .ui-datepicker-month and .ui-datepicker-year are in dom tree
fn = $.datepicker._generateHTML; //preserve original function
$.datepicker._generateHTML = function(inst) {
    //call original function
    fn.call(this, inst);
    //do custom changes
    //you'll need better selectors in case of multiple datepicker instances
    $(".ui-datepicker-month").replaceWith("#custom-html-block");
    $(".ui-datepicker-year").replaceWith("#another-custom-html-block");   
}