jQuery ui datepicker positioning problem when scrolling down webpage

前端 未结 10 1169
野的像风
野的像风 2021-01-02 11:30

I have a webpage that uses multiple instances of the jQuery ui datepicker. My webpage will display ~80 records which extends beyond a single screenshot.

<         


        
相关标签:
10条回答
  • 2021-01-02 12:00

    I think I have managed to resolve my issue but at the same time I think I may have uncovered a bug (?) in the jquery ui datepicker code.

    Before I go further then let me just say that I am new to jquery / javascript and would appreciate any input on the below.

    To recap the problem, I am using asp.net mvc and I am trying to show ~80 datepickers on a page. For any datepicker in the initial viewport, the datepickers position fine. However, when I scroll down the datepickers are still rendered near the top of the screen.

    I started to view the source code and do some debugging. What I noticed is that the extent to which the datepicker was offset towards the top of the screen was directly proportional to the amount by which I had scrolled i.e. more scroll = greater offset.

    The key issue in the code I found (see below) is that when the code works out where to position the datepicker it does not take into account how far down the screen a user has scrolled:

    _showDatepicker: 
    function(input) { 
          input = input.target || input;
          //....more code...
    
          if (!$.datepicker._pos) { // position below input
          $.datepicker._pos = $.datepicker._findPos(input);
          $.datepicker._pos[1] += input.offsetHeight; //add the height
           }
    

    In the final line the offsetHeight method does not take account of how much you have scrolled down the screen by.

    If you update this line to the following then this solves the issue I have raised:

      $.datepicker._pos[1] += input.offsetHeight + document.documentElement.scrollTop; //add the height 
    

    This simply gets the scrollbar position and adds it to offsetHeight to get the correct position.

    In the interests of full disclosure I am not exactly sure why this works and would appreciate some insight.

    I have spent ~ 3 days on this issue and researched the web and this is the best I can come up with.

    Interestingly, there was a similar query in the jquery forums:

    Click here to view

    Reading the report it seemed to suggest that the bug was fixed in a prior version to 1.8?

    Thanks

    0 讨论(0)
  • 2021-01-02 12:04

    I encountered this same problem with jQuery UI version 1.9.2 and IE9.

    There appears to be a function in jQuery UI entitled _checkOffset that is meant to take care of this problem. It doesn't work.

    It attempts to use $(document).scrollTop(), which always seems to return 0 in IE9. I had to alter the contents of the function to use document.body.scrollTop instead when the jQuery function returns zero. Thus replace

    $(document).scrollTop()
    

    with

    ($(document).scrollTop()||document.body.scrollTop)
    

    everywhere in _checkOffset in order to 'fix' jQuery UI and make it work properly.

    0 讨论(0)
  • 2021-01-02 12:04

    The Datepicker-UI popup can be made draggable by adding the following code:

    $('#ui-datepicker-div').draggable();

    As this ID applies to the component div created for all popup datepickers on the page. While:

    $(".ui-datepicker").draggable()

    Applies to all datepickers on a page (whether popup or inline). By making the panel draggable, you can usually position the datepicker where you want it without scrolling.

    0 讨论(0)
  • 2021-01-02 12:08

    Within Jquery.UI, just update the _checkOffset function, so that viewHeight is added to offset.top, before offset is returned.
    Script: datepicker.js

    _checkOffset: function(inst, offset, isFixed) {
         var dpWidth = inst.dpDiv.outerWidth();
         var dpHeight = inst.dpDiv.outerHeight();
         var inputWidth = inst.input ? inst.input.outerWidth() : 0;
         var inputHeight = inst.input ? inst.input.outerHeight() : 0;
         var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
         var 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;
    },
    
    0 讨论(0)
提交回复
热议问题