Hover over an element covered by another element's padding - javascript

So I have a map composed by tiles that are svg elements.
In the image, the tile itself is the blue area, but it has a buffer area to allow geometries that span outside the tile to render whole. The problem is that this buffer area (in green), is covering the geometries from other tiles that are below it. This buffer zone is set in CSS as the following:
padding: 128px;
margin: -128px;
Is there a way to hover/click "through" the buffer area, or is there a better approach in CSS to achieve this?

Padding is part of a element, therefore will react like it was content of your tag.
See here. If you absolutely need to have that spacing to be padding, you can't click anything behind neither content nor padding.
You might consider changing your layering, using z-index, but for further advise on this, you'll have to provide further code, your HTML Markup and CSS code.

If that blue thingy is the only element that needs this treatment, then I suggest creating a key bind to move that element to the back with z-index, and be done with it.
If you require this functionality on all of these red balls, the thing to do would probably be to move, the one you click on, to the back with z-index ( again ).
Both of these require you to use JavaScript most likely, unless you want to move that big blue element to the back on hover.
To always move the clicked element to the back you could just keep track of what was the last assigned z-index, and decrease it by one every time you assign it to a new object.
Something like this would probably do:
#box1 { position: absolute; background-color: #123; width: 100px; height: 100px; top: 200px; left: 300px; opacity: 0.9; }
#box2 { position: absolute; background-color: #ABC; width: 100px; height: 100px; top: 250px; left: 350px; opacity: 0.8; }
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>
<script type="text/javascript">
var boxes = document.getElementsByClassName("box");
var length = boxes.length;
var index = 0;
function moveToBack(event)
{
var element = this;
this.style.zIndex = index;
index--;
return false;
}
for(var i = 0; i < length; i++)
{
var box = boxes[i];
box.addEventListener("click", moveToBack, false);
}
</scirpt>
Does that do the job ? or did you mean something else entirely ?

Only way I can seem to get it to work is to add a child inner element and give pointer-events:none to the wrapper and pointer-events:auto to the inner child element. It's not ideal as support for pointer-events is limited and there's no telling if all browsers will respect a child of pointer-events:none element having a different value than its parent. It will need tested. Well, in any case, here is the code:
$('.tile').on('mouseenter', function(){
$('.info', this).find('.tile-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="tile-info">mouseenter tile '+ts+'</div>');
});
$('.tile').on('mouseleave', function(){
$('.info', this).find('.tile-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="tile-info">mouseleave tile '+ts+'</div>');
});
$('.inner').on('mouseenter', function(){
$('.info', this).find('.inner-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="inner-info">mouseenter inner '+ts+'</div>');
});
$('.inner').on('mouseleave', function(){
$('.info', this).find('.inner-info').remove();
var ts = new Date().getTime();
$('.info', this).append('<div class="inner-info">mouseleave inner '+ts+'</div>');
});
.tile {
width: 200px;
height: 200px;
background: rgba(100,100,200,0.2);
padding: 50px;
margin: -50px;
position: absolute;
pointer-events:none;
}
.tile:nth-of-type(1) {left: 300px;top: 20px;}
.tile:nth-of-type(2) {left: 90px;top: 210px;}
.tile:nth-of-type(3) {left: 0px;top: 0px;}
.tile:nth-of-type(4) {left: 360px;top: 240px;}
.tile .inner {
width: 100%;
height: 100%;
background: rgba(200,100,100,0.2);
pointer-events:auto;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>
<div class="tile">
<div class="inner">
<div class="info"></div>
</div>
</div>

Related

how to trigger multi event in same level multi div overlap area?

i define a event in same level div,but i can't trigger the event with div between multi different div overlap area,just one of them triggered,how to trigger these same level div events by overlap area?
the example code like this
function Triggered(e){
console.log(event.target.id);//
}
.S{
position: absolute;
width: 99px;
height: 99px;
opacity: .7;
}
<body>
<div id="1" style="background-color:blue;left: 50%;top:50%" onclick="Triggered()" class="S"></div>
<div id="2" style="background-color:red;left: 50%;top:50%;transform: translate(-25%,-50%);" onclick="Triggered()" class="S"></div>
<div id="3" style="background-color:green;left: 50%;top:50%;transform: translate(-50px,0);" onclick="Triggered()" class="S"></div>
</body>
(ps: it's use for slove the li sort question,when li A over another li B,the mouseover event in B can't trigger,just trigger A,so i need a solution for slove multi same level div event triggered in overlap area,pointer-events:none it's not helpful,i need trigger multi event in overlap area not one)
If I understood correctly you want to detect click event for your three divs, even when they overlap each other. Since your tags are defined at the same level, you cannot use event bubbling or capturing to handle click at different levels like we do with nested tags.
When user clicks, try calling function document.elementsFromPoint(x, y) to get all elements underneath the mouse pointer.
function Triggered(e) {
var clickedElements = [];
document.elementsFromPoint(event.clientX, event.clientY).forEach(function(element) {
if (element.classList.contains('S')) {
clickedElements.push(element.id);
}
});
console.log(clickedElements);
}
.S {
position: absolute;
width: 99px;
height: 99px;
opacity: .7;
}
<div onclick="Triggered()">
<div id="blue" style="background-color:blue;left: 50%;top:15%" class="S"></div>
<div id="red" style="background-color:red;left: 50%;top:15%;transform: translate(-25%,-50%);" class="S"></div>
<div id="green" style="background-color:green;left: 50%;top:15%;transform: translate(-50px,0);" class="S"></div>
</div>
I started out with an approach along the lines of:
if (e.target.style.getPropertyValue('pointer-events') !== 'none') {
console.log(e.target.id);
}
else {
e.target.style.setProperty('pointer-events', 'none');
e.target.dispatchEvent('click');
e.target.style.removeProperty('pointer-events');
}
But quickly learned that the pointer-events property does not work with computational clicks.
This is my final solution (ultimately very similar to the solution provided by #derloopkat, above, so credit should go to that answer, not this one).
Working Example:
const div1 = document.getElementById('div1');
const div2 = document.getElementById('div2');
const div3 = document.getElementById('div3');
const triggered = (e) => {
// GET MOUSE POSITION
const x = e.clientX;
const y = e.clientY;
// GET STACKED ELEMENTS
const stackedElements = document.elementsFromPoint(x, y);
// BUILD ARRAY OF TARGET ELEMENTS
const targetElements = [];
for (let stackedElement of stackedElements) {
if (stackedElement.classList.contains('s')) {
targetElements.push(stackedElement);
}
}
// LOG IDS OF TARGET ELEMENTS
for (let targetElement of targetElements) {
console.log(targetElement.id);
}
}
div1.addEventListener('click', triggered, true);
div2.addEventListener('click', triggered, true);
div3.addEventListener('click', triggered, true);
.s {
position: absolute;
top:50%;
left: 50%;
width: 99px;
height: 99px;
opacity: .7;
}
#div1 {
background-color: blue;
}
#div2 {
background-color: red;
transform: translate(-25%, -50%);
}
#div3 {
background-color: green;
transform: translate(-50px, 0);
}
<div id="div1" class="s"></div>
<div id="div2" class="s"></div>
<div id="div3" class="s"></div>

How do I attach a div to the right or left side of another div using Javascript?

I am trying to create a simulated chat box, which requires chats to pop up on the left and the right side of the div. Each of these chats are divs as well. I cannot figure out how to append a div to the right side of the outer div. In my code I've appended some text to the div I want to then append to the outer div. I want to do this with vanilla Javascript, if possible.
function pressEnter() {
if (event.keyCode === 13) {
event.preventDefault;
// get text
var text = document.getElementById("client_text_area").value;
// create new div
var newdiv = document.createElement('div');
newdiv.id = "human_chat"
// create text node to append
text = document.createTextNode(text);
newdiv.appendChild(text);
}
I'd put this in a comment below Gershom's answer but since I can't comment yet, I'm putting it in an answer.
As Gershom shared, use CSS to style your divs. You can add classes to your div when creating them with JavaScript like the following:
newdiv.classList.add('class-name');
Using left: 0% positions a child element within its parent, hugging its left side. Using left: 50% positions this child's left side in the very middle of its parent. And so we can see that left: 100% will position the child's left against the rightmost edge of its parent. Similarly, right: 100% can be used to position children to the left of their parent:
.parent {
position: absolute;
left: 50%; top: 50%;
width: 100px; height: 100px;
margin-left: -50px; margin-top: -50px;
background-color: #900;
}
.parent > .child {
position: absolute;
width: 50px; height: 50px;
top: 25px;
background-color: #090;
}
/* These are the rules that should interest you! */
.parent > .child.left { right: 100%; }
.parent > .child.right { left: 100%; }
<div class="parent">
<div class="child left"></div>
<div class="child right"></div>
</div>
In order to set these values through javascript, you can the modify values on yourElem.style.
For example, if you wish for newdiv to stick to the right of its parent you can do:
newdiv.style.position = 'absolute';
newdiv.style.left = '100%';

Javascript & CSS/HTML - Background Change on Mouse Over of DIV

I have the following code in my HTML.
<div class="bg"></div>
<div class="content" id="hover">
<div class="one" id="hover-over">1</div> <!--Trigger!-->
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
The CSS..
.bg {
background: yellow;
position: fixed;
top: 0;
left: 0;
z-index: 1;
}
.content {
background: red;
}
The Javascript..
var box = document.getElementById("bg");
var bgChanger = document.getElementById("hover-over");
//var body = document.getElementsByTagName("body");
function changeBackgroundUp() {
box.style.backgroundColor = "blue";
//body.style.backgroundColor = "#6fcc6f";
}
function changeBackgroundDown() {
box.style.backgroundColor = "green";
//body.style.backgroundColor = "red";
}
bgChanger.onmouseover = changeBackgroundUp; //
bgChanger.onmouseleave = changeBackgroundDown; //
A Fiddle: https://jsfiddle.net/bqnw4qyb/56/
The Problem
I wish to have the background of the project CHANGED to, for example, green - when the user hovers over one of the DIV elements inside "content". So, when the user hovers over "1", the background of the whole page will change to green. My DIV elements have the background of RED, I don't want this colour to change, only the background color, ideally I would want to change the background to an image using a
background: url('someImage');
type of system..
I have tried many existing solutions, such as using CSS hover:
.one:hover ~ .bg {
background: url('someImage')
}
At this stage I am stumped, so any help is very much appreciated.
function green() {
document.getElementsByClassName("content")[0].style.backgroundColor = "green";
}
function red() {
document.getElementsByClassName("content")[0].style.backgroundColor = "red";
}
.bg {
background-color: yellow;
position: fixed;
top: 0;
left: 0;
z-index: 1;
}
.content {
background: red;
}
<div class="bg"></div>
<div class="content" id="hover">
<div class="one" onmouseover="green()" onmouseout="red()" id="hover-over">1</div> <!--Trigger!-->
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>
</div>
Please see how I implemented this, is this what you would like?
My program is using the onmouseover and the onmouseout event.
Please leave any concerns in the comments, hope it helped ;)
Check the error console!
You have no box object as you have no element with id bg only class.
Add add the id to the div with class bg as well.
<div class="bg" id="bg"></div>
Also with your current positioning, the bg div is not actually visible.
https://jsfiddle.net/bqnw4qyb/67/

Change image opacity when using GetElementById

Part of my Uni module requires me to make a webstory that uses random elements to mix up the story. I'm using GetElementById in JS to embed one random image from an array into a div, which works perfectly fine. The image becomes the background of the div, and I then have text on top of the image - again this all works perfectly fine.
However the issue is that I want the image to be slightly transparent so that the text is easier to read, however no matter what solution I try, I can't get it to work.
I've tried making the div transparent in both CSS and JS, however then the whole div including the text is effected which defeats the point. Then when I try the RGBA style in CSS, the image isn't effected.
So what I need is the image that is loaded into the div through JS to be slightly transparent, whilst the text that is also in the div in the HTML doument to remain untouched.
This is the JS I'm using to randomly select an image:
function randomGun() {
var imgCount = 3;
var dir = 'img/';
var randomCount = Math.round(Math.random() * (imgCount - 1)) + 1;
var images = new Array
images[1] = "gun1.jpg",
images[2] = "gun2.jpg",
images[3] = "gun3.jpg",
document.getElementById("left").style.backgroundImage = "url(" + dir + images[randomCount] + ")";
}
<div id="container">
<div id="left">
<a id="message">Drive a bit closer to see if anybody is there.</a>
</div>
<script>
window.onload = randomGun()
</script>
</div>
Use a nested div with semi-transparent white background.
<div id="container">
<div id="left">
<div id="nested" style="width:100%;height:100%; background-color: rgba(255,255,255,0.5)">
<a id="message">Drive a bit closer to see if anybody is there.</a>
</div>
</div>
<script>window.onload = randomGun()</script>
</div>
In addition, I would set everything relative to style in a stylesheet, or at least inside a <style></style>.
UPDATE
Added your JS and fixed it a little. Note the adjustment to the random expression.
Perhaps this'll help you.
Use an element that'll contain 2 other elements, give the container position:relative and z-index:-2
Then the 2 elements inside should have position:absolute.
Next give the top element z-index:-1, background:url(http://image-host.com/path/to/img.jpg), and opacity:.5
Then the second element should have text and whatever else you want visible. Give this element z-index:1.
The reason why opacity wasn't working the way you expected to work is because opacity applies to everything within the element as well. Here in the Snippet, we layered an element with content and an element with a background image separately.
REFERENCE: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index
SNIPPET
function randomBG() {
var imgCount = 3;
var path = 'http://imgh.us/';
var randomCount = Math.round(Math.random() * (imgCount));
var images = ['solar_system.jpg', 'kowloon.jpg', 'transparent-map.png'];
document.getElementById("fader").style.backgroundImage = "url(" + path + images[randomCount] + ")";
}
window.onload = randomBG;
html,
body {
height: 100%;
width: 100%;
font: 400 16px/1.5 Verdana;
box-sizing: border-box;
}
* {
margin: 0;
padding: 0;
border: 0;
}
#base {
position: relative;
z-index: -2;
width: 100vw;
height: 100vh;
}
#content {
position: absolute;
z-index: 1;
padding: 20px;
margin: 0 auto;
width: 75%;
height: auto;
top: 0;
left: 0;
background: none;
}
#fader {
position: absolute;
z-index: -1;
padding: 20px;
margin: 0 auto;
min-width: 75%;
min-height: 75%;
/*background: url(http://imgh.us/Lenna.png);*/
opacity: .5;
}
<main id='base'>
<section id='fader'></section>
<article id='content'>
<h1>This is the Text</h1>
</article>
</main>

Javascript - Multi-Usage of General Function

I have a example of a situation here, I want to change the color of a div when clicked. Do I have to have two different functions, one for each div? What if the functions that I wanted to apply to the div was very complex? What if I had hundereds of the div? Can I make a general function, that can be applied for every div? By this I do not mean for example document.getElementsByClassName(" ... "), I want to for example change the color of the separately.
To be clear, how can I apply the same function to different objects? Something like document.getElementThatIsClicked(" ... " ) Thank you.
function changeColor1() {
document.getElementById("div1").style.backgroundColor = "#21a9c9";
}
function changeColor2() {
document.getElementById("div2").style.backgroundColor = "#21a9c9";
}
<div id="div1" onClick="changeColor1()" style="position:absolute; top:10px; left: 10px; width:200px; height: 200px; background-color:#000000;"></div>
<div id="div2" onClick="changeColor2()" style="position:absolute; top: 10px; left: 220px; width:200px; height: 200px; background-color:#000000;"></div>
You can make a function that accepts the element you want to change the color and make the function change the background color for that element
function changeColor(elem) {
elem.style.backgroundColor = "#21a9c9"
}
<div id="div1" onClick="changeColor(this)" style="position:absolute; top:10px; left: 10px; width:200px; height: 200px; background-color:#000000;"></div>
<div id="div2" onClick="changeColor(this)" style="position:absolute; top: 10px; left: 220px; width:200px; height: 200px; background-color:#000000;"></div>
Copied from https://stackoverflow.com/a/32828729/227299 but:
Avoids setting handlers using inline HTML attributes in favor of unobtrusively setting handlers from JavaScript itself. See onclick="" vs event handler
Avoid setting CSS attributes from HTML attributes. See What's so bad about in-line CSS?
function changeColor(elem) {
elem.style.backgroundColor = "#21a9c9"
}
var divs = document.querySelectorAll('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', function(e) {
changeColor(this);
});
}
#div1,#div2 {
display: inline-block;
width: 200px;
height: 200px;
background-color:#000000;
}
<div id="div1"></div>
<div id="div2"></div>

Categories

Resources