jQuery日期选择器 - 鼠标悬停时获取日期

15

我正在使用这个jQuery日期选择器,并尝试在悬停时获取日期的值。 我看到插件有一个参数:

eventName 触发日期选择器所需的事件。 默认值:'click'

由于文档非常有限,我想知道除了点击之外是否还有其他选项,如果没有,如何使用eventName在悬停时获取日期的值。


你说的想在鼠标悬停时获取值是什么意思?你是想让日期选择器在鼠标悬停时出现吗? - Arun P Johny
如果用户点击了两个日期,我可以使用onChange回调函数获取所选日期范围,但我还想在用户滚动每个日期时实时更新日期。 - eozzy
2
为什么你不使用jQuery内置的日期选择器?这个看起来很丑。 - scrowler
eventName参数仅指定哪个事件将使日期选择器显示出来。默认值为“click”,这意味着当用户单击设置为日期选择器的文本框时,日历将显示出来。我没有看到任何返回特定事件上实际值的选项,我认为它需要点击来设置该值。 - Zack
请查看DatePicker脚本的第735行,它将单击事件绑定到DatePicker对象的click函数。我不确定是否可能,但您可以尝试修改插件本身,将“hover”绑定到click函数。 - Zack
显示剩余2条评论
9个回答

13

eventName选项仅用于将内部的show方法绑定到事件:

$(this).bind(options.eventName, show);

你理论上可以使用hover来显示日期选择器,但你需要为eventName选项指定'mouseenter mouseleave',因为hover是一个jQuery快捷方法,绑定到'mouseenter mouseleave'。由于你已经在评论中说明了你想要在kayak.co.in找到的行为,所以你只需在.DatePicker调用后链接一个mouseenter处理程序即可(不需要对其他任何内容进行更改):
$('#date').DatePicker({
    // options...
}).on('mouseenter', '.datepickerDays td:not(.datepickerDisabled, .datepickerNotInMonth)', function (e) { // delegating on the mouseenter event which jQuery patches to be a cross-browser event, and only targeting clickable dates
    var target = $(this).children('a'), // cache lookup
        options = target.parents('.datepicker').data('datepicker'), // get DatePicker options
        current = new Date(options.current), // grab the current month/year
        val = parseInt(target.text(), 10), // grab the target date
        hoverVal = new Date(current.getFullYear(), current.getMonth(), val), // make into an actual date
        hoverDay = hoverVal.getDayName(), // get the short day name
        hoverM = hoverVal.getMonth() + 1, // and month
        hoverD = hoverVal.getDate(), // and date
        hoverText = hoverDay + ' ' + (hoverD < 10 ? '0' + hoverD : hoverD) + '/' + hoverM, // for a formatted text value
        selectedVal = new Date(options.date[0]), // get the selected date (which may just be the initial date without an actual selection or an actual selected date, hereafter "selected")
        selectedDay = selectedVal.getDayName(), // get the short day name
        selectedM = selectedVal.getMonth() + 1, // and month
        selectedD = selectedVal.getDate(), // and date
        selText = selectedDay + ' ' + (selectedD < 10 ? '0' + selectedD : selectedD) + '/' + selectedM, // for a formatted text value
        startDate = $('#startDate').data('lastHovered') || new Date(hoverVal) || selectedVal, // default to: last hovered, current hover, or "selected" date (in that order)
        endDate = $('#endDate').data('lastHovered') || new Date(options.date[1]) || startDate, // default to: last hovered, actual selected date, or "selected" date (in that order)
        startDateSelected = $('#startDate').data('startDateSelected') || $('.datepickerDays .datepickerSelected.first').length > 0, // test whether an actual date was selected
        endDateSelected = !isNaN(options.date[1]) && (options.date[1] - options.date[0] > 86400000), // test whether an end date was selected. end date is set in options when start date is actually selected and is the same day as the selected start date but the time is set to 23:59:59
        selector; // variable to store a selector string
    // no end date has been selectd AND if no start date has been selected, or if it has and the user is hovering over an earlier date, or if the user hasn't selected a date yet
    if (!endDateSelected && (!startDateSelected || (startDateSelected && hoverVal < selectedVal) || hoverVal <= startDate)) {
        selector = '#startDate'; // use the startDate input
        $('#endDate').val(''); // since using startDate, endDate has not been selected. make sure the input is cleared.
    } else if (!endDateSelected){ // otherwise, as long as no end date has been selected
        selector = '#endDate'; // use the endDate input
        $('#startDate').val(selText); // and set the value of startDate back to the actual selected date value
    }
    if (!endDateSelected) { // if the user hasn't picked an end date (which cannot be picked without a start date)
        $(selector).data({ // persist the last hovered date and whether a start date has been selected
            "lastHovered": hoverVal,
            "startDateSelected": startDateSelected // this is necessary as the plugin routinely destroys and recreates the tables that make up the calendars while navigating the calendars
        }).val(hoverText); // set the value of the input to the hovered date
    }
});

工作演示:http://jsfiddle.net/QgXNn/5/


非常好,运行得很棒,只有一个小问题...如果我选择第一和第二个日期,第一个日期在悬停时停止更新。第二个日期仍然可以正常更新。 - eozzy

3
尝试这种方法:
创建一个Div用于你的悬停目标。
<div id="content">
    <div id="test">Hover Me</div>
    <div id="datePicker"></div>
</div>

就绪时,初始化并绑定悬停事件以打开

$(function () {
    $('#datePicker').datepicker();
    $('#datePicker').hide();

    $('#content').hover(function () {
        $('#datePicker').fadeIn('fast');
    }, function () {
        $('#datePicker').fadeOut('fast');
    });

});

Fiddle(无法引用您的选择器,所以我使用了JQuery UI)


更新:查看新的Fiddle

我将我的方法应用于您的Fiddle。现在,当您悬停在“Hover Me”上时,您的日期选择器会出现,并且光标离开时消失。我添加了:

$(function () {
    $('#date').hide();
    $('#test').hover(function () {
        $('#date').show();
    }, function () {
        $('#date').hide();
    });

});

顺便说一下,我让日期选择对话框在非悬停状态下消失只是为了效果。这很容易通过移除相邻的

来更改。
}, function () {
    $('#date').hide();

抱歉,我不能在这个阶段更改插件。我的fiddle链接:http://jsfiddle.net/iaezzy/QgXNn/ - eozzy
@Nimbuz,我并不是要建议你改变你的插件,只是希望应用相同的逻辑。我会查看你的fiddle。 - Dave Alperovich
@Nimbuz,我调整了你的Fiddle,使用了我的方法。我认为这就是你想要的。 - Dave Alperovich

3
请查看已编辑的示例代码,它是从您的代码派生而来的。
// setting the value of the input field to hovered date
// Note that we're not triggering the "click" event bec. 
// it will cause the onChange event of the datepicker to be fired. 
// Instead, we're setting and resetting the input field value 
$("body").on("mouseover", ".datepickerDays td", function (e) {
    var d = parseInt($(this).text(), 10),
        my = $(this).closest('table').find('.datepickerMonth span').html().split(', '),
        m = $.inArray(my[0], MONTH_NAMES),
        y = parseInt(my[1], 10),
        date = new Date(y, m, d),
        textbox = $('#startDate').hasClass('focus') ? $('#endDate') : $('#startDate');
    textbox.val(getFormattedDate(date));
});

// We set back the input field back to its original value on mouseout
$("body").on("mouseout", ".datepickerDays td", function (e) {
    var fd = $('#date').DatePickerGetDate(false),
        start = getFormattedDate(fd[0]),
        end = getFormattedDate(fd[1]);
    $('#startDate').val(start);
    $('#endDate').val(end);
});

// ----------------------------------------
// HELPER FUNCTIONS & VARS
// ----------------------------------------

var MONTH_NAMES = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
function pad0(num) { return num < 10 ? '0' + num : num; }
function getFormattedDate(date) {
    if (isNaN(date.getTime())) { return ''; }
    var wd = WEEKDAYS[date.getDay()].substr(0, 3);
    return wd + ' ' + pad0(date.getDate()) + '/' + pad0(date.getMonth() + 1);
}

哇,几乎完美,只有一个问题...我选择了一个日期范围,当我再次尝试选择日期范围时,它直接选择了结束日期。 - eozzy
我实际上并没有进行任何选择。我只是在鼠标悬停/移出时重置输入值。请检查您自己的fiddle。当您选择一个范围后,下一次点击将设置开始和结束日期。我的fork也是这样做的。您确定这段代码会导致这种情况吗? - Onur Yıldırım
@OnurYıldırım,请不要在你的答案中使用<kbd>标签来样式化链接。这些标签用于表示用户输入,而不是超链接。 - James Donnelly

1
针对你的问题,我猜测你不想在悬停时显示日期选择器,而是希望在悬停时在输入框中显示值或日期。 如果你想在悬停时显示日期选择器,请尝试使用插件的eventName属性中的“mouseover”。 像这样:
$('.inputDate').DatePicker({
    eventName:'mouseover', // This is the event to fire.
    format:'m/d/Y',
    date: $('#inputDate').val(),
    current: $('#inputDate').val(),
    starts: 1,
    position: 'right'});

它没有接收到hover的jquery事件。

现在,当悬停在日期选择器元素上时,在输入标签中显示新日期。您可能需要调整插件本身并尝试找到第734行的代码。

var cal = $(tpl.wrapper).attr('id', id).bind('click', click).data('datepicker', options);

将其改为


var cal = $(tpl.wrapper).attr('id', id).bind('mouseover', click).data('datepicker', options);

如您所见,我使用的是旧的mouseover事件而不是jQuery的'Hover'关键字。 如果此方法有效,您也可以尝试在插件中添加一个新的options参数,例如'callon:click',并在调用时设置此选项并将其传递到第734行。

var cal = $(tpl.wrapper).attr('id', id).bind(options.callon, click).data('datepicker', options);

使用它,您可以设置自己的事件来更新文本框的值。 它肯定适用于单个日期选择器。请尝试并对此发表评论。但是,您可能需要进行更多操作才能在单击时设置日期。

尝试过这个,但它似乎不能很好地与我想要的日期范围日历配合使用:http://jsfiddle.net/iaezzy/QgXNn/ - eozzy
我需要在鼠标悬停时更改输入字段中的日期。请参见 kayak.co.in .. 如果您将鼠标悬停在日期上,则会更新输入字段中的日期。 - eozzy
为什么不使用同样的JS呢? - SSS
啊,这是一个更好的插件,真希望我之前就知道了。 - eozzy
@Nimbuzz 希望你能得到一些关于它的帮助。享受吧。顺便说一下,这并不能给你完整的功能。但是如果你对它进行一些研究,可以从js中进行更改。 - SSS
显示剩余2条评论

1

由于插件已经绑定了click函数,我们可以通过为hover附加事件并简单地触发它来使用它。因此,代码如下:

function make_hover(){
    $(".datepickerDays td span").hover(function(e){
        $(this).trigger("click")
    })
    $(".datepickerDays td").mouseup(function(e){
        $('#inputDate').DatePickerHide(); //hide it when click actually occurs
    })
    $(".datepickerContainer").mouseup(function(e){
        setTimeout(function(){
          make_hover()
        },0) //have to run this with setTimeout to force it to run after DOM changes
    })
}

var date=$('#inputDate').DatePicker({
    format:'m/d/Y', 
    date: $('#inputDate').val(),
    current: $('#inputDate').val(),
    eventName: 'mouseenter',
    onBeforeShow: function(){
        $('#inputDate').DatePickerSetDate($('#inputDate').val(), true);
        make_hover()
    },
    onChange: function(formated, dates){
        $('#inputDate').val(formated);
        make_hover()
    }
})

{{链接1:示例}}


谢谢,它可以工作,但只有在更改到另一个月份的日历时,悬停功能就会停止工作。 - eozzy
插件不断改变DOM,因此我们需要不断运行make_hover。我想我已经为一个日历找到了解决方法,但修改你的fiddle使它有点不可预测。我会更新我的答案,但我会稍微研究一下你的fiddle。 - mfirdaus

0

通过使用jQuery和jQuery UI:

<div id="date_div">
     <input type="text" id="test" placeholder="Hover Me"/>
    <div id="datePicker"></div>
</div>

<script>
jQuery(function($) {
    $('#datePicker').datepicker({
       onSelect: function(dat){
          $('#test').val(dat);
       }
    });
    $('#datePicker').hide();

    $('#date_div').hover(function(){
         $('#datePicker').fadeIn(200);
    }, function() {
         $('#datePicker').fadeOut(200);
    });
});
</script>

查看演示 @: http://jsfiddle.net/renishar/ZVf48/4/

也要包括 jQuery 和 jQuery UI 库。


0

您可以在悬停日期元素时使用委托,如果需要,强制单击元素本身。

代码:

$("body").delegate(".datepickerDays td span","hover",function(e){
    $(this).click();
})

由于我无法让插件在更新的jQuery版本上工作,所以我必须使用{{link1:delegate}}。

演示:http://jsfiddle.net/IrvinDominin/fFc7h/


这个(delegate)是我需要添加的唯一代码块吗?因为它对我来说不起作用,还有其他我漏掉的更改吗? - eozzy
@Nimbuz,请检查一下这个fiddle,它是可以工作的;你使用的jQuery和插件版本是什么? - Irvin Dominin
@Nimbuz 我正在检查它。 - Irvin Dominin
@IrvinDomininakaEdward @Nimbuzz 当我使用jQuery 1.10.x插件时出现了故障。这就是为什么我使用1.3.x,但是经过调查发现,插件正在使用已在1.8中弃用的$.curCss。因此,使用1.7.x可以正常工作,而无需更改插件,它应该具有delegate甚至on。嗯。应该更新我的答案。 - mfirdaus
@Nimbuz 我必须知道你想做什么;插件在点击两个元素后会选择一个范围,第三次点击表示新的范围开始。这段代码中也是同样的情况:http://jsfiddle.net/IrvinDominin/zkKpY/ 因为悬停代表了一次点击。那么悬停时期望的效果是什么?始终扩大/缩小范围吗? - Irvin Dominin
@IrvinDomininakaEdward 不,点击部分没问题,但我需要输入框中的日期在悬停时更改。请参见http://www.kayak.co.in..如果您将鼠标悬停在日期上,则会在输入字段中更新。 - eozzy

0

使用eventName 'mouseover'代替'hover'


-1

根据我所看到的DatePicker插件提供的可选参数,该插件没有onHover函数。

但是,如果您有生成DatePicker的代码副本,实际上可以在插件中添加自己的jquery .hover()方法,以在鼠标进入元素/插件时触发。

这里是.hover()方法的文档。

http://api.jquery.com/hover/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接