Preserve mouse offset to parent when clicking - javascript

I'm trying to get the mouse offset inside a square, but when I click on its children, the offset changes, now returning the mouse offset inside the children, and not the parent.
What I would like to achieve is to get the mouse offset inside the parent, even if I click inside the children.
Thanks a lot!
Below is an example of the problem. (Look in the console)
$("#parent").click(function(e){
console.log(e.offsetX, e.offsetY)
});
.square{
position: relative;
height: 200px;
width: 200px;
background-color: red;
}
.small{
position: absolute;
top: 25px;
right: 25px;
height: 50px;
width: 50px;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="square" id="parent">
<div class="square small"></div>
</div>

You can use
e.target
to get the element clicked, as this is the parent element that the click has bubbled up to.
Then combine with .getBoundingClientRect() to get its position, gives:
$("#parent").click(function(e) {
var rect = e.target.getBoundingClientRect();
//console.log(e.offsetX, e.offsetY)
//console.log(rect.left, rect.top)
console.log(rect.left + e.offsetX, rect.top + e.offsetY)
});
.square {
position: relative;
height: 200px;
width: 200px;
background-color: red;
}
.small {
position: absolute;
top: 25px;
right: 25px;
height: 50px;
width: 50px;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="square" id="parent">
<div class="square small"></div>
</div>

Solution
Add a transparent background and full height and width child div to the parent (#parent-overlay) and check for its offset instead.
Why
The offsets are gotten from the click event and the click event was on the child. So while in the child, you can't get an offset from the parent (the event was registered on the child).
Adding a full width and height overlay, that matches the parent, and getting offset from there should give you what you want.
$("#parent-overlay").click(function(e) {
console.log(e.offsetX, e.offsetY);
});
.square{
position: relative;
height: 200px;
width: 200px;
background-color: red;
}
.small{
position: absolute;
top: 25px;
right: 25px;
height: 50px;
width: 50px;
background-color: blue;
z-index: 1;
}
#parent-overlay {
position: absolute;
z-index: 3;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: transparent;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="square" id="parent">
<div id="parent-overlay"></div>
<div class="square small"></div>
</div>

Adding pointer-events: none; to the css for the class "small" disables clicking on the element.
$("#parent").click(function(e){
console.log(e.offsetX, e.offsetY)
});
.square{
position: relative;
height: 200px;
width: 200px;
background-color: red;
}
.small{
position: absolute;
top: 25px;
right: 25px;
height: 50px;
width: 50px;
background-color: blue;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="square" id="parent">
<div class="square small"></div>
</div>

Related

Draw div with scrollHeight

I need to draw a div with height of entire document. An id named "background" should have the height equal to the content. I am trying to get the result by getting the scrollHeight. I already know the height from the code below but I don't know how to put the value into css. Thank you in advance for any help!
document.getElementById("background").text = ("scrollHeight : " + $(".demo").prop("scrollHeight"));
.content {
background: #eee;
width: 100%;
height: 2000px;
}
#background {
width: 200px;
background: #000;
position: absolute;
top: 0;
left: 0;
height: 100%;
}
<div id="background"></div>
<div class="content"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
One way is to use getComputedStyle
document.querySelector('#background').setAttribute('style','height:'+ window.getComputedStyle(document.querySelector('.content')).getPropertyValue('height'));
.content {
background: #eee;
width: 100%;
height: 2000px;
}
#background {
width: 200px;
background: #000;
position: absolute;
top: 0;
left: 0;
/*height: 200px;*/
}
<div id="background"></div>
<div class="content"></div>
To have the same height for the background every time you change the content height it has to be a child of content.
And for the background set the height to inherit
.content {
background: #eee;
width: 100%;
height: 2000px;
}
#background {
width: 200px;
background: #000;
position: absolute;
top: 0;
left: 0;
height: inherit;
}
<div class="content">
<div id="background"></div>
</div>
Hope I could help you.
document.getElementById("background").style.height = <get .content height>
https://www.w3schools.com/jsref/prop_style_height.asp

Element to be only visible where it's overlapping specific other element?

I'm trying to achieve the following:
I have an image in the background and a moving element in the foreground. I want to show the foreground element only while it's overlapping the background element. In the snippet below, the globe represents the background element, and the red square is the foreground element.
Here is a demonstration what I want it to look like:
The first things that came to mind were the css clip-path and mask-image properties, but I couldn't really get it to work.
Thanks in advance!
.world {
position: absolute;
top: 100px;
left: 100px;
}
.world img{
width: 300px;
height: auto;
}
.testelement {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
left: 75px;
top: 200px;
}
<div class="world">
<img src="https://png2.kisspng.com/sh/bfd975773964bd26a28b9eecfb96b970/L0KzQYm3U8I6N5hwj5H0aYP2gLBuTgdwep1pRdl1b3LoPbTzigAuaaN5RddqcoTrPbTokwRwd58yTdNrZETkdom4VvU3QWczUKgBMEK2R4a4VcIzO2Y5UaUBMEm2SHB3jvc=/kisspng-world-globe-clip-art-earth-cartoon-5abd4af816e696.8660237515223549360938.png"/>
</div>
<div class="testelement">
</div>
Here is an idea with mask. Simply use the same image inside the mask on the container where the size is defined by the image. Then make the red square inside that container:
.world {
position: absolute;
top: 100px;
left: 100px;
width:300px;
-webkit-mask:url(https://i.ibb.co/2qmJjxR/kisspng-world-globe-clip-art-earth-cartoon-5abd4af816e696-8660237515223549360938.png)
center/contain no-repeat;
mask:url(https://i.ibb.co/2qmJjxR/kisspng-world-globe-clip-art-earth-cartoon-5abd4af816e696-8660237515223549360938.png)
center/contain no-repeat;
}
.world img{
width: 100%;
display:block;
}
.testelement {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
left: -20px;
top: 150px;
transition:1s all;
}
.world:hover .testelement{
left:20px;
}
<div class="world">
<img src="https://i.ibb.co/2qmJjxR/kisspng-world-globe-clip-art-earth-cartoon-5abd4af816e696-8660237515223549360938.png">
<div class="testelement">
</div>
</div>

Making divs focus and change z-index

So basically we have a concept picture: http://imgur.com/a/Z38Fy
Each of these window's is a div element on the site that on click should get on top. Let's say we click on window #2, that means that window 2 is on top now and window 1 is behind it. This is literally how the Windows operating system individual windows work.
Is this possible using jQuery and javascript?
Is this what you are looking for?
Set the z-index when click on a div, and set the z-index of the others to something lower
$("div").click(function() {
$("div").not(this).css("z-index", "1")
$(this).css("z-index", "2")
})
div {
position: absolute;
height: 100px;
width: 100px;
border: 1px solid #000;
background-color:white;
}
.one {}
.two {
top: 40px;
left: 100px;
}
.three {
top: 70px;
left: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
A quick example
$(".window").on("click", function() {
$(".window").css("z-index", 0);
$(this).css("z-index", 1);
});
.window {
width: 250px;
height: 250px;
}
.window:nth-child(1) {
background-color: lightblue;
position: absolute;
left: 20px;
top: 20px;
}
.window:nth-child(2) {
background-color: purple;
position: absolute;
left: 100px;
top: 60px;
}
.window:nth-child(3) {
background-color: darkgreen;
position: absolute;
left: 180px;
top: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="window">W1</div>
<div class="window">W2</div>
<div class="window">W3</div>
</div>
As Carsten Løvbo Andersen answered, yes! it is posible, and he gave us an example that works using jQuery and javascript.
I just want to point out that it can be done by using css and html only, what answer the title of this question "Making divs focus and change z-index".
See modified Carsten Løvbo Andersen example:
.container {
position: absolute;
height: 100px;
width: 100px;
border: 1px solid #000;
background-color: white;
z-index: 0;
}
.container:focus {
z-index: 1;
}
.one {}
.two {
top: 40px;
left: 100px;
}
.three {
top: 70px;
left: 40px;
}
<div class="container one" tabIndex="0">1</div>
<div class="container two" tabIndex="0">2</div>
<div class="container three" tabIndex="0">3</div>

Website with a tricky structure with JS

Here is my tricky problem. I'm trying to do this:
http://www.hostingpics.net/viewer.php?id=767312test.gif
(More clear than an explication I think).
My structure :
<header></header>
<div class="section">
<div class="text"></div>
<div class="content"></div>
<div class="img"><img src="img1.png"/></div>
</div>
<div class="section">
<div class="text"></div>
<div class="content"></div>
<div class="img"><img src="img2.png"/></div>
</div>
<div class="section">
<div class="text"></div>
<div class="content"></div>
<div class="img"><img src="img3.png"/></div>
</div>
<footer></footer>
Important informations :
"Header" is fix
"Content" fit to the screen less the height of header
Every "section" are the same but with different content
When the image comes to an end, the "content" div is unfixed.
I am using "section" for implementing a next and previous button in the header (with anchors).
My problem is the scrolling part. I am really lost when I try to fix the "content" div. I don't know how to fix everything except the scroll of the image in the active "img" div when the active "content" div hits the header. (Everyone follows? Look here : http://www.hostingpics.net/viewer.php?id=767312test.gif
For the scrolling part in the "img" div, I was thinking use a sort of "overflow:scroll" but the scrollbar is really awful.
I don't know if it's enough clear. If there is any problem I can complete my problem. I am not very comfortable with complex structures in html with JS.
Thanks for your help!
This is pretty close to what you're asking for (using CSS only).
This relies on the fact that the backgrounds are solid colors. It uses various specifically-defined height properties as well that match some padding properties.
The .top-bar and .bottom-bar elements can probably be changed to pseudo elements if you don't want the extra HTML.
HTML:
<header>Header</header>
<div class="top-bar"></div>
<div class="bottom-bar"></div>
<div class="section">
<div class="text">Section 1 Text</div>
<div class="content">
<div class="img"><img src="http://placekitten.com/100/1000"/></div>
</div>
</div>
<div class="section">
<div class="text">Section 2 Text</div>
<div class="content">
<div class="img"><img src="http://placekitten.com/200/2000"/></div>
</div>
</div>
<div class="section">
<div class="text">Section 3 Text</div>
<div class="content">
<div class="img"><img src="http://placekitten.com/300/3000"/></div>
</div>
</div>
<footer>Footer</footer>
CSS:
body {
margin: 0;
padding: 100px 0 0;
}
header {
background-color: red;
height: 100px;
position: fixed;
top: 0;
width: 100%;
z-index: 10;
}
footer {
background-color: blue;
height: 100px;
}
.section {
min-height: 400px;
}
.text {
background-color: aqua;
height: 50px;
}
.content {
background-color: green;
min-height: 100%;
padding: 40px 0;
position: relative;
}
.img {
background-color: yellow;
min-height: 70%;
margin: 0 auto;
padding: 40px 0;
text-align: center;
width: 80%;
}
.img > img {
vertical-align: middle;
}
.top-bar, .bottom-bar {
background-color: green;
height: 40px;
position: fixed;
width: 100%;
z-index: 5;
}
.top-bar {
top: 100px;
}
.bottom-bar {
bottom: 0;
}
footer, .text {
position: relative;
z-index: 6;
}
JSFiddle here.
For an almost completely correct solution, here is one with some jQuery involved.
New CSS:
body {
margin: 0;
padding: 100px 0 0;
}
header {
background-color: red;
height: 100px;
position: fixed;
top: 0;
width: 100%;
z-index: 10;
}
footer {
background-color: blue;
height: 100px;
}
.section {
min-height: 400px;
}
.text {
background-color: aqua;
height: 50px;
}
.content {
background-color: green;
min-height: 100%;
padding: 40px 0;
position: relative;
}
.img {
background-color: yellow;
min-height: 70%;
margin: 0 auto;
padding: 40px 0;
text-align: center;
width: 80%;
}
.img > img {
vertical-align: middle;
}
.top-bar, .bottom-bar {
background-color: green;
height: 40px;
position: fixed;
width: 100%;
}
.top-bar {
top: 100px;
z-index: 5;
}
.bottom-bar {
bottom: 0;
z-index: 7;
}
footer, .text {
position: relative;
z-index: 8;
}
.img-fix {
bottom: 40px;
height: 400px;
overflow: hidden;
position: absolute;
width: 100%;
z-index: 6;
}
jQuery:
$(document).ready(function(){
$(".content").each(function(){
$(this).append($(this).html());
$(this).find(".img + .img").wrap("<div class='img-fix'></div>");
});
$(window).resize(function() {
resizeImgFix();
});
resizeImgFix();
});
function resizeImgFix() {
$(".img-fix").height($(window).height() - $("header").height() - $(".top-bar").height() - $(".bottom-bar").height());
$(".img-fix").each(function(){
$(this).scrollTop($(this).prop("scrollHeight"));
});
}
JSFiddle here.
Note: It duplicates the .img element and its children. This could be memory intensive depending. However, it does make it work as intended without any visual lag or artifacts.

Jquery .Click applies to all sub divs?

HTML:
<div id="lowerLayer">
<div id="positionLayer">
<div id="imageLayer">
<div id="imageHolder" style="background-image: url('/Images/Loading/ajax-loader.gif');">
</div>
</div>
</div>
</div>
CSS:
#lowerLayer
{
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
width: 100%;
height: 100%;
background-color: Green;
cursor: help;
}
#positionLayer
{
position: relative;
margin-top: 80px;
width: 100%;
background-color: Red;
}
#imageLayer
{
position: relative;
width: 450px;
height: 400px;
margin: auto;
background-color: Blue;
background-image: url('../Images/Large-image-holder.png');
}
#imageHolder
{
position: absolute;
left: 25px;
top: 25px;
width: 400px;
height: 300px;
line-height: 300px;
background-position: center;
background-repeat: no-repeat;
background-color: Aqua;
}
JQuery:
$(document).ready(function() {
$("#lowerLayer").click(function() {
$(this).fadeTo("fast", 0, function() {
$(this).hide(0);
});
});
});
});
Edit:
the problem im having us that the click event seems to be applied to all sub divs i just want it to apply to "#lowerLayer"
I think this will solve your problem:
$(document).ready(function() {
$("#lowerLayer").click(function(e) {
// Return if it's a child that's clicked:
if (e.target !== this) {return;}
// Otherwise continue:
$(this).fadeTo("fast", 0, function() {
$(this).hide(0);
});
});
});
});
Leaving event delegation and bubbling aside, since I don't think it is relevant to the actual problem here.
The jQuery hide() method applies display: none to the styles for an element. If an element is not displayed, then none of its descendants are either. Likewise, fadeTo() reduces the opacity, which also has an effect on the descendents of an element.

Categories

Resources