So I wrote this little script in which there are two lists - Completed/Active Tasks, you can switch the task list by clicking the button, and you can read more information about the task by clicking "More Info". When more info is clicked, a new div element is created and I want to follow its host element's Y position, and it works half way. This is what it looks like: Enter image description here
This is a bug, I'm pretty sure this error occurs when the scrollable element scrollTop
is not 0 (it is created the right way and whenever I start scrolling it Jump up immediately and cover the mission itself): Enter image description here.
This is the part of my code that is responsible for identifying the px amount of scrolling, the scroll direction and moving the "more info" div element, and the part responsible for creating it, I don't know where this is the problem because I have no idea about I'm still new to coding overall, and I'm not very familiar with css/html.
createTooltip() { const tooltipElement = document.createElement('div'); tooltipElement.className = 'card'; const toolTipTemplate = document.getElementById('tooltip'); const tooltipBody = document.importNode(toolTipTemplate.content, true); tooltipBody.querySelector('p').textContent = this.text; tooltipElement.append(tooltipBody); const hostElPosLeft = this.hostElement.offsetLeft; const hostElPostop = this.hostElement.offsetTop; const hostElHeight = this.hostElement.clientHeight; const parentElementScrolling = this.hostElement.parentElement.scrollTop; const x = hostElPosLeft + 20; const y = hostElPostop + hostElHeight - parentElementScrolling - 10; tooltipElement.style.position = 'absolute'; tooltipElement.style.left = x + 'px'; tooltipElement.style.top = y + 'px'; const scrollHandler = () => { ulElement.addEventListener('scroll', yLogger); }; tooltipElement.addEventListener('click', this.closeToolTip); tooltipElement.addEventListener('click', scrollHandler); this.element = tooltipElement; const ulElement = this.hostElement.parentElement; console.log(ulElement); let pxPosition = [0]; let currentY = y; const yLogger = () => { let scrollDirection; let pxScrolled = 0; if (pxPosition.length <= 1) { pxPosition.push(ulElement.scrollTop); } else { pxPosition.push(ulElement.scrollTop); pxPosition.shift(ulElement); } console.log(pxPosition); if (pxPosition[1] < pxPosition[0]) { scrollDirection = 'up'; pxScrolled = pxPosition[0] - pxPosition[1]; } else if (pxPosition[0] < pxPosition[1]) { scrollDirection = 'down'; pxScrolled = pxPosition[1] - pxPosition[0]; } console.log(pxScrolled); console.log(scrollDirection); if (scrollDirection === 'down') { currentY = currentY - pxScrolled; console.log(currentY); tooltipElement.style.top = currentY + 'px'; } else { scrollDirection === 'up'; currentY = currentY + pxScrolled; console.log(currentY); tooltipElement.style.top = currentY + 'px'; } }; this.hostElement.closest('ul').addEventListener('scroll', yLogger); } }
I'm adding the HTML and CSS snippets, although I don't think they're necessary since it was written by the instructor of the course I'm taking.
This is the HTML snippet:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Project Board</title> <link rel="stylesheet" href="assets/styles/app.css" /> <script src="assets/scripts/app.js" defer></script> </head> <body> <template id="tooltip"> <h2>More Info</h2> <p></p> </template> <header id="main-header"> <h1>Project Planner</h1> </header> <section id="active-projects"> <header> <h2>Active Projects</h2> </header> <ul> <li id="p1" data-extra-info="Got lifetime access, but would be nice to finish it soon!" class="card" draggable="true" > <h2>Finish the Course</h2> <p>Finish the course within the next two weeks.</p> <button class="alt">More Info</button> <button>Finish</button> </li> <li id="p2" data-extra-info="Not really a business topic but still important." class="card" draggable="true" > <h2>Buy Groceries</h2> <p>Don't forget to pick up groceries today.</p> <button class="alt">More Info</button> <button>Finish</button> </li> </ul> </section> <section id="finished-projects"> <header> <h2>Finished Projects</h2> </header> <ul> <li id="p3" data-extra-info="Super important conference! Fictional but still!" class="card" draggable="true" > <h2>Book Hotel</h2> <p> Academind conference takes place in December, don't forget to book a hotel. </p> <button class="alt">More Info</button> <button>Activate</button> </li> </ul> </section> <footer> <button id="im-done-btn">I'm Done!</button> </footer> </body> </html>
Here is the relevant CSS snippet:
* { box-sizing: border-box; } html { font-family: sans-serif; } body { margin: 0; } #main-header { width: 100%; height: 6rem; display: flex; justify-content: center; align-items: center; background: #ff0062; } #main-header h1 { color: white; margin: 0; } footer { position: absolute; bottom: 0; left: 0; width: 100%; text-align: center; } ul { list-style: none; margin: 0; padding: 0; } li { margin: 1rem 0; } section { margin: 1rem auto; width: 40rem; max-width: 90%; } section ul { padding: 1rem; max-height: 20rem; overflow: scroll; } section > h2 { color: white; margin: 0; } button { font: inherit; background: #ff0062; color: white; border: 1px solid #ff0062; padding: 0.5rem 1.5rem; cursor: pointer; } button.alt { background: white; color: #ff0062; } button:focus { outline: none; } button:hover, button:active { background: #ff2579; border-color: #ff2579; color: white; } .card { border-radius: 10px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26); padding: 1rem; background: white; } .droppable { background: #ffe0ec } #active-projects { border: 1px solid #870099; } #active-projects > header { background: #870099; padding: 1rem; display: flex; justify-content: space-between; align-items: center; } #active-projects header h2 { color: white; margin: 0; } #finished-projects { border: 1px solid #535353; } #finished-projects > header { background: #535353; padding: 1rem; display: flex; justify-content: space-between; align-items: center; } #finished-projects header h2 { color: white; margin: 0; }
This problem can be solved with CSS, you can remove the following from the Javascript code:
Instead, change the CSS by adding the following:
To do this, the
div.card
element you create in Javascript code must be a child of the correspondingli.card
element. I also (probably wrongly) assumed that your original code was similar to the code I found earlier and posted it in the comments of your question since I couldn't run your original code.Your
position:absolute
initially doesn't work because theli.card
parent's position is not explicitly set and defaults tostatic
.EditForgot to mention the z-index bit. This is required because your infobox won't be fully visible (it will be under the next
li.card
element).