Skip to content
This repository has been archived by the owner on Feb 14, 2019. It is now read-only.

Implement pickerPosition:'auto' option #645

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 73 additions & 6 deletions js/bootstrap-datetimepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
this.linkField = options.linkField || this.element.data('link-field') || false;
this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType);
this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;
this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';
this.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'auto';
this.showMeridian = options.showMeridian || this.element.data('show-meridian') || false;
this.initialDate = options.initialDate || new Date();
this.zIndex = options.zIndex || this.element.data('z-index') || undefined;
Expand Down Expand Up @@ -222,7 +222,7 @@
if (this.isInline) {
this.picker.addClass('datetimepicker-inline');
} else {
this.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu');
this.picker.addClass('datetimepicker-dropdown-' + this.getAutoPosition() + ' dropdown-menu');
}
if (this.isRTL) {
this.picker.addClass('datetimepicker-rtl');
Expand Down Expand Up @@ -401,6 +401,10 @@
}
this.place();
$(window).on('resize', $.proxy(this.place, this));

var scrollElement = this.getScrollParent(this.element[0]);
$(scrollElement).on('scroll', $.proxy(this.place, this));

if (e) {
e.stopPropagation();
e.preventDefault();
Expand All @@ -417,6 +421,10 @@
if (this.isInline) return;
this.picker.hide();
$(window).off('resize', this.place);

var scrollElement = this.getScrollParent(this.element[0]);
$(scrollElement).off('scroll', this.place);

this.viewMode = this.startViewMode;
this.showMode();
if (!this.isInput) {
Expand Down Expand Up @@ -592,6 +600,60 @@
this.updateNavArrows();
},

getAutoHorizonalPosition: function(inverse) {
if (this.pickerPosition != 'auto') {
return this.pickerPosition;
}
var el = this.component ? this.component : this.element;
var scrollElement = this.getScrollParent(el[0]);

var leftOffset = scrollElement ? el.offset().left + scrollElement.scrollLeft : el.offset().left;
var pickerWidthWithMargin = this.picker.outerWidth(true);
var leftOverflow = $(window).width() - (leftOffset + pickerWidthWithMargin);

return leftOverflow < 0 ? 'left' : 'right';
},

getAutoVerticalPosition: function() {
if (this.pickerPosition != 'auto') {
return this.pickerPosition;
}

var el = this.component ? this.component : this.element;
var scrollElement = this.getScrollParent(el[0]);

var topOffset = scrollElement ? el.offset().top + scrollElement.scrollTop : el.offset().top;
var pickerHeightWithMargin = this.picker.outerHeight(true);
var bottomOverflow = $(window).height() - (topOffset + pickerHeightWithMargin);

return bottomOverflow < 0 ? 'top' : 'bottom';
},

getAutoPosition: function () {
if (this.pickerPosition != 'auto') {
return this.pickerPosition;
}

return this.getAutoVerticalPosition() + '-' + this.getAutoHorizonalPosition();
},

getScrollParent: function(element, includeHidden) {
var style = getComputedStyle(element);
var excludeStaticParent = style.position === "absolute";
var overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;

if (style.position === "fixed") return document.body;
for (var parent = element; (parent = parent.parentElement);) {
style = getComputedStyle(parent);
if (excludeStaticParent && style.position === "static") {
continue;
}
if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) return parent;
}

return document.body;
},

place: function () {
if (this.isInline) return;

Expand All @@ -606,23 +668,28 @@
this.zIndex = index_highest + 10;
}

var offset, top, left, containerOffset;
var offset, top, left, containerOffset, position;
if (this.container instanceof $) {
containerOffset = this.container.offset();
} else {
containerOffset = $(this.container).offset();
}

var isAutoPosition = this.pickerPosition == 'auto';
position = isAutoPosition ? this.getAutoPosition() : this.pickerPosition;
this.picker.removeClass('datetimepicker-dropdown-top-right datetimepicker-dropdown-top-left datetimepicker-dropdown-bottom-right datetimepicker-dropdown-bottom-left');
this.picker.addClass('datetimepicker-dropdown-' + this.getAutoPosition(true) + ' dropdown-menu');

if (this.component) {
offset = this.component.offset();
left = offset.left;
if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
if (position == 'bottom-left' || position == 'top-left') {
left += this.component.outerWidth() - this.picker.outerWidth();
}
} else {
offset = this.element.offset();
left = offset.left;
if (this.pickerPosition === 'bottom-left' || this.pickerPosition === 'top-left') {
if (position == 'bottom-left' || position == 'top-left') {
left += this.element.outerWidth() - this.picker.outerWidth();
}
}
Expand All @@ -632,7 +699,7 @@
left = bodyWidth - 220;
}

if (this.pickerPosition === 'top-left' || this.pickerPosition === 'top-right') {
if (position == 'top-left' || position == 'top-right') {
top = offset.top - this.picker.outerHeight();
} else {
top = offset.top + this.height;
Expand Down