Bring element to view if not in view
Browse files- assets/scripts/src/element.js +42 -5
- assets/scripts/src/sholo.js +12 -2
- index.html +2 -0
assets/scripts/src/element.js
CHANGED
@@ -34,6 +34,40 @@ export default class Element {
|
|
34 |
return { x, y };
|
35 |
}
|
36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
/**
|
38 |
* Gets the calculated position on screen, around which
|
39 |
* we need to draw
|
@@ -82,17 +116,17 @@ export default class Element {
|
|
82 |
|
83 |
const popoverTip = this.popover.querySelector('.sholo-popover-tip');
|
84 |
|
85 |
-
const
|
86 |
const popoverHeight = this.getPopoverHeight();
|
87 |
const popoverMargin = this.options.padding + 10;
|
88 |
|
89 |
this.popover.style.left = `${position.left - this.options.padding}px`;
|
90 |
|
91 |
// Calculate different dimensions after attaching popover
|
92 |
-
const
|
93 |
|
94 |
// If adding popover would go out of the window height, then show it to the top
|
95 |
-
if (
|
96 |
this.popover.style.top = `${position.top - popoverHeight - popoverMargin}px`;
|
97 |
popoverTip.classList.add('bottom');
|
98 |
} else {
|
@@ -113,12 +147,15 @@ export default class Element {
|
|
113 |
this.popover.style.display = 'none';
|
114 |
}
|
115 |
|
116 |
-
|
117 |
// eslint-disable-next-line prefer-destructuring
|
118 |
const body = this.document.body;
|
119 |
const html = this.document.documentElement;
|
120 |
|
121 |
-
return
|
|
|
|
|
|
|
122 |
}
|
123 |
|
124 |
getPopoverHeight() {
|
|
|
34 |
return { x, y };
|
35 |
}
|
36 |
|
37 |
+
isInView() {
|
38 |
+
let top = this.node.offsetTop;
|
39 |
+
let left = this.node.offsetLeft;
|
40 |
+
const width = this.node.offsetWidth;
|
41 |
+
const height = this.node.offsetHeight;
|
42 |
+
|
43 |
+
let el = this.node;
|
44 |
+
|
45 |
+
while (el.offsetParent) {
|
46 |
+
el = el.offsetParent;
|
47 |
+
top += el.offsetTop;
|
48 |
+
left += el.offsetLeft;
|
49 |
+
}
|
50 |
+
|
51 |
+
return (
|
52 |
+
top >= this.window.pageYOffset &&
|
53 |
+
left >= this.window.pageXOffset &&
|
54 |
+
(top + height) <= (this.window.pageYOffset + this.window.innerHeight) &&
|
55 |
+
(left + width) <= (this.window.pageXOffset + this.window.innerWidth)
|
56 |
+
);
|
57 |
+
}
|
58 |
+
|
59 |
+
bringInView() {
|
60 |
+
if (this.isInView()) {
|
61 |
+
return;
|
62 |
+
}
|
63 |
+
|
64 |
+
const elementRect = this.getCalculatedPosition();
|
65 |
+
const absoluteElementTop = elementRect.top + window.pageYOffset;
|
66 |
+
const middle = absoluteElementTop - (window.innerHeight / 2);
|
67 |
+
|
68 |
+
window.scrollTo(0, middle);
|
69 |
+
}
|
70 |
+
|
71 |
/**
|
72 |
* Gets the calculated position on screen, around which
|
73 |
* we need to draw
|
|
|
116 |
|
117 |
const popoverTip = this.popover.querySelector('.sholo-popover-tip');
|
118 |
|
119 |
+
const pageHeight = this.getFullPageSize().height;
|
120 |
const popoverHeight = this.getPopoverHeight();
|
121 |
const popoverMargin = this.options.padding + 10;
|
122 |
|
123 |
this.popover.style.left = `${position.left - this.options.padding}px`;
|
124 |
|
125 |
// Calculate different dimensions after attaching popover
|
126 |
+
const pageHeightAfterPopOver = position.bottom + popoverHeight + popoverMargin;
|
127 |
|
128 |
// If adding popover would go out of the window height, then show it to the top
|
129 |
+
if (pageHeightAfterPopOver >= pageHeight) {
|
130 |
this.popover.style.top = `${position.top - popoverHeight - popoverMargin}px`;
|
131 |
popoverTip.classList.add('bottom');
|
132 |
} else {
|
|
|
147 |
this.popover.style.display = 'none';
|
148 |
}
|
149 |
|
150 |
+
getFullPageSize() {
|
151 |
// eslint-disable-next-line prefer-destructuring
|
152 |
const body = this.document.body;
|
153 |
const html = this.document.documentElement;
|
154 |
|
155 |
+
return {
|
156 |
+
height: Math.max(body.scrollHeight, body.offsetHeight, html.scrollHeight, html.offsetHeight),
|
157 |
+
width: Math.max(body.scrollWidth, body.offsetWidth, html.scrollWidth, html.offsetWidth),
|
158 |
+
};
|
159 |
}
|
160 |
|
161 |
getPopoverHeight() {
|
assets/scripts/src/sholo.js
CHANGED
@@ -72,12 +72,22 @@ export default class Sholo {
|
|
72 |
const prevClicked = e.target.classList.contains('sholo-prev-btn');
|
73 |
const closeClicked = e.target.classList.contains('sholo-close-btn');
|
74 |
|
|
|
|
|
|
|
|
|
|
|
75 |
if (nextClicked) {
|
76 |
this.moveNext();
|
77 |
} else if (prevClicked) {
|
78 |
this.movePrevious();
|
79 |
-
}
|
80 |
-
|
|
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
}
|
83 |
|
|
|
72 |
const prevClicked = e.target.classList.contains('sholo-prev-btn');
|
73 |
const closeClicked = e.target.classList.contains('sholo-close-btn');
|
74 |
|
75 |
+
if (closeClicked) {
|
76 |
+
this.reset();
|
77 |
+
return;
|
78 |
+
}
|
79 |
+
|
80 |
if (nextClicked) {
|
81 |
this.moveNext();
|
82 |
} else if (prevClicked) {
|
83 |
this.movePrevious();
|
84 |
+
}
|
85 |
+
|
86 |
+
// @todo - move to onHighlighted hook and add the check if not visible then do this
|
87 |
+
if (this.overlay.highlightedElement) {
|
88 |
+
window.setTimeout(() => {
|
89 |
+
this.overlay.highlightedElement.bringInView();
|
90 |
+
}, 800);
|
91 |
}
|
92 |
}
|
93 |
|
index.html
CHANGED
@@ -77,6 +77,8 @@
|
|
77 |
|
78 |
sholo.defineSteps([
|
79 |
{ element: '.section__header' },
|
|
|
|
|
80 |
{ element: '.section__examples' },
|
81 |
{ element: '.section__contributing' },
|
82 |
]);
|
|
|
77 |
|
78 |
sholo.defineSteps([
|
79 |
{ element: '.section__header' },
|
80 |
+
{ element: '.section__how' },
|
81 |
+
{ element: '.section__purpose' },
|
82 |
{ element: '.section__examples' },
|
83 |
{ element: '.section__contributing' },
|
84 |
]);
|