【问题标题】:How to control positioning of jQueryUI datepicker如何控制 jQueryUI 日期选择器的定位
【发布时间】:2010-12-21 13:53:45
【问题描述】:

jQueryUI 中的日期选择器以动态位置呈现。如果有足够的空间,它会根据它的 css 进行渲染,但如果没有足够的窗口空间,它会尝试在屏幕上渲染。我需要它每次都保持原样并在同一个地方渲染,与屏幕位置或其他情况无关。 jQueryUI 日期选择器如何做到这一点? jQuery datepicker 的其他实现似乎有这样做的方法,但我没有看到 UI 版本的方法。

答案似乎不只是修改css:

.ui-datepicker { width: 17em; padding: .2em .2em 0; (trying top/margin-top/position:relative, etc. here...)}

...自从创建日期选择器后,它会动态创建元素样式的顶部和左侧。还没有找到解决这个问题的方法。我看到的一种方法是在 beforeShow 选项中给出类似的内容:

beforeShow: function(input,inst){
                                inst.dpDiv.css({ 
                                   'top': input.offsetHeight+ 'px', 
                                   'left':(input.offsetWidth - input.width)+ 'px'
                                               });
                                }

这有一些效果,但在日期选择器呈现时运行后,top 和 left 属性仍会动态设置。它仍在尝试在屏幕上渲染。如何让它始终在同一个位置渲染?我的下一步可能是进入 datepicker 的胆量并开始把东西拉出来。有什么想法吗?

请注意,答案(针对 UI 版本)不在:

【问题讨论】:

    标签: jquery jquery-ui datepicker uidatepicker


    【解决方案1】:

    发布此内容希望对其他人有所帮助。至少从 datepicker 的 v1.8.1 开始,使用 'window.DP_jQuery.datepicker' 不再有效,因为指针(正确的术语?)现在以其创建的时间戳命名 - 例如,它现在将是 'window. DP_jQuery_1273700460448'。所以现在,不要使用指向 datepicker 对象的指针,而是像这样直接引用它:

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

    非常感谢下面的回答让我得到了我需要的东西。

    【讨论】:

    • 没有问题 - 我很高兴其他人从中得到了一些东西,我记得花了一两个小时来解决这个问题。
    • 不错,对我很有帮助!对于任何需要它的人,您可以像这样更改日期选择器的边距: .ui-datepicker { margin-left: -361px; }
    • eeehh,也许是一个愚蠢的问题,但是如何使用它呢?在演出前?
    • 像魅力一样工作。 @JilcoTigchelaar 我只是让函数返回一个固定的偏移量。 $.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){offset.top = 80; offset.left=180; return offset;}});
    • @mutanic - $(document).ready(function () {把行放在这里});
    【解决方案2】:

    编辑: JaredC 为上述 jQuery 的更高版本提供了更新的答案。切换接受的答案。

    好的,这是一个猴子补丁的问题,它尝试始终在视口中渲染,因为没有提供启用/禁用该功能的选项。幸运的是,它在一个函数中解耦和隔离,因此我们可以进入并覆盖它。以下代码仅完全禁用该功能:

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

    _checkOffset 在打开时被调用,它计算偏移量并返回一个新的偏移量,否则它会在视口之外。这将替换函数体以直接传递原始偏移量。然后,您可以使用 beforeShow 设置技巧和/或 .ui-datepicker css 类将其放置在您想要的任何位置。

    【讨论】:

      【解决方案3】:

      使用日期选择器后绑定焦点 更改 datepicker 小部件的 css 希望得到帮助

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

      【讨论】:

      • 当您已经看到已接受的答案时,再次回答的意义何在。无论如何,欢迎来到 SO! :)
      • 展示如何在没有“黑客”的情况下做到这一点总是一件好事。已接受的解决方案(覆盖 datepicker 的内部“私有”逻辑) 可能会在每个新版本的 jquery.ui 中破坏该修复。看着接受的答案,在我看来实际上就是这样......
      【解决方案4】:

      使用 jQuery:

      beforeShow : function(input,inst){
          var offset = $(input).offset();
          var height = $(input).height();
          window.setTimeout(function () {
              $(inst.dpDiv).css({ top: (offset.top + height) + 'px', left:offset.left + 'px' })
          }, 1);
      }
      

      【讨论】:

      • 我发现这对最新的 jQuery UI 版本最有用
      【解决方案5】:

      我遇到的问题是日期选择器在固定元素中的位置不正确,例如花式/灯箱。出于某种原因,当发生这种情况时,日期选择器会切换到“固定”定位模式,然后偏移量计算会变得不正确,而绝对定位本来可以正常工作。

      但是,我们可以通过这个 hack 获得正确的固定位置:

      const checkOffset = $.datepicker._checkOffset;
      
      $.extend($.datepicker, {
          _checkOffset: function(inst, offset, isFixed) {
              if(!isFixed) {
                  return checkOffset.apply(this, arguments);
              }
      
              let isRTL = this._get(inst, "isRTL");
              let obj = inst.input[0];
      
              while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
                  obj = obj[isRTL ? "previousSibling" : "nextSibling"];
              }
      
              let rect = obj.getBoundingClientRect();
      
              return {
                  top: rect.top,
                  left: rect.left,
              };
          }
      });
      

      【讨论】:

      • 有趣。但是我怎样才能只在特定的日期选择器上使用它呢?它似乎不适用于标准 DP,仅适用于我的情况下包含在对话框中的那些。
      • @SchweizerSchoggi 不确定。如果您可以获得 datepicker 对象的实例,则可能只能覆盖该实例的 _checkOffset。哦,但是这段代码确实会检查日期选择器是否“固定”,也许您可​​以调整该逻辑以满足您的需求。
      • 我已经使用了您的解决方案,但在 rect.top 返回值中添加了 + inst.input[0].clientHeight!。谢谢
      【解决方案6】:

      在你的css文件中,例如:

      #ui-datepicker-div {
        position: absolute !important;
        top: auto !important;
        left: auto !important;
      }
      

      您的重要设置,无论它们是什么,都将覆盖内联默认值。

      【讨论】:

      • @hcharge 实际上,如果您在 CSS 样式中使用 !important,它们不会。只有具有 !important 的内联样式才能覆盖来自 CSS 的 !important - jsfiddle.net/NTCP7
      • 虽然!important 有点像不得已的 CSS hack,但此解决方案运行良好且最容易实现。
      • 这个答案对于将日期选择器日历小部件定位在绝对位置的非常具体的问题是正确的。关于更笼统的标题“如何控制 jQueryUI 日期选择器的定位?”的答案是不正确的
      【解决方案7】:

      之前我尝试在 datepicker.js 的 beforeShow 事件中给出 top,left,它被 jquery-ui-custom.js 的 _showDatePicker 方法覆盖。 但是在窗口超时后它工作正常。下面是代码

      beforeShow : function(input,inst) {
        var offset = js.select("#" + dpId).offset();
                              var height = js.select("#" + dpId).height();
                              var width = js.select("#" + dpId).width();
                              window.setTimeout(function () {
                                    js.select(inst.dpDiv).css({ top: (offset.top + height - 185) + 'px', left: (offset.left + width + 50) + 'px' })
                              }, 1);
      }
      

      【讨论】:

      • 这个解决方案只不过是一个 hack。虽然它通常可以工作,但您可能会注意到 datepicker 小部件上的一种“跳跃”,尤其是当 datepicker 生成的位置远离您的“被黑”位置时。这当然只是次要的,因为您的解决方案可能根本无法在“慢”计算机上运行。
      【解决方案8】:

      这是一个相当古老的问题,但是我最近在使用 jQuery UI Datepicker 时遇到了与此类似的问题。我们已经在使用上面@JaredC 发布的解决方案(特别是此代码 sn-p:$.extend($.datepicker,{_checkOffset:function(inst,offset,isFixed){return offset}});),但是它不适用于具有我们需要在其中呈现下拉菜单的输入的模式。

      这个问题会发生,因为当向下滚动页面时,模式中输入的偏移量相对于滚动页面的顶部发生了变化。由此产生的行为意味着日期选择器将呈现在不同的垂直位置,具体取决于您向下滚动页面的距离(注意:虽然日期选择器可见和滚动已经固定)。这个问题的解决方案(“嵌套在模式中的 datepicker 输入”)是计算输入相对于视图屏幕的垂直定位,然后添加输入的高度(允许 datepicker 的“top”css 属性在输入的正下方)。

      下面的 sn-p 在coffeescript 中。我们不是根据@JaredC 的解决方案返回常规偏移量,而是从“inst”对象获取输入的 elementId,然后通过 jquery 访问该对象,以便使用它来计算输入相对于屏幕顶部的距离视口。

      # CoffeeScript
      $.extend( $.datepicker, { _checkOffset: (inst,offset,isFixed) ->
              offset.top = $("##{inst.id}").offset().top - $(window).scrollTop() + $("##{inst.id}")[0].getBoundingClientRect().height
              offset
          }
      )
      

      // JavaScript
      $.extend($.datepicker, {
          _checkOffset: function(inst, offset, isFixed) {
              offset.top = $("#" + inst.id).offset().top - $(window).scrollTop() + $("#" + inst.id)[0].getBoundingClientRect().height;
              return offset;
          }
      });
      

      【讨论】:

      • 您的咖啡充满了语法错误。你介意修理它们吗?或者更好的是,为我们将其转换为 JS? 编辑: Nvm,所以只是搞砸了间距。这就是我讨厌依赖空格的语言的原因。我正在用 JS 修改你的答案,希望没问题。
      【解决方案9】:

      接受的答案总体上效果很好。

      但是,在使用 jQuery UI v1.11.4 时,我遇到了一个问题,即当向下滚动浏览器窗口时,日期选择器会将自己定位在模式窗口中的输入之外(固定定位)。我能够解决这个问题,编辑接受的答案如下:

      const checkOffset = $.datepicker._checkOffset;
      
      $.extend($.datepicker, {
        _checkOffset: function(inst, offset, isFixed) {
          if(isFixed) {
            return checkOffset.apply(this, arguments);
          } else {
            return offset;
          }
        }
      });
      

      【讨论】:

        【解决方案10】:
        $("first-selector").datepicker().bind('click',function () {
              $("#ui-datepicker-div").appendTo("other-selector");
        });
        
        <style>
        #ui-datepicker-div {
                position: absolute !important;
                top: auto !important;
                left: auto !important;
                z-index: 99999999 !important;
        }
        </style>
        

        【讨论】:

          【解决方案11】:

          这对我来说是这样的:

          $( "input[name='birthdate']" ).datepicker({
              beforeShow : function(input,inst){
              window.setTimeout(function () {
                  $("#ui-datepicker-div").position({ my: "left top", at: "left bottom", of: input });
              }, 1);
              }
          });
          

          在调整屏幕大小时使其定位:

          $(window).resize(function(){ $("#ui-datepicker-div").position({ my: "left top", at: "left bottom", of: "input[name='birthdate']" }); });
          

          【讨论】:

            【解决方案12】:

            这里有一个更简单的解决方案

            var $picker = $( ".myspanclass" ).datepicker(); // span has display: inline-block
            $picker.find('.ui-datepicker').css('margin-left', '-50px');
            

            【讨论】:

            • 这个答案是错误的,因为线程开始专门询问静态渲染位置。您的答案只是将位置向左移动 50 像素。
            【解决方案13】:

            默认情况下,日期选择器的日历显示在我的输入框的右上角,所以它的顶部被我的菜单栏隐藏了。这是我非常简单地定位小部件(jquery-ui 版本 1.11.4)的方式(注意 'ui-datepicker' 是 jquery-ui 给出的类名):

            $(document).ready(function() {
            $(".ui-datepicker").css('margin-left', '-50px', 'margin-top', '-50px');
            //... 
            }
            

            【讨论】:

            • 您的问题错过了与该线程所述问题的相关性。其次,为什么要通过 JS 而不是 CSS 样式表来应用 css 属性?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-10
            • 1970-01-01
            • 1970-01-01
            • 2019-04-04
            • 2015-03-01
            • 1970-01-01
            相关资源
            最近更新 更多