Skip to content

Commit d275f0a

Browse files
committed
Fix the positioning if the timepicker is viewport is changed.
1 parent 57f0805 commit d275f0a

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

jquery.timepicker.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@
211211
last: function() { return widget.last(i) ;},
212212
selected: function() { return widget.selected(i) ;},
213213
open: function() { return widget.open(i) ;},
214+
reposition: function () { return widget.reposition(i); },
214215
close: function() { return widget.close(i) ;},
215216
closed: function() { return widget.closed(i) ;},
216217
destroy: function() { return widget.destroy(i) ;},
@@ -224,6 +225,7 @@
224225

225226
widget._setDefaultTime(i);
226227
widget._addInputEventsHandlers(i);
228+
$(window).on('resize.timepicker', )
227229

228230
i.element.data('TimePicker', i);
229231
},
@@ -397,6 +399,11 @@
397399
i.element.data('timepicker-user-clicked-outside', true).blur();
398400
}
399401
});
402+
// make sure we reposition the timepicker when the viewport changes
403+
$(window).bind('resize.timepicker-' + i.element.data('timepicker-event-namespace'), i.reposition);
404+
// use vanilla javascript to be able to use event capturing instead of bubbling: otherwise we have to listen
405+
// on all parent containers.
406+
window.addEventListener('scroll', i.reposition, true);
400407

401408
// if a date is already selected and options.dynamic is true,
402409
// arrange the items in the list so the first item is
@@ -517,6 +524,46 @@
517524
return i.element;
518525
},
519526

527+
reposition: function (i) {
528+
var widget = this;
529+
var containerDecorationHeight = widget.container.outerHeight() - widget.container.height(),
530+
zindex = i.options.zindex ? i.options.zindex : i.element.offsetParent().css( 'z-index' ),
531+
elementOffset = i.element.offset();
532+
533+
// position the container right below the element, or as close to as possible.
534+
widget.container.css( {
535+
top: elementOffset.top + i.element.outerHeight(),
536+
left: elementOffset.left
537+
} );
538+
539+
// then show the container so that the browser can consider the timepicker's
540+
// height to calculate the page's total height and decide if adding scrollbars
541+
// is necessary.
542+
widget.container.show();
543+
544+
// now we need to calculate the element offset and position the container again.
545+
// If the browser added scrollbars, the container's original position is not aligned
546+
// with the element's final position. This step fixes that problem.
547+
widget.container.css( {
548+
left: i.element.offset().left,
549+
height: widget.ui.outerHeight() + containerDecorationHeight,
550+
width: i.element.outerWidth(),
551+
zIndex: zindex,
552+
cursor: 'default'
553+
} );
554+
555+
556+
var calculatedWidth = widget.container.width() - ( widget.ui.outerWidth() - widget.ui.width() );
557+
558+
// hardcode ui, viewport and item's width. I couldn't get it to work using CSS only
559+
widget.ui.css( { width: calculatedWidth } );
560+
widget.viewport.css( { width: calculatedWidth } );
561+
i.items.css( { width: calculatedWidth } );
562+
563+
564+
return i.element;
565+
},
566+
520567
close: function(i) {
521568
var widget = this;
522569

@@ -530,6 +577,9 @@
530577
'keydown.timepicker-' + i.element.data('timepicker-event-namespace') + ' ' +
531578
'keyup.timepicker-' + i.element.data('timepicker-event-namespace'));
532579

580+
$(window).unbind('resize.timepicker-' + i.element.data('timepicker-event-namespace'));
581+
window.removeEventListener('scroll', i.reposition, true);
582+
533583
return i.element;
534584
},
535585

@@ -669,6 +719,7 @@
669719
'next',
670720
'previous',
671721
'open',
722+
'reposition',
672723
'close',
673724
'destroy',
674725
'setTime'

0 commit comments

Comments
 (0)