Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

preventOverflow flag to offset tooltips to stay within viewport #953

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ Options can be passed either as a data (data-slider-foo) attribute, or as part o
| tooltip | string | 'show' | whether to show the tooltip on drag, hide the tooltip, or always show the tooltip. Accepts: 'show', 'hide', or 'always' |
| tooltip_split | bool | false | if false show one tootip if true show two tooltips one for each handler |
| tooltip_position | string | null | Position of tooltip, relative to slider. Accepts 'top'/'bottom' for horizontal sliders and 'left'/'right' for vertically orientated sliders. Default positions are 'top' for horizontal and 'right' for vertical slider. |
| preventOverflow | bool | false | whether to shift tooltips to keep them within the viewport, similar to Popper.js's [`preventOverflow` modifier](https://popper.js.org/docs/v2/modifiers/prevent-overflow/)
| handle | string | 'round' | handle shape. Accepts: 'round', 'square', 'triangle' or 'custom' |
| reversed | bool | false | whether or not the slider should be reversed |
| rtl | string, bool| 'auto' | whether or not the slider should be shown in rtl mode. Accepts true, false, 'auto'. Default 'auto' : use actual direction of HTML (`dir='rtl'`) |
Expand Down
59 changes: 59 additions & 0 deletions src/js/bootstrap-slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,11 @@ const windowIsDefined = (typeof window === "object");
// Bind window handlers
this.resize = this._resize.bind(this);
window.addEventListener("resize", this.resize, false);
// Simulate Popper's behavior of listening to both resize and scroll:
// https://popper.js.org/docs/v2/modifiers/event-listeners/
if (this.options.preventOverflow) {
window.addEventListener("scroll", this.resize, false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you make sure this event listener is being removed in the _removeSliderEventHandlers cleanup method?

}


// Bind tooltip-related handlers
Expand Down Expand Up @@ -906,6 +911,7 @@ const windowIsDefined = (typeof window === "object");
scale: 'linear',
focus: false,
tooltip_position: null,
preventOverflow: false,
labelledby: null,
rangeHighlights: []
},
Expand Down Expand Up @@ -1243,13 +1249,62 @@ const windowIsDefined = (typeof window === "object");
this._setText(this.tooltipInner, formattedTooltipVal);

this.tooltip.style[this.stylePos] = `${positionPercentages[0]}%`;
this._preventOverflow(this.tooltip);

function getPositionPercentages(state, reversed){
if (reversed) {
return [100 - state.percentage[0], self.options.range ? 100 - state.percentage[1] : state.percentage[1]];
}
return [state.percentage[0], state.percentage[1]];
}
},
_preventOverflow: function _prevetOverflow(tooltip){
if (!this.options.preventOverflow) {
return;
}
const rect = tooltip.getBoundingClientRect();
if (rect.width === 0 && rect.height === 0) {
return; // not rendered
}
const style = tooltip.style[this.stylePos];
const arrow = tooltip.querySelector('.arrow');
let offset;
if (this.options.orientation === 'vertical') {
const minY = 0, maxY = document.body.clientHeight;
if (rect.y < minY) {
offset = minY - rect.y;
} else if (rect.y + rect.height > maxY) {
offset = maxY - (rect.y + rect.height);
}
if (offset) {
tooltip.style.top = `calc(${style} + ${offset}px)`;
//arrow.style.top = `calc(50% - .4rem + ${offset}px)`;
arrow.style.transform = `translateY(${-offset}px)`;
} else {
arrow.style.transform = null;
}
} else {
const minX = 0, maxX = document.body.clientWidth;
// Because of .tooltip-inner's left: -50%, the actual rectangle span
// is [rect.x - rect.width / 2, rect.x + rect.width + 2]
if (rect.x - rect.width / 2 < minX) {
offset = minX - (rect.x - rect.width / 2);
} else if (rect.x + rect.width / 2 > maxX) {
offset = maxX - (rect.x + rect.width / 2);
}
if (offset) {
if (this.stylePos === 'left') {
tooltip.style.left = `calc(${style} + ${offset}px)`;
//arrow.style.left = `calc(50% - .4rem + ${offset}px)`;
} else {
tooltip.style.right = `calc(${style} - ${offset}px)`;
}
arrow.style.transform = `translateX(${-offset}px)`;
} else {
arrow.style.transform = null;
}
}
// right, top
},
_copyState: function() {
return {
Expand Down Expand Up @@ -1465,6 +1520,7 @@ const windowIsDefined = (typeof window === "object");
formattedTooltipVal = this.options.formatter(this._state.value);
this._setText(this.tooltipInner, formattedTooltipVal);
this.tooltip.style[this.stylePos] = `${ (positionPercentages[1] + positionPercentages[0])/2 }%`;
this._preventOverflow(this.tooltip);

var innerTooltipMinText = this.options.formatter(this._state.value[0]);
this._setText(this.tooltipInner_min, innerTooltipMinText);
Expand All @@ -1473,14 +1529,17 @@ const windowIsDefined = (typeof window === "object");
this._setText(this.tooltipInner_max, innerTooltipMaxText);

this.tooltip_min.style[this.stylePos] = `${ positionPercentages[0] }%`;
this._preventOverflow(this.tooltip_min);

this.tooltip_max.style[this.stylePos] = `${ positionPercentages[1] }%`;
this._preventOverflow(this.tooltip_max);

} else {
formattedTooltipVal = this.options.formatter(this._state.value[0]);
this._setText(this.tooltipInner, formattedTooltipVal);

this.tooltip.style[this.stylePos] = `${ positionPercentages[0] }%`;
this._preventOverflow(this.tooltip);
}

if (this.options.orientation === 'vertical') {
Expand Down