How to change the pop-up position of the jQuery DatePicker control

有什么办法可以让 DatePicker 出现在相关文本框的末尾而不是直接出现在它的下面吗?通常会发生的情况是,文本框位于页面的底部,DatePicker 会向上移动,从而完全覆盖文本框。如果用户想键入日期而不是选择日期,那么他们就不能这样做。我宁愿它刚好出现在文本框之后,所以不管它如何垂直调整。

知道怎么控制位置吗?我没有看到小部件的任何设置,我也没有任何运气来调整 CSS 设置,但是我很容易遗漏一些东西。

284308 次浏览

这个问题的公认答案实际上并不适用于 jQueryUIDatepicker。要更改 jQueryUIDatepicker 的位置,只需修改。Css 文件中的 ui-datepicker。Datepicker 的大小也可以通过这种方式改变,只需调整字体大小即可。

Here's what I'm using:

$('input.date').datepicker({
beforeShow: function(input, inst) {
inst.dpDiv.css({
marginTop: -input.offsetHeight + 'px',
marginLeft: input.offsetWidth + 'px'
});
}
});

您可能还希望向左边距添加一些内容,这样它就不会正对输入字段。

我直接在 CSS 中完成:

.ui-datepicker {
margin-left: 100px;
z-index: 1000;
}

我的日期输入字段都是100px 宽。我还添加了 z-index,这样日历也会出现在 AJAX 弹出窗口的上方。

我没有修改 jquery-ui CSS 文件; 我在主 CSS 文件中重载了类,这样就可以更改主题或更新小部件,而不必重新输入特定的 mod。

First I think there should be a afterShowing method in the datepicker object, where you could change the position after jquery has done all its voodoo in the _showDatepicker method. Additionally, a parameter called preferedPosition would be also desirable, so you could set it and jquery modify it in case the dialog is rendered outside the viewport.

做这最后一件事有一个“诀窍”。如果您研究 _showDatepicker方法,您将看到一个私有变量 $.datepikcer._pos的使用。如果以前没有人设置过这个变量,那么它将被设置。如果在显示对话框之前修改了该变量,Jquery 将接受它,并尝试在该位置分配对话框,如果它在屏幕之外呈现,它将调整它以确保它是可见的。听起来不错吧?

问题是,_pos是私有的,但是如果你不介意的话,你可以:

$('input.date').datepicker({
beforeShow: function(input, inst)
{
$.datepicker._pos = $.datepicker._findPos(input); //this is the default position
$.datepicker._pos[0] = whatever; //left
$.datepicker._pos[1] = whatever; //top
}
});

But be careful of Jquery-ui updates, because a change in the internal implementation of the _showDatepicker might break your code.

我需要根据我的无边界输入控件所在的父 div 来定位数据采集器。为此,我使用了 jquery UI core 中包含的“ position”实用程序。我在 before Show 活动中做了这个。正如上面其他人所说的,您不能直接在 before Show 中设置位置,因为 datepicker 代码会在完成 before Show 函数之后重置位置。要解决这个问题,只需使用 setInterval 设置位置。当前脚本将完成,显示数据收集器,然后重新定位代码将在数据收集器可见后立即运行。虽然这种情况永远不会发生,但是如果在.5秒后数据收集器不可见,代码就有一个自动防故障装置来放弃并清除间隔。

        beforeShow: function(a, b) {
var cnt = 0;
var interval = setInterval(function() {
cnt++;
if (b.dpDiv.is(":visible")) {
var parent = b.input.closest("div");
b.dpDiv.position({ my: "left top", at: "left bottom", of: parent });
clearInterval(interval);
} else if (cnt > 50) {
clearInterval(interval);
}
}, 10);
}

下面是我对准 Datepicker 日历的变体。

我认为这是非常好的,因为您可以通过 jQueryUI 位置控制定位。

一个限制: 需要 jquery.ui.position. js。

密码:

$('input[name=date]').datepicker({
beforeShow: function(input, inst) {
// Handle calendar position before showing it.
// It's not supported by Datepicker itself (for now) so we need to use its internal variables.
var calendar = inst.dpDiv;


// Dirty hack, but we can't do anything without it (for now, in jQuery UI 1.8.20)
setTimeout(function() {
calendar.position({
my: 'right top',
at: 'right bottom',
collision: 'none',
of: input
});
}, 1);
}
})

修正显示位置问题 daterangepicker.jQuery.js

//Original Code
//show, hide, or toggle rangepicker
function showRP() {
if (rp.data('state') == 'closed') {
rp.data('state', 'open');
rp.fadeIn(300);
options.onOpen();
}
}




//Fixed
//show, hide, or toggle rangepicker
function showRP() {
rp.parent().css('left', rangeInput.offset().left);
rp.parent().css('top', rangeInput.offset().top + rangeInput.outerHeight());
if (rp.data('state') == 'closed') {
rp.data('state', 'open');
rp.fadeIn(300);
options.onOpen();
}
}

这对我有用:

beforeShow: function(input, inst) {
var $this = $(this);
var cal = inst.dpDiv;
var top = $this.offset().top + $this.outerHeight();
var left = $this.offset().left;


setTimeout(function() {
cal.css({
'top': top,
'left': left
});
}, 10);
}

bind focusin after using datepicker 更改数据采集器小部件的 css 希望能帮上忙

$('input.date').datepicker();
$('input.date').focusin(function(){
$('input.date').datepicker('widget').css({left:"-=127"});
});

同样值得注意的是,如果 IE 进入怪异模式,您的 jQueryUI 组件和其他元素的位置将不正确。

为了确保您不会陷入怪癖模式,请确保您正确地将 doctype 设置为最新的 HTML5。

<!DOCTYPE html>

使用过渡会把事情弄得一团糟。希望这会在将来为某人节省一些时间。

这将功能放入一个名为 function 的方法中,允许您的代码封装它,或者允许该方法生成一个 jquery 扩展。只是用在我的代码上,效果很好

var nOffsetTop  = /* whatever value, set from wherever */;
var nOffsetLeft = /* whatever value, set from wherever */;


$(input).datepicker
(
beforeShow : function(oInput, oInst)
{
AlterPostion(oInput, oInst, nOffsetTop, nOffsetLeft);
}
);


/* can be converted to extension, or whatever*/
var AlterPosition = function(oInput, oItst, nOffsetTop, nOffsetLeft)
{
var divContainer = oInst.dpDiv;
var oElem        = $(this);
oInput       = $(oInput);


setTimeout(function()
{
divContainer.css
({
top  : (nOffsetTop >= 0 ? "+=" + nOffsetTop : "-=" + (nOffsetTop * -1)),
left : (nOffsetTop >= 0 ? "+=" + nOffsetLeft : "-=" + (nOffsetLeft * -1))
});
}, 10);
}

在 Jquery.UI 中,只需更新 _ checkOffset 函数,以便在返回偏移量之前将 viewHeight 添加到 offset.top。

_checkOffset: function(inst, offset, isFixed) {
var dpWidth = inst.dpDiv.outerWidth(),
dpHeight = inst.dpDiv.outerHeight(),
inputWidth = inst.input ? inst.input.outerWidth() : 0,
inputHeight = inst.input ? inst.input.outerHeight() : 0,
viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : ($(document).scrollTop()||document.body.scrollTop));
offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? ($(document).scrollTop()||document.body.scrollTop) : 0;


// now check if datepicker is showing outside window viewport - move to a better place if so.
offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
Math.abs(offset.left + dpWidth - viewWidth) : 0);
offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
Math.abs(dpHeight + inputHeight) : 0);
**offset.top = offset.top + viewHeight;**
return offset;
},

一个非常简单的 jquery 函数。

$(".datepicker").focus(function(event){
var dim = $(this).offset();
$("#ui-datepicker-div").offset({
top     :   dim.top - 180,
left    :   dim.left + 150
});
});

我花了大量的时间试图解决这个问题,我正在开发的一个新网站的几个页面,似乎没有一个工作(包括上面提出的各种解决方案,我实施。我猜测 jQuery 已经改变了足够多的东西,因为他们被建议解决方案不再起作用。我不知道。说实话,我不明白为什么 jQuery ui 中没有一个简单的实现来配置这个,因为日历总是在页面的某个位置弹出,离它所附加的输入很远,这似乎是一个相当大的问题。

无论如何,我想要一个通用的最终解决方案,我可以在任何地方使用它,它会工作。我似乎最终得出了一个结论,避免了上面那些更复杂和特定于 jQuery 代码的答案:

http://jsfiddle.net/mu27tLen/

HTML:

<input type="text" class="datePicker" />

约翰逊:

positionDatePicker= function(cssToAdd) {
/* Remove previous positioner */
var oldScript= document.getElementById('datePickerPosition');
if(oldScript) oldScript.parentNode.removeChild(oldScript);
/* Create new positioner */
var newStyle= document.createElement("style");
newStyle.type= 'text/css';
newStyle.setAttribute('id', 'datePickerPostion');
if(newStyle.styleSheet) newStyle.styleSheet.cssText= cssToAdd;
else newStyle.appendChild(document.createTextNode(cssToAdd));
document.getElementsByTagName("head")[0].appendChild(newStyle);
}
jQuery(document).ready(function() {
/* Initialize date picker elements */
var dateInputs= jQuery('input.datePicker');
dateInputs.datepicker();
dateInputs.datepicker('option', {
'dateFormat' : 'mm/dd/yy',
'beforeShow' : function(input, inst) {
var bodyRect= document.body.getBoundingClientRect();
var rect= input.getBoundingClientRect();
positionDatePicker('.page #ui-datepicker-div{z-index:100 !important;top:' + (rect.top - bodyRect.top + input.offsetHeight + 2) + 'px !important;}');
}
}).datepicker('setDate', new Date());
});

Essentially I attach a new style tag to the head prior to every datepicker "show" event (deleting the previous one, if present). This method of doing things gets around a large majority of the issues that I ran into during development.

在 Chrome,Firefox,Safari 和 IE > 8上测试(IE8在 jsFiddle 上不能很好的工作,我已经失去了关心的热情

我知道这是 jQuery 和 javascript 上下文的混合,但是在这一点上,我只是不想把精力花在将它转换成 jQuery 上。很简单,我知道。我现在真的受够了。希望其他人能从这个解决方案中受益。

.ui-datepicker {-ms-transform: translate(100px,100px); -webkit-transform: translate(100px,100px); transform: translate(100px,100px);}

下面是另一个适合我的变化,调整 rect.top + 40,rect.left + 0以适应你的需要:

$(".datepicker").datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'mm/dd/yy',
beforeShow: function (input, inst) {
var rect = input.getBoundingClientRect();
setTimeout(function () {
inst.dpDiv.css({ top: rect.top + 40, left: rect.left + 0 });
}, 0);
}
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<form>
<input class="datepicker" name="date1" type="text">
<input class="datepicker" name="date2" type="text">
</form>

他们把类名改成了 ui-datepicker-trigger

So this works in jquery 1.11.x

.ui-datepicker-trigger {
margin-top:7px;
margin-left: -30px;
margin-bottom:0px;
position:absolute;
z-index:1000;
}

我从 ((如何控制 jQueryUI 数据采集器的定位))

$.extend($.datepicker, {
_checkOffset: function(inst, offset, isFixed) {
return offset
}
});

成功了! ! !

我用自定义的 jquery 代码修复了它。

  1. gave my datepicker input field a class "< em > . datepicker2 "

  2. 从上面找到它的当前位置

  3. positioned the popup box, which class name is "[ em > . ui-datepicker ]"

here is my code.

$('.datepicker2').click(function(){
var popup =$(this).offset();
var popupTop = popup.top - 40;
$('.ui-datepicker').css({
'top' : popupTop
});
});

在这里“40”是我期望的像素,你可以改变你的。

或者您可以在 dateSelect 对象上使用 focus 事件,并将 api 放在一起。您可以将顶部、底部和左边交换为右边或中心(或者您想从 api 位置得到的任何东西)。这样,您就不需要时间间隔或任何疯狂复杂的解决方案,并且您可以根据输入的位置来配置布局以满足您的需要。

dateSelect.focus(function () {
$("#ui-datepicker-div").position({
my: "left top",
at: "left bottom",
of: $(this)
});
});
$('.PDatePicker').MdPersianDateTimePicker({
Placement: 'top',
});

还有一个办法。

  1. 创建修复位置的函数

     function setDatepickerPos(input, inst) {
    var rect = input.getBoundingClientRect();
    // use 'setTimeout' to prevent effect overridden by other scripts
    setTimeout(function () {
    var scrollTop = $("body").scrollTop();
    inst.dpDiv.css({ top: rect.top + input.offsetHeight + scrollTop });
    }, 0);}
    
  2. 将函数添加到 datepicker 的‘ before Show’属性中

     $('#MyDatepicker').datepicker({
    dateFormat: "yy-mm-dd",
    changeMonth: true,
    changeYear: true,
    defaultDate: +0,
    inline: true,
    beforeShow: function (input, inst) { setDatepickerPos(input, inst) },});
    

这里是参考链接: 链接。所有的学分应该去 白羊座,我

如果拖动面板和面板中的数据采集器有滚动条。你必须用数据采集器的位置来计算所有的卷轴位置随间隔的变化。

$(function () {
var datePickerInterval;


$("#id").datepicker({
beforeShow: function (input, inst) {
var calendar = inst.dpDiv;
datePickerInterval = setInterval(function () {
calendar.position({
my: 'right top',
at: 'right bottom',
collision: 'none',
of: input
});
}, 10);
},
onClose: function () {
clearInterval(datePickerInterval);
}
});
});

这里的解决方案是: https://stackoverflow.com/a/10598178/19074969解决了我将数据采集器放置在日期输入字段的特定一侧的基本问题。但是,仍然需要定义一个偏移量来调整数据收集器弹出框的位置。这似乎可以很容易地通过将一些 CSS 样式转换转换应用到日期接收器 div 来实现:

setTimeout(function() {
jQuery("input[name='date']").datepicker({
beforeShow: function(input, inst) {
var calendar = inst.dpDiv;
setTimeout(function () {
calendar.position({
my: 'left bottom',
at: 'left top',
collision: 'none',
of: input
});
jQuery("#ui-datepicker-div").css('transform', 'translate( -40px, -10px )');
}, 0);
},
});
}, 800);

Problem is, if you click somewhere else, the datepicker box disappears and if you click on the date input field again, jQuery recalculates and updates the position of the datepicker div before opening it and the effect of the CSS 样式转换转换 is lost.

为了解决这个问题,我们需要在每次关闭数据收集器弹出框时将 css style transform translate重置为零。在下面的例子中,我们设置了一个变异观察器,比如: Javascript 在计算的 css 属性更改时检测,当数据采集器关闭时,CSS 样式属性“ display”变为“ none”,而 css style transform translate可以重新设置为零时,观察事件发生的情况:

if ( !window.document.documentMode ) {                                                  // would break IE11
setTimeout(function() {                                                              // after page is loaded, otherwise (input.hasDatepicker) would not be available
if ( jQuery("input.hasDatepicker").length > 0 ) {
var $observation_target = document.getElementById('ui-datepicker-div');
let style = window.getComputedStyle($observation_target);
var $mutation_observer = new MutationObserver(function(mutations){             // callback function
mutations.forEach(function(mutation){
if ( style.display === 'none' ) {
$observation_target.style.transform = 'translate( 0px, 0px )';
}
});
});
$mutation_observer.observe( $observation_target , {attributes:true} );         // Start the mutation observer (options: What is observed? CSS style attributes!)
}
}, 800);
}

在这两种情况下,都需要等待“ setTimeout”函数,直到页面加载完成,否则 input.hasDatepicker 将不存在并且无法找到。根据页面加载速度调整延迟(毫秒) ! 现在,它每次都能正常工作,并且数据采集器 div 的位置被调整为 之后,它由 jQuery 重新计算。

唯一的限制是: transform translate hack不能与 IE11一起工作。(经过测试,可以与 Edge 和 Firefox 一起工作!)