I am trying to attach a div to the cursor. The div only appears when it is over a specific box, and depending on the box it hovers over it is populated with an html message.
I've got the cursor attached to the mouse, but when I hover over any of the boxes (which also turn white when hovered over,) the div and the box "glitch" really hard. I assume this has to do something with the z-index, but I can't figure it out.
function mouseHandler(ev) {
document.getElementById('boxshadow').style.transform = 'translateY(' + (ev.clientY) + 'px)';
document.getElementById('boxshadow').style.transform += 'translateX(' + (ev.clientX) + 'px)';
}
document.getElementById("talk").addEventListener("mousemove", mouseHandler)
document.getElementById("time").addEventListener("mousemove", mouseHandler)
document.getElementById("chat").addEventListener("mousemove", mouseHandler)
$("#talk").mouseleave(function() {
$("#boxshadow").hide()
});
$("#talk").mouseover(function() {
$("#boxshadow").show()
$("#boxshadow").html("Message1")
});
$("#time").mouseleave(function() {
$("#boxshadow").hide()
});
$("#time").mouseover(function() {
$("#boxshadow").show()
$("#boxshadow").html("Message2")
});
$("#chat").mouseleave(function() {
$("#boxshadow").hide()
});
$("#chat").mouseover(function() {
$("#boxshadow").show()
$("#boxshadow").html("Message3")
});
.scrolltext {
position: relative;
border-bottom: 2px solid black;
letter-spacing: -15px;
white-space: nowrap;
line-height: 80%;
overflow-y: hidden;
overflow-x: scroll;
padding: 5px;
height: 160px;
width: 100%;
font-size: 200px;
z-index: 1;
}
#talk:hover {
background-color: white;
}
#time:hover {
background-color: white;
}
#chat:hover {
background-color: white;
}
#boxshadow {
width: 200px;
height: 200px;
background-color: red;
border: 1px solid black;
position: absolute;
z-index: 100000000000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div id="boxshadow"></div>
<div class="scrolltext" id="talk">
<p>A TALK WITH A GOOD FRIEND</p>
</div>
<div class="scrolltext" id="time">
<p>A LOVELY TIME WITH A GOOD FRIEND </p>
</div>
<div class="scrolltext" id="chat">
<p>A CHAT WITH A GOOD FRIEND </p>
</div>
</div>
So I think what's happening here is that your cursor can't be hovering over the div if the #boxshadow element is in the way. So the cursor triggers the box because it's over the div, then immediately isn't over the div anymore because it's over the box. So it's flipping back and forth... forever.
To avoid this, add the css property pointer-events: none; to the box. The browser will basically ignore the box when it's asking whether the mouse is "over" the div, and that should stop the glitching.
NB: If you want the user to be able to click on something in the box (obviously not an option right now, but I don't know what your plans are), with pointer-events: none the click will pass through to the div below.
Related
in html, sometimes I have elements that I display only when another one gain focus : you click on a button, to make another one appear.
If then you click on this newly displayed element, it disappears immediately because the focus gets away from the first one.
EDIT : And this is what I want. That could be a drop down menu for example, and I want the list to appears when clicking the title, and I want it to disappear when clicking on an element in the list.
but I also want to capture the click event before the element go away, and I can't do that ! example :
function make_action(element) {
console.log(element);
document.getElementById("output").innerHTML += `<p>detected ${element.innerHTML}</p>`;
};
#buttons {
width: 100px;
padding: 10px;
border: 1px solid black;
}
#buttons:focus p {
display: block;
}
#buttons p {
border: 1px solid blue;
display: none;
}
p {
margin: 5px;
padding: 0px;
}
<div id="buttons" tabindex=0>
<p onclick="make_action(this)" tabindex=0>onclick</p>
<p onfocus="make_action(this)" tabindex=0>onfocus</p>
<p onfocusin="make_action(this)" tabindex=0>onfocusin</p>
</div>
<div id="output">
</div>
I can workaround with the use of opacity and visibility with transition :
opacity to have the ux of the instantaneous hide of the element but it's still present so you can click on it
visibility is being delayed (sort of) with the transition, so for a moment you still have the element because it's still 'visible', but for human eyes it's not visible anymore
like that :
function make_action(element) {
console.log(element);
document.getElementById("output").innerHTML += `<p>detected ${element.innerHTML}</p>`;
};
#buttons {
width: 100px;
padding: 10px;
border: 1px solid black;
}
#buttons:focus p {
/*
display: block;
*/
visibility: visible;
opacity: 1;
}
#buttons p {
border: 1px solid blue;
/*
display: none;
*/
opacity: 0;
visibility: hidden;
transition: visibility 0.5s;
}
p {
margin: 5px;
padding: 0px;
}
<div id="buttons" tabindex=0>
<p onclick="make_action(this)" tabindex=0>onclick</p>
<p onfocus="make_action(this)" tabindex=0>onfocus</p>
<p onfocusin="make_action(this)" tabindex=0>onfocusin</p>
</div>
<div id="output">
</div>
but, I'm not sure it's a good practice because the element is actually still on the page, so it can impact accessibility and maybe other things.
do you know a way to capture the click on the element, before it disappears ?
what I don't understand, is the following : the buttons disappears because the div lose it's focus. But, it loses it's focus BECAUSE a click occurred on one button, so why isn't this click on the button detected ? or how is it detectable ?
You can replace you :focus with :focus-within which was created specially for this purpose.
And to do so that when clicked the elements loses focus, you can use the blur method to do so :
function make_action(element) {
console.log(element);
element.blur()
document.getElementById("output").innerHTML += `<p>detected ${element.innerHTML}</p>`;
};
#buttons {
width: 100px;
padding: 10px;
border: 1px solid black;
}
/* there is the change */
#buttons:focus-within p {
display: block;
}
#buttons p {
border: 1px solid blue;
display: none;
}
p {
margin: 5px;
padding: 0px;
}
<div id="buttons" tabindex=0>
<p onclick="make_action(this)" tabindex=0>onclick</p>
<p onfocus="make_action(this)" tabindex=0>onfocus</p>
<p onfocusin="make_action(this)" tabindex=0>onfocusin</p>
</div>
<div id="output">
</div>
I'm trying to make specified div's on my page interactive and thus, change focus (come to the foreground if you will) when clicked. Essentially, I would like the div's to act much like the windows do on a computer running Microsoft Windows.
This is what I've come up with so far using z-index and it does work, sort of. The problem is that the div's appear to have their own "order" so to speak when it comes to overlapping each other based on where they are placed in the HTML.
For instance, if you click "Div2" then "Div1", you can see that "Div2" ends up actually going back behind "Div3" rather than staying in front of it as it previously was. I'd like order to be retained as clicked. If you click Div2, it should be in the front, then you click Div1 and it would then be in front of Div2, etc.
Any ideas on a way around this would be greatly appreciated. Thank you in advance!
// Global vars
var lastFocused;
// When left mousedown on a ".window" element, remove the ".window-focus" class from id
// specified in the global var "lastFocused". Next, update the global var "lastFocused"
// with the most recently clicked element id. Lastly, add the ".window-focus" class to
// the id specified in global var "lastFocused".
$('.window').mousedown(function () {
$(lastFocused).removeClass('window-focus');
lastFocused = "#" + $(this).attr("id");
$(lastFocused).addClass('window-focus');
});
// Make all ".window" elements resizable and draggable.
$('.window').draggable({containment: '#container'}).resizable({containment: '#container'});
html, body, #container {
height: 100%;
width: 100%;
font-family: Roboto;
background-color: #333;
color: #c9c9c9;
font-size: 1em;
overflow: hidden;
}
.window {
position: absolute !important;
border: 1px solid #999;
background-color: #222;
height: 100px;
width: 100px;
z-index: 1;
}
#div1 { top: 20px; left: 20px; }
#div2 { top: 60px; left: 60px; }
#div3 { top: 100px; left: 100px; }
.window-focus { z-index: 2; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<div class="window" id="div1">ONE</div>
<div class="window" id="div2">TWO</div>
<div class="window" id="div3">THREE</div>
Your issue is that you are always giving the the currently clicked div a z-index of 2, which does bring it to the front, but then when you remove that class from an element it simply goes back to it's original z-index. You need that last-applied z-index not to change and have the next-clicked element get a z-index that is one higher than the previous one.
Just keep track of the last z-index assigned to the last-clicked div element and increment it by one after each assignment so that the next clicked element will get a higher z-index assigned to it.
NOTES:
There is no need for the lastFocused variable, the .window-focus
CSS selector, or to assign a z-index:1 to the .window elements.
You were exactly right about elements having an implicit z-index
based on where they are in the HTML. For sibling elements, the z-index is simply based on the sequence. The earlier in the sequence, the lower the z-index. But, it's more complex when you start working with elements that don't share the same parent. See the stacking context for details.
JQuery recommends using the element.on("eventName", callback)
method rather than event-specific methods (i.e.
element.mousedown(callback)).
It's probably not a good idea to use a class name of .window for
elements that are not the window object. It will cause confusion. For something like this, a class name of stackable or draggable seems appropriate.
var highestZ = 3; // There are 3 divs, so highest z-index in use is initially 3
// When any of the div.stackable elements get clicked...
$('.stackable').on("mousedown", function () {
$(this).css('z-index', ++highestZ); // Clicked div gets a z-index one higher than prevous highest
});
// Make all ".stackable" elements resizable and draggable.
$('.stackable').draggable({containment: '#container'}).resizable({containment: '#container'});
html, body, #container {
height: 100%;
width: 100%;
font-family: Roboto;
background-color: #333;
color: #c9c9c9;
font-size: 1em;
overflow: hidden;
}
.stackable {
position: absolute !important;
border: 1px solid #999;
background-color: #222;
height: 100px;
width: 100px;
user-select:none;
cursor:pointer;
}
#div1 { top: 20px; left: 20px; }
#div2 { top: 60px; left: 60px; }
#div3 { top: 100px; left: 100px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<div class="stackable" id="div1">ONE</div>
<div class="stackable" id="div2">TWO</div>
<div class="stackable" id="div3">THREE</div>
I'm not really asking for help with my code, I'm more asking, how do you do this?
When you click my div, the screen goes black, but I want my div underneath to still show as normal, but the rest of the area to be blacked out.
function lightsout() {
document.getElementById("lightsout").style.visibility = "visible";
}
<div style="width:100px;height:100px;border:2px solid blue" onclick="lightsout()">Click Me</div>
<div id="lightsout" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:black;visibility:hidden;">
You can use the box-shadow property to achieve this effect.
Updated the Code
function lightsout() {
document.getElementById("maindiv").classList.toggle("visible");
}
.visible{
box-shadow: 0 0 0 10000px #000;
position: relative;
}
body{
color: red;
}
<div style="width:100px;height:100px;border:2px solid blue; color: #000;" onclick="lightsout()" id="maindiv">Click Me</div>
Other elements on the page will be hidden...
You can simply add z-indexes to your positioning. With giving the black area a lower z-index than your button but a higher z-index than the rest, you will have your effect.
Also it is recommended to not use inline styles, as your code becomes way more maintainable with styles and markup seperate.
function lightsout() {
document.getElementById("lightsout").classList.toggle("visible");
}
.button {
position: relative;
z-index: 10;
width: 100px;
height: 100px;
border: 2px solid blue;
background: white;
}
#lightsout {
position: fixed;
z-index: 5;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: gray;
visibility: hidden;
}
#lightsout.visible {
visibility: visible
}
<div class="button" onclick="lightsout()">Click Me</div>
<div id="lightsout"></div>
Other elements are hidden.
you can use css,
z-index, and add divbox background-color like this :)
function lightsout() {
document.getElementById("lightsout").style.visibility = "visible";
}
#lightsout{
z-index: -1
}
<div style="width:100px;height:100px;border:2px solid blue;background-color:white;" onclick="lightsout()">Click Me</div>
<div id="lightsout" style="position:fixed;top:0;left:0;width:100%;height:100%;background-color:black;visibility:hidden;">http://stackoverflow.com/questions/42688925/how-to-make-a-page-lights-out-except-for-one-element#
Say I have divA that partially overlaps divB. How can I allow clicks on divA to pass through to divB but still have hover fired when hovering over divA?
I'm aware of pointer-events:none; and this makes the clicks pass through but it also prevents the hover.
I have also tried the below, but it did not allow clicks to fall through
$(document).on('click', '.feedback-helper', function(e){
e.preventDefault();
})
Picture the relation of the divs like:
Here is the why of it (read as: "let's avoid an X Y problem"):
I'm working on an implementation of feedback.js
To see the issue:
view the feedback.js demo
click the feedback button in the bottom right
draw a box on the screen to highlight a section
click the "black out" button
try to draw a box inside the first box you can't because the click is blocked by the first box
I need to allow drawing a blackout box over a highlighted area but if I set pointer-events:none; I will lose other hover functionality I have on those elements.
Here is a jsFiddle example
All solutions welcome
I checked your example page and if you set a slightly lower z-index on data-type="highlight" that could take care of the problem, try a z-index of 29990 in comparison to your current 30000. This should allow you to target the highlighted feedback area and overlay it with the blackout elements.
You could get the click event for the overlaying element to initiate the click event for the underlying element.
Native JS Example:
document.getElementById('divA').addEventListener('click', function() {
alert('Clicked A');
});
document.getElementById('divB').addEventListener('click', function() {
var event = document.createEvent('HTMLEvents');
event.initEvent('click', true, false);
document.getElementById('divA').dispatchEvent(event);
});
div {
cursor: pointer;
border: 1px solid black;
}
#divA {
height: 300px;
width: 300px;
background: whitesmoke;
}
#divB {
height: 30px;
width: 30px;
background: grey;
position: absolute;
left: 100px;
top: 100px;
}
#divB:hover {
background: green;
}
<div id="divA"></div>
<div id="divB"></div>
jQuery Example:
$('#divA').on('click', function() {
alert('Clicked A');
});
$('#divB').on('click', function() {
$('#divA').trigger('click');
});
div {
cursor: pointer;
border: 1px solid black;
}
#divA {
height: 300px;
width: 300px;
background: whitesmoke;
}
#divB {
height: 30px;
width: 30px;
background: grey;
position: absolute;
left: 100px;
top: 100px;
}
#divB:hover {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="divA"></div>
<div id="divB"></div>
Another option is to use a pseudo element instead. Perhaps that will do what you need.
$('#toggleBlack').on('click', function() {
$('#divA').toggleClass('hidden');
});
div {
border: 1px solid black;
}
#divA {
background: whitesmoke;
position: relative;
}
#divA.hidden:before {
position: absolute;
content: ' ';
top: 0;
left: 0;
right: 0;
bottom: 0;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="divA">Highlight the text once I'm hidden and cut/copy/drag</div>
<br />
<br />
<button id="toggleBlack">Toggle Hidden</button>
I am simulating a pop up window that fades the background out. I do this by simply toggling a div that fills the whole screen. I would like to be able to close the pop up by clicking the outside background, but not when you click on the new content area, which is what is currently happening. My code:
JS:
function popbox() {
$('#overbox').toggle();
}
HTML:
<div class="popbox" onclick="popbox()"> Click Here </div>
<div id="overbox" onclick="popbox()">
<div id="infobox1">
<p>This is a new box</p>
<br />
<p>hello </p>
<br/><br/>
<p style="color:blue;text-align:center;cursor:pointer;" onclick="popbox()">close</p>
</div><!-- end infobox1 -->
</div> <!-- end overbox -->
CSS:
#overbox {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: rgba(64, 64, 64, 0.5);
z-index: 999999;
display: none;
}
#infobox1 {
margin: auto;
position: absolute;
left: 35%;
top: 20%;
height: 300px;
width: 400px;
background-color: white;
border: 1px solid red;
}
.popbox {
cursor: pointer;
color: black;
border: 1px solid gray;
padding: 5px; 10px;
background: ghostwhite;
display: inline-block;
}
JSFiddle link: http://jsfiddle.net/RrJsC/
Again, I want it to toggle only when you click the faded background or "close" (which isnt working in the jsfiddle but is on my site), but not when you click inside the white box that it contains.
After some research it seems like I might be looking for .stopPropagation(), but I haven't been able to get it to work at all.
I got it to work using jQuery's event handlers:
$('#container').on('click', '.popbox, #overbox', function(e){
$('#overbox').toggle();
});
$('#container').on('click', '#infobox1', function(e){
e.stopPropagation();
});
I replaced document with '#container' for better performance. You should wrap all your divs in <div id="container">...</div> so the the callback doesn't fire on the dom every time there is a click (even thought that callback is only called when the selector matches).
You'll also need to get rid of your onclick html attributes, because they will throw an error if that function is not defined.
I hope I understand well your problem.
If it is the case, you should have this:
<div id="overbox">
instead of this:
<div id="overbox" onclick="popbox()">
here is the updated jsfiddle