jQuery Datepicker:单击日期时防止关闭选择器

Posted

技术标签:

【中文标题】jQuery Datepicker:单击日期时防止关闭选择器【英文标题】:jQuery Datepicker: Prevent closing picker when clicking a date 【发布时间】:2010-11-18 03:50:19 【问题描述】:

大家好,***:ers,

我正在使用jQuery Datepicker plugin 和Martin Milesich Timepicker 插件。一切都很好,除了单击日期选择器中的日期会关闭小部件,没有时间选择时间。

问题:所以我想知道是否有办法阻止小部件在单击日期时关闭,而是强制用户单击“完成”按钮(启用“showButtonPanel:true”选项时会显示该按钮) ,或单击小部件外部。我不希望我的用户必须打开小部件两次!查看行为online at the timepicker demo

感谢任何解决此问题的帮助,甚至是正确方向的指针!

更多信息: 我正在使用 Martins 下载链接提供的文件:http://milesich.com/tpdemo/timepicker-0.2.0.zip

jquery-ui-1.7.2.custom.min.js timepicker.js(最新版本 0.2.0)

这些是我正在使用的选项:

$(document).ready(function()
    $(".datepicker").datepicker(
        duration: '',  
        showTime: true,  
        constrainInput: false,  
        stepMinutes: 5,  
        stepHours: 1, 
        time24h: true,
        dateFormat: "yy-mm-dd",
        buttonImage: '/static/images/datepicker.png',
        buttonImageOnly: true,
        firstDay: 1,
        monthNames: ['Januari','Februari','Mars','April','Maj','Juni','Juli','Augusti','September','Oktober','November','December'],
        showOn: 'both',
        showButtonPanel: true
     );
)

【问题讨论】:

快速说明,这个问题在当前版本的 TimePicker 插件中不再是问题。 @JamesMcGrath:谢谢,很高兴知道! @lucifer:对不起,没有。您使用 *** 错误。如果你有一个问题,写一个新的,尽可能多的信息。您可能会在几个小时内收到回复。 【参考方案1】:

最好使用现有事件,而不是更改源

onSelect: function() 
    $(this).data('datepicker').inline = true;                               
,
onClose: function() 
    $(this).data('datepicker').inline = false;

【讨论】:

这是一个更好的解决方案。注意:如果您启用了showButtonPanel: true,这将删除“完成”按钮。还没有想出如何阻止这种行为。 非常感谢。这是完美的解决方案。 @PhilMoorhouse 有点晚了,但也许仍然可以帮助某人:在 jquery-ui 中,你会找到一个 _generatehtml 函数,如果实例有 inline: true,它不会添加“完成”按钮放。您可以在那里搜索唯一出现的 ui-datepicker-close 并摆脱这种行为。 @Min Hur:这有点好用,但是如果日期选择器上有一个按钮,那么如果使用此代码,它将不会保持可见。请您告诉如何在选择日期时防止关闭日期选择器并防止其上的按钮。 当您使用 js 进行一些自定义样式时,此解决方案并不好,因为它会重新初始化 datepicker 弹出窗口。 $(this).data('datepicker').inline = true; 之后所有的更改都消失了;【参考方案2】:

供参考,因为人们通过邮件问过我这个问题。这是需要添加到 timepicker.js 中的代码块:

/**
 * Don't hide the date picker when clicking a date
 */
$.datepicker._selectDateOverload = $.datepicker._selectDate;
$.datepicker._selectDate = function(id, dateStr) 
    var target = $(id);
    var inst = this._getInst(target[0]);
    inst.inline = true;
    $.datepicker._selectDateOverload(id, dateStr);
    inst.inline = false;
    this._updateDatepicker(inst);

祝你好运!

【讨论】:

+1 一个老问题,但仍然有效!感谢您添加此参考。 @zaf:感谢您回复我并投票:) 这可行,但在选择日期时会滚动到屏幕顶部……至少在 Chrome 中是这样。 给我这个错误:Uncaught RangeError: Maximum call stack size exceeded @OmidHezaveh:您可能没有正确复制内容。请注意名称 _selectDateOverload 和 _selectDate。它们需要不同。【参考方案3】:

您必须自己破解日期选择器。这是它使用的代码。如果它不是内联的,它将在您选择日期时隐藏。

您可以传入自己的 onSelect 方法并快速将 datePicker 实例更改为内联,然后将其改回而无需更改 datepicker 内部结构,但这是一个非常老套的解决方案。

if (inst.inline)
        this._updateDatepicker(inst);
else 
      this._hideDatepicker(null, this._get(inst, 'duration'));
      this._lastInput = inst.input[0];
      if (typeof(inst.input[0]) != 'object')
      inst.input[0].focus(); // restore focus
      this._lastInput = null;

【讨论】:

非常感谢 redsquare,您的回复让我朝着正确的方向前进。似乎 onSelect 仅在选择日期时触发,因此只需在 select 上的实例上调用 show() 即可获得我想要的行为。 ... onSelect: function(dateText, inst) inst.show(); 不,我的错。上面抛出了一个错误,这似乎阻止了选择器隐藏。我仍然无法让您的建议发挥作用。如果我把它变成“内联”,完成按钮就会消失,除了点击它之外没有其他方法可以关闭窗口。我尝试设置超时并将内联模式重置为无效。 好的,我找到了第二种方法来做我想做的事。实际上可以使用自定义方法覆盖 _selectDate 方法,您在上面提供的代码来自哪里。该方法包含与原始文件中完全相同的代码,但没有“_hideDatepicker”行。简单,而且相当老套,但它确实有效。 很高兴你对它进行了排序,埃米尔。祝你好运【参考方案4】:

这是一个解决方案:

onSelect: function ( dateText, inst ) 
    ..... // Your code like $(this).val( dateText );`


    //Set inline to true to force "no close"
    inst.inline = true;
,
onClose: function(date,inst)
    //Set inline to false => datapicker is closed
    // onClose is called only if you click outside the datapicker, onSelect will not
    // trig onClose due to inline = true
   inst.inline = false;

`

【讨论】:

【参考方案5】:

为什么所有 cmets 都提供解决方法?它是直字:

使用带有 altField 的内联日历 :)

    <input type="text" id="alternate" size="30" />
    <div id="datepicker"></div>

    <script>
       $("#datepicker").datepicker(
          altField: "#alternate"
       );
    </script>

检查这个小提琴: http://jsfiddle.net/menocomp/y2s662b0/1/

【讨论】:

【参考方案6】:

酷,如果你使用 jquery-ui-1.8.5.custom.min.js 和 jquery-ui.multidatepicker.js,你可以修改 jquery-ui-1.8.5.custom.min.js: 来自:

if(a.inline)this._updateDatepicker(a);

进入:

if(a.inline || !this._get(a, 'closeOnSelect'))this._updateDatepicker(a);

【讨论】:

【参考方案7】:

这是一个肮脏的解决方法......但它对我有用......即使使用 showButtonPanel: true

  $(function() 
    var dp_c = null, dp_once = false;
    $( '#datepicker' ).datepicker(
      showButtonPanel: true,
      onSelect: function() 
        $(this).data('datepicker').inline = true;  
        setTimeout(function () 
          $('#ui-datepicker-div').find('.ui-datepicker-buttonpane').append(dp_c);
        , 1);

      ,
      onClose: function() 
        $(this).data('datepicker').inline = false;
      
    ).click(function () 
      if(!dp_once) 
        setTimeout(function () 
          dp_c = $('#ui-datepicker-div').find('.ui-datepicker-close').clone();
        , 500);
        dp_once = !!1;
      
    );

    $('#ui-datepicker-div').on('click', '.ui-datepicker-close', function () 
      $('#datepicker').datepicker( "hide" );
    );

  );

【讨论】:

【参考方案8】:

你应该重写原生 js 函数:

 /* Update the input field with the selected date. */
        _selectDate: function(id, dateStr) 
            var target = $(id);
            var inst = this._getInst(target[0]);
            dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
            if (inst.input)
                inst.input.val(dateStr);
            this._updateAlternate(inst);
            var onSelect = this._get(inst, 'onSelect');
            if (onSelect)
                onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
            else if (inst.input)
                inst.input.trigger('change'); // fire the change event
            if (inst.inline)
                this._updateDatepicker(inst);
            else 
                if(inst.settings.hideOnSelect != false)
                    this._hideDatepicker();
                
                this._lastInput = inst.input[0];
                if (typeof(inst.input[0]) != 'object')
                    inst.input.focus(); // restore focus
                this._lastInput = null;
            
        ,

并为 datepicker 配置添加适当的选项,例如:

var defaultDatePickerOptions = 
        hideOnSelect: false,
        ...
    ; 
 var birthDate = jQuery.extend(, defaultDatePickerOptions);
 $('#birthdate').datepicker(birthDate);

【讨论】:

【参考方案9】:

按照 Emil 的建议,我找到了一种更好、更简单的方法来修改小部件以支持在选择事件时不关闭小部件。

首先,我在小部件的默认字典中添加了另一个属性:

closeOnSelect:true //True to close the widget when you select a date

其次,在_selectDate方法中找到这条语句:

if (inst.inline)
        this._updateDatepicker(inst);
else 
        ...
    

然后把条件改成这样:

var closeOnSelect = this._get(inst, "closeOnSelect");        
if (inst.inline || !closeOnSelect)
        this._updateDatepicker(inst);
else 
        ...
    

试一试,它对我有用。我是在 JQuery UI 1.8.5 版本上完成的。

【讨论】:

以上是关于jQuery Datepicker:单击日期时防止关闭选择器的主要内容,如果未能解决你的问题,请参考以下文章

单击链接时,Jquery UI Datepicker 不再显示

如何在按钮单击并插入跨度标记时显示 jquery datepicker

jQuery DatePicker:点击今天然后完成时,不保留今天的日期

jQuery Datepicker - 悬停时获取日期

是否可以在输入单击和按钮上触发 jQuery datepicker 元素?

如果超出范围,防止 jQuery UI datepicker 更改文本字段的值