Alex P
Alex P

Reputation: 12489

jQuery ui datepicker positioning problem when scrolling down webpage

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.

<% foreach (var record in Model) { %>
    <div class="recordname"><%=record.name%></div>
    <%=Html.TextBox("DateTimePicker", null, new { @class = "date-pick" } )%>
    // <-- additional html here -->
<% } %> 

I have set the defaults of my datepicker as follows:

    $(".date-pick").each(function() {
    $(this).datepicker({
        dateFormat: 'dd M yy',
        showOn: 'button',
        buttonImage: '/Images/datepickericon.png',
        buttonImageOnly: true
        });
    });

When the page first loads, if I click any datepicker icon that is visible on screen (i.e. without scrolling) then the datepicker appears as expected.

However, if I scroll down the page and then click a datepicker icon, the datepicker does not appear in the screen window but is instead rendered right back near the top of the screen.

Any ideas how to solve this?

I am using:

Upvotes: 8

Views: 30510

Answers (11)

Carlos Campos
Carlos Campos

Reputation: 15

This worked for me:

beforeShow: function(input, inst) {
    inst.dpDiv.css({
    marginTop: $('body').scrollTop() + 'px'
});

so the final code would be:

$(this).datepicker({
    dateFormat: 'dd M yy',
    showOn: 'button',
    buttonImage: '/Images/datepickericon.png',
    buttonImageOnly: true,
    beforeShow: function(input, inst) {
        inst.dpDiv.css({
            marginTop: $('body').scrollTop() + 'px'
        });
    }
});

Upvotes: 0

sanjay
sanjay

Reputation: 21

first go to here and format your js file in Javascript Beautifier

then go to line no 445

k = k + document.body.scrollTop;
change this line as 
k = k ;

Upvotes: 0

David Moore
David Moore

Reputation: 29

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;
},

Upvotes: 2

Abhishek
Abhishek

Reputation: 1618

Hey here is one hack which can we be used to solve this issue.

$(".ui-datepicker-trigger").on("click", function() {
var self;
if ($.browser.msie) {
self = $(this);
$("#ui-datepicker-div").hide();
setTimeout(function(){
$("#ui-datepicker-div").css({
top: self.offset().top + $('html').scrollTop() + 30
});
$("#ui-datepicker-div").show();
}, 0); 
}
}); 

Give a try it worked for me :)

Upvotes: 1

nanoscopic
nanoscopic

Reputation: 41

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.

Upvotes: 3

Christian Suarez
Christian Suarez

Reputation: 91

I had the same problem too, I'm using IE9 but instead to use document.documentElement.scrollTop I edit the follwing line on my JS code

$.datepicker._pos[1] += input.offsetHeight + document.body.scrollTop;

This is because document.documentElement.scrollTop returns 0, for me the above code solves my problem

Upvotes: 9

humbolight
humbolight

Reputation: 690

I was having these issues as well in IE 9 and cannot thank you enough for your collective help. Chrome 22.0.1229.94 m and FF 15.0.1 did not exhibit this issue for me.

I first tried forcing IE 8 emulation with a meta tag

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" /> 

to no avail.

I then edited the jquery.ui.datepicker.js file as suggested to adjust position height by accounting for scrolling. This did not work either.

Finally I changed my doctype from

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 

to

<!DOCTYPE html>

which worked successfully!!

I removed the meta tag that forced IE 8 emulation, but kept the changes I made to the datepicker js file. My success could be a combination of the edited js and the change in doctype, or just the change in doctype.

Upvotes: 3

andora
andora

Reputation: 1356

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.

Upvotes: -1

Jeffrey Cobb
Jeffrey Cobb

Reputation: 26

I have come across the same issue on an app I am working on and found a solution. The application did not contain a proper doc-type specification and all that was needed was to add it to the top of the page.

<!DOCTYPE html>

Hope this helps.

Upvotes: 1

Alex P
Alex P

Reputation: 12489

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

Upvotes: 7

Quasipickle
Quasipickle

Reputation: 4498

I'm not sure if this would be the problem, but you're attaching the datepicker in a non-standard way. You don't need to iterate with .each();

$("input.date-pick").datepicker({
    dateFormat: 'dd M yy',
    showOn: 'button',
    buttonImage: '/Images/datepickericon.png',
    buttonImageOnly: true
});

Also, you should always put a tag name in front of a class selector whenever possible, as it speeds up the selection process.

Upvotes: 1

Related Questions