I'm trying to clone a tooltip div and append it to the document body while also centering around it's original parent.
window.addEventListener("load", function() {
const tooltipActivator = document.querySelectorAll("[data-onsitetooltip]");
for(let i = 0; i < tooltipActivator.length; i++) {
if(tooltipActivator[i] != undefined) {
let added = false;
tooltipActivator[i].addEventListener("mouseenter", function(e) {
const clone = tooltipActivator[i].querySelector(".onsiteTooltip").cloneNode(true),
elemRect = tooltipActivator[i].getBoundingClientRect(),
offset_top = elemRect.top - document.body.getBoundingClientRect().top,
offset_left = elemRect.left;
clone.style.visibility = "visible";
clone.style.opacity = "1";
clone.style.top = offset_top + parseInt(tooltipActivator[i].dataset.onsitetooltiptop) + "px";
clone.style.left = offset_left + "px";
clone.style.transform = "translateX(-"+tooltipActivator[i].offsetWidth/2+"px)";
clone.style.pointerEvents = "none";
document.body.appendChild(clone);
});
tooltipActivator[i].addEventListener("mouseleave", function(e) {
const tooltipToRemove = document.querySelectorAll("body > .onsiteTooltip");
for(let z = 0; z < tooltipToRemove.length; z++) {
if(tooltipToRemove[z] != undefined) {
document.body.removeChild(tooltipToRemove[z]);
}
}
});
}
}
});
.onsiteTooltip {
visibility: hidden;
opacity: 0;
width: 25em;
cursor: auto;
background: #0c1633;
padding: 1em;
#include border-radius(0.25rem);
#include box-shadow($shadow-big);
position: absolute;
z-index: 4;
border: 1px solid rgba(0, 0, 0, 0.05);
#include transition(visibility 0s, opacity 0.2s linear);
font-size: 0.9em;
}
.myDiv { height: 100px; background: red; }
<div class="myDiv" data-onsitetooltip data-onsitetooltiptop="70">
<div class="onsiteTooltip">Hello World</div>
</div>
The goal is to make it so when appended to the body, it should be below and centered around the element with the data-onsitetooltip property, without appending it as a child to that element.
Depending on the element that hold the tooltip, it works sometimes, but on other elements it sometimes isn't centered and misaligned.
Like this: http://prntscr.com/op0wuk
How can I accomplish this?
EDIT: I've tried to set the offset left to 50% of the parent and then -50% on the tooltip like you would do in CSS but that did not work either.
Related
hello everyone hope you guys are having a great day!
so, i am building a simple game where I use a custom-made cursor as the aim for shooting div elements moving around the screen as the enemies and when i apply the "pointerdown" event i want the enemy to change its color. however, every time i hover over the enemy the cursor falls behind witch i don't understand why, and when i use the z-index property it will prevent the "pointerdown" event from firing. if some cool OG programmer can help me, it would mean a lot to me.
style
* {
margin: 0;
padding: 0;
cursor: none;
}
.aim {
position: absolute;
background: black;
width: 10px;
height: 10px;
border-radius: 50%;
transform: translate(-50%, -50%);
}
.enemy {
position: absolute;
border: 3px solid black;
background-color: blue;
width: 50px;
height: 50px;
}
javascript
const body = document.body;
const aim = document.createElement("div");
const enemy = document.createElement("div");
body.appendChild(aim);
body.appendChild(enemy);
aim.classList.add("aim");
enemy.classList.add("enemy");
let enemy_X_position = 0;
let enemy_Y_position = 0;
let enemy_X_distance = 1;
let enemy_Y_distance = 1;
function Flight()
{
enemy.style.left = enemy_X_position + "px";
enemy.style.top = enemy_Y_position + "px";
}
setInterval(function()
{
enemy_X_position += enemy_X_distance;
enemy_Y_position += enemy_Y_distance;
if ((enemy_X_position + enemy.offsetWidth) >= window.innerWidth || enemy_X_position <= 0)
enemy_X_distance = -enemy_X_distance;
if ((enemy_Y_position + enemy.offsetHeight) >= window.innerHeight || enemy_Y_position <= 0)
enemy_Y_distance = -enemy_Y_distance;
Flight();
},1000/60)
window.onmousemove = function()
{
aim.style.left = event.pageX + "px";
aim.style.top = event.pageY + "px";
}
enemy.onpointerdown = function()
{
event.target.style.background = "red";
}
enemy.onpointerup = function()
{
event.target.style.background = null;
}
Update
The event is not triggering because pointerdown was received by aim when it sits on top of enemy.
To solve this, add pointer-events: none on aim class to prevent it from being the target of a pointer event.
More about pointer-events
Hope this will help!
.aim {
position: absolute;
background: black;
width: 10px;
height: 10px;
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
Original
Perhaps an over simplified solution, but it seems that if you reverse the order of appendChild, the aim should be stacked over enemy without additional styling.
Example:
body.appendChild(enemy);
body.appendChild(aim);
Because both elements are child of body, Unless there is other styling that override this stacking, the later one should be on top.
I am trying to create a vertical slide show on scroll. One picture-screen glide over the next one, and then the second over the third, and so on…
HTML/CSS structure looks as following: external container has display property relative. Inside it there are several containers with images with the property fixed, so that they are all as a card deck and you pull card by card from the top.
JavaScript function should load the first pare of image-pages and follow the amount of scrolled distance changing the index of the image-page and changing the z-index of the layer (the top one: 2, the one blow: 1 and so on...)
var mansDok = []; var paklajAttal = [];
// Find all the slides containers
mansDok = document.getElementsByClassName("slaide");
// Find all the slides IDs
for(i=0; i<mansDok.length; i++) {
paklajAttal[i] = mansDok[i].id;
}
// Height of the browser window
var logAugst = document.documentElement.clientHeight;
// Start function on scrolling the contents
window.onscroll = function() {vertikSlaidrade()};
//
// Slideshow function
function vertikSlaidrade() {
var k = 0; var i = 0, winScroll;
// How far the screen been scrolled
winScroll = document.documentElement.scrollTop || document.body.scrollTop;
// Change slides while scrolling
if(winScroll <= logAugst * 1) {
document.getElementById(paklajAttal[k]).style.zIndex = "2";
document.getElementById(paklajAttal[k]).style.position = "relative";
document.getElementById(paklajAttal[k+1]).style.display = "block";
document.getElementById(paklajAttal[k+1]).style.position = "fixed";
} else if(winScroll <= logAugst * 2) {
document.getElementById(paklajAttal[k+1]).style.zIndex = "3";
document.getElementById(paklajAttal[k+1]).style.position = "relative";
document.getElementById(paklajAttal[k+2]).style.display = "block";
document.getElementById(paklajAttal[k+2]).style.position = "fixed";
} else if(winScroll <= logAugst * 2.8) {
document.getElementById(paklajAttal[k+2]).style.zIndex = "4";
document.getElementById(paklajAttal[k+2]).style.position = "relative";
document.getElementById(paklajAttal[k+3]).style.display = "block";
document.getElementById(paklajAttal[k+3]).style.position = "fixed";
} else if(winScroll > logAugst * 2.8) {
// Run reset function by the end of slides
atiestat();
}
}
// Function to reset the slides properties
function atiestat() {
for(var i=0; i<mansDok.length; i++) {
document.getElementById(paklajAttal[i]).style.zIndex = "0";
document.getElementById(paklajAttal[i]).style.position = "absolute";
document.getElementById(paklajAttal[i]).style.display = "none";
}
// Show the first pair of slides
document.getElementById(paklajAttal[0]).style.display = "block";
document.getElementById(paklajAttal[0]).style.zIndex = "2";
document.getElementById(paklajAttal[1]).style.position = "fixed";
document.getElementById(paklajAttal[1]).style.zIndex = "1";
}
* {box-sizing: border-box;}
html, body{
height: 100%;
margin: 0px;
padding: 0px;
background-color: #000;
font-size: 1em;
}
main {
position: relative;
margin: 0px;
padding: 0px;
width: 100%;
overflow-x: hidden;
overflow-y: auto;
}
/* Page with slide */
.slaide {
position: absolute;
top: 0px;
left: 0px;
z-index: 0;
margin: 0px;
padding: 0px;
width: 100%;
display: none;
}
.slaide img {
width: 1230px; /* Doesn't work below this value !?!? */
}
/* Empty filler */
.tukss {
display: block;
margin: 0px;
padding: 0px;
height: 1000px; /* Do NOT reduce this value!!! */
}
<main>
<div class="slaide" id="lapa1" style="display: block;">
<img src="https://www.w3schools.com/howto/img_parallax.jpg">
</div>
<div class="slaide" id="lapa2">
<img src="https://www.w3schools.com/howto/img_parallax2.jpg">
</div>
<div class="slaide" id="lapa3">
<img src="https://www.w3schools.com/howto/img_parallax3.jpg">
</div>
<div class="tukss" id="tukss"></div>
</main>
May be its not the most elegant version of JS code, but everything works perfectly as I wanted. Somehow it doesn’t work if I change the image size below 1230px or to 100% and reduce the width of the browser window. (Images are from W3Schools.com)
I would appreciate if somebody could help me out with this situation.
I have a function which counts the number of line breaks in a div, depending on the width of the window. While the functions works fine when placed in the $(window).on('resize') function, it does not work when put in $(document).ready() function. I want it to work right on page load, and also window resize, how do I support both?
JSFiddle
Javascript/jQuery:
// functions called in both document.ready() and window.resize
$(document).ready(function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Ready");
});
$(window).on('resize', function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Number of lines: " + lineCount);
});
// calculates the amount of lines required to hold the items
function getLineCount() {
var lineWidth = $('.line').width();
var itemWidthSum = 0;
var lineCount=1;
$('.item').each(function(index, element) {
if((lineWidth - itemWidthSum) > ($(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = $(element).outerWidth();
}
});
return lineCount;
}
// overlays rows for the amount of linebreaks
function postItems(lineCount){
var container = $('<div />');;
for(var i = 1; i <= lineCount; i++) {
container.append('<div class="line">' + i + '</div>');
}
$('.line-wrap').html(container);
}
You'll see at the start of the page, it incorrectly shows 17 lines, and then once you resize it will show the correct amount.
The issue lies in the first line of getLineCount(). Originally you had
var lineWidth = $('.line').width();
but no elements with the class "line" exist yet on your page (since they get added in your postItems() method. I changed it to
var lineWidth = $(".container").width();
instead, and now your code should be working. Snippet posted below:
$(document).ready(function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Ready");
});
$(window).on('resize', function(){
var lineCount = getLineCount();
postItems(lineCount);
$('.answer').text("Number of lines: " + lineCount);
});
// calculates the amount of lines required to hold the items
function getLineCount() {
var lineWidth = $('.container').width();
var itemWidthSum = 0;
var lineCount=1;
$('.item').each(function(index, element) {
if((lineWidth - itemWidthSum) > ($(element).outerWidth())) {
itemWidthSum = itemWidthSum + $(element).outerWidth();
} else {
lineCount++;
itemWidthSum = $(element).outerWidth();
}
});
return lineCount;
}
// overlays rows for the amount of linebreaks
function postItems(lineCount){
var container = $('<div />');;
for(var i = 1; i <= lineCount; i++) {
container.append('<div class="line">' + i + '</div>');
}
$('.line-wrap').html(container);
}
body {
text-align:center;
}
.answer {
position: fixed;
left: 0;
bottom: 0;
}
.container {
position: relative;
width: 50%;
margin: 0 auto;
border: 1px solid #e8e8e8;
display: inline-block;
}
.item {
height: 50px;
padding:0 10px;
background-color: #aef2bd;
float: left;
opacity:0.2;
white-space: nowrap;
}
.line-wrap {
position: absolute;
border: 1px solid red;
width: 100%;
height: 100%;
top:0; left: 0;
}
.line {
height: 50px;
width: 100%;
background-color: blue;
opacity:0.5;
color: white;
transition: all 0.5s ease;
}
.line:hover {
background-color: yellow;
color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item-wrap">
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
<div class="item">Computer Science</div>
<div class="item">Language</div>
<div class="item">Marketing</div>
<div class="item">Biology</div>
</div>
<div class="line-wrap">
</div>
</div>
<h1 class="answer"></h1>
I need help for an effect I'm trying to create: I made a CSS triangle and I want it to be fixed on the Y-axis but follow the mouse on his X-axis (didn't you read the title ?!). If it's not clear, I want it to move only to the left/right but not up/down. I managed to apply a js script I found on the internet to my triangle but I can't figure out how to change it to stop it from moving on the Y-axis. When I try to change anything, the whole thing doesn't move anymore. Can some one help me ?
// Here get the Div that you want to follow the mouse
var div_moving = document.getElementById('div_moving');
// Here add the ID of the parent element
var parent_div = 'parent_div';
// object to make a HTML element to follow mouse cursor ( http://coursesweb.net/ )
var movingDiv = {
mouseXY: {}, // will contain the X, Y mouse coords inside its parent
// Get X and Y position of the elm (from: vishalsays.wordpress.com/ )
getXYpos: function(elm) {
x = elm.offsetLeft; // set x to elm’s offsetLeft
y = elm.offsetTop; // set y to elm’s offsetTop
elm = elm.offsetParent; // set elm to its offsetParent
//use while loop to check if elm is null
// if not then add current elm’s offsetLeft to x, offsetTop to y and set elm to its offsetParent
while(elm != null) {
x = parseInt(x) + parseInt(elm.offsetLeft);
y = parseInt(y) + parseInt(elm.offsetTop);
elm = elm.offsetParent;
}
// returns an object with "xp" (Left), "=yp" (Top) position
return {'xp':x, 'yp':y};
},
// Returns object with X, Y coords inside its parent
getCoords: function(e) {
var xy_pos = this.getXYpos(e.target);
// if IE
if(navigator.appVersion.indexOf("MSIE") != -1) {
var standardBody = (document.compatMode == 'CSS1Compat') ? document.documentElement : document.body;
x = event.clientX + standardBody.scrollLeft;
y = event.clientY + standardBody.scrollTop;
}
else {
x = e.pageX;
y = e.pageY;
}
x = x - xy_pos['xp'];
y = y - xy_pos['yp'];
return {'xp':x, 'yp':y};
}
};
// registers 'mousemove' event to parent_div
document.getElementById(parent_div).addEventListener('mousemove', function(e){
mouseXY = movingDiv.getCoords(e);
div_moving.style.left = mouseXY.xp + 8 +'px';
div_moving.style.top = mouseXY.yp - 8 +'px';
});
#parent_div {
position: relative;
width: 100%;
height: 800px;
margin: 1em auto;
border; 1px solid #333;
background: #fefebe;
}
#div_moving {
position: absolute;
width: 41em;
height: 31em;
margin: 0;
border: 1px solid #33f;
background: #88ee99;
overflow:hidden;
}
.container {
width: 37.5em;
height: 37.5em;
position: relative;
border-top: 20px solid #e74c3c;
left:3%;
}
.triangle {
position: relative;
margin: auto;
top: -20em;
left: 0;
right: 0;
width:31em;
height:31em;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
border-right: 20px solid #e74c3c;
border-bottom: 20px solid #e74c3c;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent_div">
<div id="div_moving">
<div class="container">
<div class="triangle"></div>
</div>
</div>
Content in parent ...
</div>
I just reformatted a little, then commented one line and it's working in Chrome on my machine. Is this what you're looking for?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script language="javascript">
// object to make a HTML element to follow mouse cursor ( http://coursesweb.net/ )
var movingDiv = {
mouseXY: {}, // will contain the X, Y mouse coords inside its parent
// Get X and Y position of the elm (from: vishalsays.wordpress.com/ )
getXYpos: function(elm) {
x = elm.offsetLeft; // set x to elm’s offsetLeft
y = elm.offsetTop; // set y to elm’s offsetTop
elm = elm.offsetParent; // set elm to its offsetParent
//use while loop to check if elm is null
// if not then add current elm’s offsetLeft to x, offsetTop to y and set elm to its offsetParent
while(elm != null) {
x = parseInt(x) + parseInt(elm.offsetLeft);
y = parseInt(y) + parseInt(elm.offsetTop);
elm = elm.offsetParent;
}
// returns an object with "xp" (Left), "=yp" (Top) position
return {'xp':x, 'yp':y};
},
// Returns object with X, Y coords inside its parent
getCoords: function(e) {
var xy_pos = this.getXYpos(e.target);
// if IE
if(navigator.appVersion.indexOf("MSIE") != -1) {
var standardBody = (document.compatMode == 'CSS1Compat') ? document.documentElement : document.body;
x = event.clientX + standardBody.scrollLeft;
y = event.clientY + standardBody.scrollTop;
}
else {
x = e.pageX;
y = e.pageY;
}
x = x - xy_pos['xp'];
y = y - xy_pos['yp'];
return {'xp':x, 'yp':y};
}
};
$(document).ready(function() {
// Here get the Div that you want to follow the mouse
var div_moving = document.getElementById('div_moving');
// Here add the ID of the parent element
var parent_div = 'parent_div';
// registers 'mousemove' event to parent_div
document.getElementById(parent_div).addEventListener('mousemove', function(e){
mouseXY = movingDiv.getCoords(e);
div_moving.style.left = mouseXY.xp + 8 +'px';
//div_moving.style.top = mouseXY.yp - 8 +'px';
});
});
</script>
<style>
#parent_div {
position: relative;
width: 100%;
height: 800px;
margin: 1em auto;
border; 1px solid #333;
background: #fefebe;
}
#div_moving {
position: absolute;
width: 41em;
height: 31em;
margin: 0;
border: 1px solid #33f;
background: #88ee99;
overflow:hidden;
}
.container {
width: 37.5em;
height: 37.5em;
position: relative;
border-top: 20px solid #e74c3c;
left:3%;
}
.triangle {
position: relative;
margin: auto;
top: -20em;
left: 0;
right: 0;
width:31em;
height:31em;
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
border-right: 20px solid #e74c3c;
border-bottom: 20px solid #e74c3c;
}
</style>
</head>
<body>
<div id="parent_div">
<div id="div_moving">
<div class="container">
<div class="triangle"></div>
</div>
</div>
Content in parent ...
</div>
</body>
</html>
Differences:
Load the JQuery script first
Process the listener in a ready function so all the content has been loaded
Comment out the Y positioning
EDIT: I found a solution to my problem.
So here the problems and what I did:
I wanted the object to move only on X-axis and not Y: IgnusFast found out the line to delete was "div_moving.style.top = mouseXY.yp - 8 +'px';"
I wanted it to stop staggering when the mouse passed over it: deleted "parseInt(x) +" in "while(elm != null) {x = parseInt(x) + parseInt(elm.offsetLeft); elm = elm.offsetParent;}" (makes the div stay where it is when not sure.
I wanted it to center with the mouse instead of being on its right: original was " div_moving.style.left = mouseXY.xp + 8 +'px';" wich made it go 8 pixels to the right of the current mouse's coordinates so I just used a negative number and place like this :" div_moving.style.left = mouseXY.xp + -350 +'px';"
I going to create a scroll and stick div which has to stick on the top of the page but while scrolling down the div next to stickdiv automatically stick to the div before to sticky div
var left = document.getElementsByClassName("stickdiv");
for (var i = 0; i < left.length; i++) {
var stop = (left[0].offsetTop);
window.onscroll = function(e) {
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
// left.offsetTop;
if (scrollTop >= stop) {
// get array item by index
left[0].classList.add('stick'); //adding a class name
} else {
// get array item by index
left[0].classList.remove('stick');
}
}
}
.stickdiv {
height: 50vh!important;
width: 100vh!important;
background-color: green!important;
}
.stick {
position: fixed;
top: 0;
margin: 0 0
}
#right {
float: right;
width: 100px;
height: 1000px;
background: red;
}
.des {
height: 300px;
width: 100%;
background-color: #000;
}
<div class="des"></div>
<div class="stickdiv"></div>
<div id="right"></div>
Example : green color div is the sticky div but after scrollingdown , red is also going to stick , I've tried position absolute in css but not working how to fix it
Here is the code to make green sticky when scrolling.
$ = document.querySelectorAll.bind(document);
// how far is the green div from the top of the page?
var initStickyTop = $(".stickdiv")[0].getBoundingClientRect().top + pageYOffset;
// clone the green div
var clone = $(".stickdiv")[0].cloneNode(true);
// hide it first
clone.style.display = "none";
// add it to dom
document.body.appendChild(clone);
addEventListener("scroll",stick=function() {
// if user scroll past the sticky div
if (initStickyTop < pageYOffset) {
// hide the green div but the div still take up the same space as before so scroll position is not changed
$(".stickdiv")[0].style.opacity = "0";
// make the clone sticky
clone.classList.add('stick');
// show the clone
clone.style.opacity="1";
clone.style.display = "block";
} else {
// make the clone not sticky anymore
clone.classList.remove("stick");
// hide it
clone.style.display = "none";
// show the green div
$(".stickdiv")[0].style.opacity="1";
};
});
// when resize, recalculate the position of the green div
addEventListener("resize", function() {
initStickyTop = $(".stickdiv")[0].getBoundingClientRect().top + pageYOffset;
stick();
});
.stickdiv {
height: 50vh!important;
width: 100vh!important;
background-color: green!important;
}
.stick {
position: fixed;
top: 0;
margin: 0 0
}
#right {
float: right;
width: 100px;
height: 1000px;
background: red;
}
.des {
height: 300px;
width: 100%;
background-color: #000;
}
<div class="des"></div>
<div class="stickdiv"></div>
<div id="right"></div>
JS FIDDLE
you might want to remove the stickdiv class and add it accordingly
if (scrollTop >= stop) {
// get array item by index
left[0].classList.add('stick'); //adding a class name
left[0].classList.remove('stickdiv');
} else {
// get array item by index
left[0].classList.remove('stick');
left[0].classList.add('stickdiv');
}