I am trying to create a guided tour for my website but I am having trouble with positioning the content div. I need to get it to show up in the same place regardless of screen resolution. Take a look at the two images. Image 1 shows the content div in the correct spot but on my laptop in Image 2 it does not. It needs to be positioned under the bookmark link. Here is the code:
window.onload = function(){
const guidePosition = [
{top: 40, left: 1290},
{top: 190, left: 160},
{top: 230, left: 390},
{top: 360, left: 520},
{top: 120, left: 720},
{top: 55, left: 800}
]
const bodyTextEle = document.getElementById('guideBodyText');
const contentEle = document.getElementById('guideContent');
const stepLiEle = document.getElementsByClassName('dot');
let currentStepIndex = -1;
const stepLength = guidePosition.length;
changeStep();
document.getElementById("guideNextBtn").addEventListener('click', ()=>{
changeStep('next');
}
,false
);
document.getElementById("guidePrevBtn").addEventListener('click', ()=>{
changeStep('prev');
}
, false
);
document.getElementById('closeBtn').addEventListener('click', ()=>{
document.getElementById('guidedTour').style.display = 'none';
}
,false
);
function changeStep(direction){
if((direction === 'prev' && currentStepIndex === 0) || (direction === 'next' && currentStepIndex === stepLength-1)){
document.getElementById('guidedTour').style.display = 'none';
}else{
let eraseDotIndex;
if(direction === 'prev'){
currentStepIndex = currentStepIndex - 1;
eraseDotIndex = currentStepIndex === stepLength-1 ? 0 : currentStepIndex 1;
}else{
currentStepIndex = currentStepIndex 1;
eraseDotIndex = currentStepIndex === 0 ? stepLength -1 : currentStepIndex -1;
}
bodyTextEle.style.marginLeft = `${-360*currentStepIndex}px`;
//bodyTextEle.style.left = `${-360*currentStepIndex}px`;
stepLiEle[eraseDotIndex].setAttribute('data-step', ''); // erase number
stepLiEle[currentStepIndex].setAttribute('data-step', currentStepIndex 1); // add number
stepLiEle[eraseDotIndex].classList.remove('active'); // remove dot active
stepLiEle[currentStepIndex].classList.add('active'); // add dot active
var xTop = guidePosition[currentStepIndex].top 'px'
var xLeft = guidePosition[currentStepIndex].left 'px'
contentEle.style.top = xTop;
contentEle.style.left = xLeft;
}
}
}
button {
outline: none;
}
li {
list-style: none;
}
a, button {
cursor: pointer;
}
.fb_gd_wrap .mask {
position: fixed;
top: 0;
left: 0;
//right: 0;
//bottom: 0;
background: rgba(0, 0, 0, .3);
z-index: 0;
height: 100%;
width: 100%
}
.fb_gd_wrap .content {
height: 200px;
background: transparent;
z-index: 99999;
filter: drop-shadow(0px 0px 6px rgba(0, 0, 0, 0.4));
position: absolute;
left: 0px;
}
.fb_gd_wrap .content::after {
/* this is the triangle callout pointer */
content: "";
display: block;
position: absolute;
/* left top */
//top: 25px;
//left: -30px;
//border: 15px solid #eee;
/* left bottom */
//top: 120px;
//left: -30px;
//border: 15px solid #eee;
/* top left */
//top: -30px;
//left: 25px;
//transform: rotate(90deg);
//border: 15px solid #eee;
/* top right */
top: -30px;
left: 325px;
transform: rotate(90deg);
border: 15px solid #eee;
/* right top */
//top: 25px;
//left: 400px;
//transform: rotate(180deg);
//border: 15px solid #eee;
/* right bottom */
//top: 120px;
//left: 400px;
//transform: rotate(180deg);
//border: 15px solid #eee;
/* bottom left */
//top: 200px;
//left: 90px;
//transform: rotate(-90deg);
//border: 15px solid #333;
/* bottom right */
//top: 200px;
//left: 275px;
//transform: rotate(-90deg);
//border: 15px solid #333;
border-bottom-color: transparent;
border-top-color: transparent;
border-left-color: transparent;
}
.fb_gd_wrap .header {
height: 50px;
line-height: 50px;
background: #eee;
position: relative;
border-radius: 5px 5px 0 0;
}
.fb_gd_wrap .header .text {
font-size: 2.5rem;
font-weight: bold;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin-left: 1rem;
color: #333;
}
.fb_gd_wrap .header .btn {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
font-size: 1.5rem;
border: none;
background: transparent;
color: #666;
}
.fb_gd_wrap .header .btn:hover {
color: #000;
}
.fb_gd_wrap .body {
height: 100px;
background: #eee;
}
.fb_gd_wrap .body .text {
font-size: .9rem;
color: #000;
overflow: hidden;
width: 360px;
margin: 0 20px;
}
.fb_gd_wrap .body .textList {
padding: 0;
margin: 0;
width: 10000px;
font-size: 0;
margin-left: 0;
transition: all .5s;
}
.fb_gd_wrap .body .textList p {
display: inline-block;
font-size: 14px;
width: 360px;
padding: 0;
vertical-align: top;
}
.fb_gd_wrap .footer {
height: 50px;
background: #5893d8;
border-radius: 0 0 5px 5px;
font-size: 0;
}
.fb_gd_wrap .footer .btn {
display: inline-block;
width: 80px;
border: none;
height: 100%;
padding: 0;
font-size: 16px;
vertical-align: top;
color: #fff;
background: transparent;
}
.fb_gd_wrap .footer .btn:hover {
color: #666;
}
.fb_gd_wrap .footer .steps {
display: inline-block;
width: 240px;
background: #333333;
height: 100%;
margin: 0;
padding: 0;
text-align: center;
}
.fb_gd_wrap .footer .dot {
width: 8px;
height: 8px;
background: transparent;
border: 1px solid #666;
margin: 30px 12px 12px 12px;
display: inline-block;
border-radius: 50%;
position: relative;
}
.fb_gd_wrap .footer .line::after {
content: "";
display: block;
background: #666;
width: 24px;
border-top: 1px solid #666;
position: absolute;
top: 4px;
left: 9px;
}
.fb_gd_wrap .footer .dot::before {
content: attr(data-step);
display: block;
color: #fff;
position: absolute;
top: -20px;
left: 1.2px;
font-size: 10px;
}
.fb_gd_wrap .footer .active {
background: #fff;
box-shadow: 0 0 6px rgba(255,255,255,.7);
}
<div id="guidedTour">
<div id="guideContent">
<div >
<span ><i ></i> Guided Tour</span>
<button id="closeBtn"><i ></i></button>
</div>
<div >
<div >
<div id="guideBodyText" >
<p>1: You can create bookmarks for all you favorite screens. You can even bookmark individual records, such as a particular deal number.</p>
<p>2: Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.</p>
<p>3: Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.</p>
<p>4: Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.</p>
<p>5: Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.</p>
<p>6: Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text.</p>
</div>
</div>
</div>
<div >
<button id="guidePrevBtn" >previous</button>
<ul >
<li ></li>
<li ></li>
<li ></li>
<li ></li>
<li ></li>
<li ></li>
</ul>
<button id="guideNextBtn" >next</button>
</div>
</div>
</div>
CodePudding user response:
The most reliable (and non-javascript) way to do it is to make the div with the id guidedTour to be a child of the bookmark div. Add position:relative to the style of the bookmark div and then use position:absolute, top and left css properties to position the arrow of the guidedTour div under the bookmarks div. Use z-index to make sure the popup appears over the parent element.
Without the rest of the html it's not possible to specifically show you how to do this but there is an example here
EDITED TO ADD: See example below using getBoundingClientRect to position the popup centrally below the target element and also ensure the thing doesn't spill offscreen.
window.onload = (event) => {
document.querySelectorAll('.navbar-item').forEach((element) => {
element.addEventListener('click', showPopup);
})
window.addEventListener('resize', positionPopup);
}
function showPopup(event) {
const itemId = event.target.id;
const popup = document.getElementById('popup');
popup.setAttribute('data-target', itemId);
popup.classList.remove('popup-hide');
positionPopup();
}
function hidePopup() {
const popup = document.getElementById('popup');
popup.setAttribute('data-target', "");
popup.classList.add('popup-hide');
}
function positionPopup() {
//Get necessary elements
popup = document.getElementById('popup');
targetId = popup.getAttribute('data-target');
popupArrow = document.getElementById('popupArrow');
//if no target id then popup isn't showing so just exit
if (targetId === '') {
return;
}
//Get bounding rectangles of elements
targetRect = document.getElementById(targetId).getBoundingClientRect();
popupRect = popup.getBoundingClientRect();
popupArrowRect = popupArrow.getBoundingClientRect();
//to position the arrow and make sure we don't spill offscreen we need some info about the target element, the popup and the arrow
const windowWidth = window.innerWidth;
const targetWidth = targetRect.width;
const targetLeft = targetRect.left;
const targetMiddle = targetLeft targetWidth * 0.5;
const targetBottom = targetRect.bottom;
const popupWidth = popupRect.width;
const popupArrowWidth = popupArrowRect.width;
let popupLeft = targetMiddle - popupWidth * 0.5;
//Make sure popup doesn't spill off ot the left or right of the viewport.
if (popupLeft < 0) {
popupLeft = 0;
}
if (popupLeft popupWidth > windowWidth) {
popupLeft = windowWidth - popupWidth;
}
const popupArrowLeft = targetMiddle - popupLeft - popupArrowWidth * 0.5;
//Now position elements
popup.style.top = targetBottom "px";
popup.style.left = popupLeft "px";
popupArrow.style.left = popupArrowLeft "px";
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
}
.popup-hide {
display: none;
}
.popup {
position: fixed;
max-width: 300px;
min-width: 200px;
--popup-bgnd: black;
}
.popup-arrow {
position: relative;
bottom: -0.1rem;
height: 10px;
width: 20px;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
background-color: var(--popup-bgnd);
}
.popup-body {
color: white;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--popup-bgnd);
padding: 0.25rem 0.5rem;
border-radius: 5px;
}
.navbar {
display: flex;
justify-content: space-between;
background: darkmagenta;
padding: 0.5rem;
gap: 0.25rem;
}
.navbar-item {
border: 1px solid magenta;
border-radius: 3px;
padding: 0.25rem;
cursor: pointer;
color: white;
font-weight: bold;
}
<nav >
<div id="#infobox1" >Click me!</div>
<div id="#infobox2" >Click me!</div>
<div id="#infobox3" >Click me!</div>
</nav>
<button onclick="hidePopup()">hide popup</button>
<div id='popup' data-target="">
<div >
<div id="popupArrow">
</div>
</div>
<div >
This is some text and stuff, links, info and more stuff, etc
</div>
</div>