From 348d5624b4cbc9d09b98ccb825970600fa141213 Mon Sep 17 00:00:00 2001 From: SpoonNZ Date: Tue, 6 Aug 2013 12:36:46 +1200 Subject: [PATCH] Update _checkOffset to handle invisible input The _findPos function already searches for the nearest visible element, and returns its position. This is good. The _checkOffset function, however, just deals with the current element, which causes issues where your invisible element is placed oddly by the browser. The problem is only evident when the datepicker's input element is invisible (e.g. if you're showing an altField instead, and have a button to show the picker) and a descendant of a fixed element, and the screen is scrolled. The conditions never matched, so the documents scroll amount was never subtracted from the datepicker's position. This fix uses code adapted from the _findPos function to find the nearest visible element and uses that to test the offset. Note that inputHeight and inputWidth are reset to 0, as that's the effective width of an invisible element (although using .outerHeight() actually returns a positive number). --- ui/jquery.ui.datepicker.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js index 45ddf8678e2..791a56461f8 100644 --- a/ui/jquery.ui.datepicker.js +++ b/ui/jquery.ui.datepicker.js @@ -765,10 +765,17 @@ $.extend(Datepicker.prototype, { var inputHeight = inst.input ? inst.input.outerHeight() : 0; var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft(); var viewHeight = document.documentElement.clientHeight + $(document).scrollTop(); + var isRTL = this._get(inst, "isRTL"); + var offsetTarget = inst.input; - 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() : 0; + while (offsetTarget && !offsetTarget.is(':visible')) { + offsetTarget = isRTL ? offsetTarget.prev() : offsetTarget.next(); + inputHeight = inputWidth = 0 + } + + offset.left -= (isRTL ? (dpWidth - inputWidth) : 0); + offset.left -= (isFixed && offset.left == offsetTarget.offset().left) ? $(document).scrollLeft() : 0; + offset.top -= (isFixed && offset.top == (offsetTarget.offset().top + inputHeight)) ? $(document).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) ?