Javascript 如何更改jQuery DatePicker控件的弹出位置

Javascript 如何更改jQuery DatePicker控件的弹出位置,javascript,jquery,jquery-ui,jquery-ui-datepicker,Javascript,Jquery,Jquery Ui,Jquery Ui Datepicker,你知道如何让DatePicker出现在相关文本框的末尾,而不是它的正下方吗?通常情况下,文本框位于页面底部,日期选择器向上移动以解释它,并完全覆盖文本框。如果用户想键入日期而不是选择日期,则不能。我更希望它出现在文本框的后面,这样它就不管如何垂直调整 你知道如何控制定位吗?我没有看到小部件的任何设置,也没有幸调整CSS设置,但我很容易遗漏了一些内容。这个问题的公认答案实际上不是针对jQuery UI日期选择器的。要更改jQueryUIDatePicker的位置,只需在css文件中修改.UIDat

你知道如何让DatePicker出现在相关文本框的末尾,而不是它的正下方吗?通常情况下,文本框位于页面底部,日期选择器向上移动以解释它,并完全覆盖文本框。如果用户想键入日期而不是选择日期,则不能。我更希望它出现在文本框的后面,这样它就不管如何垂直调整


你知道如何控制定位吗?我没有看到小部件的任何设置,也没有幸调整CSS设置,但我很容易遗漏了一些内容。

这个问题的公认答案实际上不是针对jQuery UI日期选择器的。要更改jQueryUIDatePicker的位置,只需在css文件中修改.UIDatePicker即可。日期选择器的大小也可以通过这种方式更改,只需调整字体大小。

以下是我使用的:

$('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索引,因此日历也显示在AJAX弹出窗口上方


我不修改jquery ui CSS文件;我在我的主CSS文件中重载了类,因此我可以更改主题或更新小部件,而无需重新输入我的特定MOD。

首先,我认为datepicker对象中应该有一个
afterShowing
方法,在jquery在
\u showDatepicker
方法中完成所有巫术后,可以更改位置。此外,还需要一个名为
preferedPosition
的参数,以便在对话框在视口外渲染时设置并修改它

做最后一件事有一个“诀窍”。如果研究
\u showDatepicker
方法,您将看到私有变量
$.datepikcer.\u pos
的使用。如果之前没有人设置过该变量,则将设置该变量。如果在显示对话框之前修改该变量,Jquery将获取该变量并尝试在该位置分配该对话框,如果它在屏幕外呈现,它将调整该变量以确保其可见。听起来不错,嗯

问题是<代码>\u 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
    }
});

但是要小心Jquery ui更新,因为
\u showDatepicker
的内部实现中的更改可能会破坏您的代码。

我需要根据无边界输入控件所在的父div来定位日期选择器。为此,我使用jQueryUICore中包含的“position”实用程序。我是在赛前活动中这样做的。正如上面其他人所评论的,您不能直接在beforeShow中设置位置,因为datepicker代码将在完成beforeShow函数后重置位置。要解决这个问题,只需使用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日历的变体

我认为这非常好,因为您可以通过jQueryUIPositionUtil控制定位

一个限制:jquery.ui.position.js是必需的

代码:


修复显示位置问题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);
}

使用日期选择器后绑定焦点 更改datepicker小部件的css 求救

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

还值得注意的是,如果IE陷入怪癖模式,那么jQueryUI组件和其他元素的位置将不正确

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

<!DOCTYPE html>


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

这将功能放入一个名为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函数,以便在返回offset之前将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中没有简单的实现来配置它,因为它似乎是一个fa日历总是会在页面下方的某个位置出现一个非常大的问题,与它所连接的输入相距甚远

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

jsFiddle:

HTML:

基本上,在每次datepicker“show”事件之前,我都会在头部附加一个新的样式标记(删除上一个,如果存在的话)。这种方法解决了我在开发过程中遇到的大部分问题

在Chrome、Firefox、Safari和IE>8上进行了测试(因为IE8不能很好地与JSFIDLE配合使用,而且我已经失去了关心它的兴趣) 我知道这是jQuery和javascript上下文的混合,但目前我不想将其转换为jQuery。这很简单,我知道。我现在已经完成了这项工作。希望其他人能从这个解决方案中受益。

这里是另一个解决方案
.ui-datepicker {-ms-transform: translate(100px,100px); -webkit-transform: translate(100px,100px); transform: translate(100px,100px);}
<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());
});
.ui-datepicker {-ms-transform: translate(100px,100px); -webkit-transform: translate(100px,100px); transform: translate(100px,100px);}
.ui-datepicker-trigger { 
margin-top:7px;
  margin-left: -30px;
  margin-bottom:0px;
  position:absolute;
  z-index:1000;
}
$.extend($.datepicker, { 
    _checkOffset: function(inst, offset, isFixed) { 
        return offset 
    } 
});
$('.datepicker2').click(function(){
    var popup =$(this).offset();
    var popupTop = popup.top - 40;
    $('.ui-datepicker').css({
      'top' : popupTop
     });
});
dateSelect.focus(function () {
    $("#ui-datepicker-div").position({
        my: "left top",
        at: "left bottom",
        of: $(this)
    });
});
$('.PDatePicker').MdPersianDateTimePicker({
                Placement: 'top',          
            });