UI Datepicker:选择日期会覆盖现有设置

时间:2014-06-15 17:11:18

标签: javascript jquery jquery-ui-datepicker

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

小提琴:http://jsfiddle.net/gGV3v/

$("#myId").datepicker({
   ...default settings...
   beforeShow: function() {
      ...here I replace the default dropdowns by custom dropdowns...
      ...something like...
      $(".ui-datepicker-month").replaceWith("#custom-html-block");
      $(".ui-datepicker-year").replaceWith("#another-custom-html-block");
    }
 });

从自定义下拉列表中选择月份或年份时,我想相应地更改视图中的日期。所以我构建了当前月份和年份的日期字符串(新月/年组合的默认日期为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)
});

我希望span文字 foo 在点击它时以编程方式设置新日期时保持不变。


问题是:它消除了自定义下拉菜单,默认值下降了。我试着做这样的事情:

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

但它仍然无效。我如何使这项工作?

2 个答案:

答案 0 :(得分:1)

你可以设置函数$.datepicker._generateMonthYearHeader的值,它是页面中所有日期选择器全局的缺点。

样本如下:

$.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;
        }
    }

你的小提琴:http://jsfiddle.net/gGV3v/2/

<强>更新

没有按钮,并且使用更好的方法,现在您可以控制所有生成的HTML:

var oldGenerateHTML = $.datepicker._generateHTML;

function newGenerateHTML(inst) {
    var html = oldGenerateHTML.call(this, inst);
    var $html = $(html);
    $html.find('[data-handler=prev]').remove();
    $html.find('[data-handler=next]').remove();
    $html.find('[data-handler=selectMonth]').replaceWith('<span class="dummy">Foo</span>');
    return $html;
}

$.datepicker._generateHTML = newGenerateHTML;

小提琴也更新了:http://jsfiddle.net/gGV3v/4/

答案 1 :(得分:1)

一般来说,这就是为什么延伸很糟糕。父(在你的情况下是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。未经测试