fgelinas / timepicker

A jQuery UI Time Picker
http://fgelinas.com/code/timepicker
GNU General Public License v2.0
266 stars 84 forks source link

Wrong calculate top value, when timepicker have position fixed #77

Open AleshchenkoMaksim opened 11 years ago

AleshchenkoMaksim commented 11 years ago

I have popup wnd with fixed position, that is displayed in the center of the page. In this popup i have input. Timepicker bind on focus event. On focus input timepicker have wrong top position, but left position is normal. Input top position 193px, timepicker top position 568px...

Use: jquery 1.4.2 and jquery UI 1.8.16

P.S.: Jquery UI datepicker have normal top and left position, it is under my input.

damienfournier commented 10 years ago

I second that. Timepicker doesn't work on modals, because it adds the scrollTop value to the position.

So when you scroll in your window, and then click on something that launches a modal with a timepicker input, the timepicker window is below the position that it should have. If you have scrolled a lot, the timepicker window is hidden out of the view.

damienfournier commented 10 years ago

For information, I solved my problem with this at line 398:

 offset = $.timepicker._checkOffset(inst, offset, isFixed);

 offset.top -= $(document).scrollTop();   // Line added

Note that non-modal views may not work now.... but I don't have them in my code.

michael-zock commented 10 years ago

Thanks, Damien! I ran into the same problem and your added line allowed me to work around that.

leitgab commented 7 years ago

The problem is caused due to lack of precision during offset calculations/comparisons. The Math.round() function avoids this - just replace the whole _checkOffset (inst, offset, isFixed) method:

        _checkOffset: function( inst, offset, isFixed ) {
            var tpWidth = inst.tpDiv.outerWidth(),
                tpHeight = inst.tpDiv.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() );

            offset.left -= ( this._get( inst, "isRTL" ) ? ( tpWidth - inputWidth ) : 0 );
            offset.left -= ( isFixed && offset.left === Math.round(inst.input.offset().left )) ? $( document ).scrollLeft() : 0;
            offset.top -= ( isFixed && offset.top === Math.round( inst.input.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 + tpWidth > viewWidth && viewWidth > tpWidth ) ?
                Math.abs( offset.left + tpWidth - viewWidth ) : 0 );
            offset.top -= Math.min( offset.top, ( offset.top + tpHeight > viewHeight && viewHeight > tpHeight ) ?
                Math.abs( tpHeight + inputHeight ) : 0 );

            return offset;
        },