How to MouseOver behind an object? - javascript

I'm trying to mouseover an image which is behind an another image.
Is there any way to render the front image like it is not there, so I can mouseover the other image behind it?
Example can be seen here:
I can't mouseover the characters which are behind the logo boundingbox.

You can set the CSS property pointer-events: none on the obstructing object... but be aware that pointer events are all or nothing; mouseovers and hovers will pass right through, but so will clicks.
Here is a description of the value, from the Mozilla Developer's Network:
none: The element is never the target of mouse events; however, mouse events may target its descendant elements if those descendants have pointer-events set to some other value. In these circumstances, mouse events will trigger event listeners on this parent element as appropriate on their way to/from the descendant during the event capture/bubble phases.
I've put together a little example. In this example, I'm using onmouseover and onmouseout, since that's what you use on your website, but you could just as easily use the CSS :hover pseudo-selector. Here's a jsfiddle version of the example, and the stack snippet is below.
.hoverable {
width: 100px;
height: 100px;
background-color: blue;
}
.obscuring {
/* this first line is the important part */
pointer-events: none;
position: absolute;
top: 50px;
left: 50px;
width: 100px;
height: 100px;
background-color: red;
opacity: 0.5;
}
<div class="hoverable" onmouseover="this.style.backgroundColor = 'green'" onmouseout="this.style.backgroundColor = 'blue'"> </div>
<div class="obscuring"> </div>

You can create some invisible divs on top of the whole thing and put the hover behaviour on them. Then control the characters position with the position of the invisible divs.
Hope it makes sense.

Related

Disable pointer-events only when dragging over an item

I have a container with dynamic content a user can interact with. It could be a YouTube video (iframe), amongst other things.
A user can drag and drop an image into this container and it'll replace the dynamic content with their image.
I'm aware that due to the dynamic content, drag events will behave erratically in the container, so I need to do pointer-events: none.
The HTML container has the following classes ant-upload-drag and ant-upload-drag-hover. The ant-upload-drag-hover class is only active when the image being dragged is on-top of the container.
I have CSS akin to the following where ant-upload-drag-container contains the dynamic content that I want unreachable by pointer-events:
.ant-upload-drag-hover {
.ant-upload-drag-container {
pointer-events: none;
}
}
Unfortunately, this doesn't work. It causes the container to behave erratically with the ant-upload-drag-hover class added and removed from the container over and over and over.
Meanwhile, the following works:
.ant-upload-drag {
.ant-upload-drag-container {
pointer-events: none;
}
}
Essentially, as long as .ant-upload-drag-container is always pointer-events: none; things work as expected, but if the pointer-events: none is triggered dynamically on hover, then things don't go as planned.
The following video demonstrates visually:
https://share.getcloudapp.com/ApuRgQlZ
The first example shows what is desired (when pointer-events is always none). The second example shows the current state (when pointer-events is dynamically shifted to always none).
I know this isn't much to go off of, but I'm not sure if I fundamentally misunderstand pointer-events: none, or if some React rendering shenanigans are happening.
Presumably, the moment ant-upload-drag-hover class is added to the element, the pointer-events: none would trigger, but it seems like for some reason pointer-events: none is also triggered on the container or something else must be happening for the container to lose the hover state and remove the class.
I'm not sure whether pointer-events: none interferes with the drag-and-drop events but it would explain your bug.
I'd suggest that you instead put a layer on top of the container that catches these events instead.
Here an example with a button and the layer is toggles (by a class) every 3 seconds.
// toggle class `ant-upload-drag-hover` every 3 seconds
setInterval(() => {
document.querySelector(".ant-upload-drag").classList.toggle("ant-upload-drag-hover");
}, 3000);
.ant-upload-drag-container {
position: relative;
}
.ant-upload-drag-hover .ant-upload-drag-container::before {
content: "";
display: block;
position: absolute;
z-index: 999;
height: 100%;
width: 100%;
/* the rest is just for aesthetics: */
content: " .ant-upload-drag-hover";
background: rgba(255, 255, 255, .5);
cursor: not-allowed;
}
button {
padding: 50px 100px;
}
button::before {
content: "Click here: ";
}
<div class="ant-upload-drag">
<div class="ant-upload-drag-container">
<button onclick="++this.textContent">0</button>
</div>
</div>

How do I select only the <body> element's background whitespace for a Javascript onclick callback?

I need to create a callback that allows me to click or double click the background of my webpage, to return it to its default layout (thereby, closing and returning things so far affected by event callbacks). If I add an onclick callback to my <body> element, it is called whenever I click higher-level elements, not just on the background. So, it is available everywhere. How do I ensure that only the lowest-level element (i.e. the background whitespace) can call the reset function?
You need to do event propagation stop technique. So that you stop your event from going up the DOM tree.
One such method is event.stopPropagation();
Do also look Event Delegation, this may also help depending on your requirement.
The idea is that if we have a lot of elements handled in a similar
way, then instead of assigning a handler to each of them – we put a
single handler on their common ancestor.
In the handler we get event.target to see where the event actually
happened and handle it.
In your case I believe You may require Event Delegation technique along with stopPropagation
I would suggest you have 2 elements background div and the inner div which will contain all the content of your webpage
<body>
<!-- the clickable background -->
<div class="background-container" onclick="reset()" id="background"></div>
<!-- Your webpage -->
<div class="webpage">
<h3>This is your webpage</h3>
</div>
</body>
CSS - to make the background fullscreen
.background-container{
background-color: #4158D0;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
/* Use z-index to put the background behind your webpage */
z-index: 0;
}
.webpage{
/* positioned relative to the nearest positioned ancestor (instead of positioned relative to the viewport, like fixed). */
position: absolute;
/*setting the z-index to one to bring it to front*/
z-index: 1;
}
h3{
font-size: 40px;
color: white;
font-family: 'Roboto';
}
Javascript - to make the background clickable and run the function reset()
This function will be triggered when the background is clicked
you can edit the function to fit your purpose
function reset(){
var colors = ["#4158D0", "#C850C0", "#FFCC70"];
document.querySelector('#background').style.cssText = `background-image: linear-gradient(43deg, ${colors[Math.floor(Math.random() * 3)]}, ${colors[Math.floor(Math.random() * 3)]}, ${colors[Math.floor(Math.random() * 3)]},${colors[Math.floor(Math.random() * 3)]},${colors[Math.floor(Math.random() * 3)]})`
}
For this demo the reset() function will change the background color
Here is the codepen https://codepen.io/Alemalohe/pen/MWjBwOd

JQuery UI Draggable set hitbox different from element or set multiple elements

I'm having an Issue that I'm trying to apply draggable to some a popup element of an external library (I can't modify them).
The problem is that, the most outer div of this popup is actually slightly outside it and has 0 height (its an arrow shaped div, its kinda like a dialog balloon), so it doesn't properly works with the containment.
I could just chose the inner element as a selector (which is the actual popup bounding box), but then the arrow element will not move with the popup.
As stated, I can't modify these elements in a way of grouping them togheter (Actually I don't even have access to the source, doing it in developer console), so how can I solve this? I would like to keep using JQuery UI, but if not possible I'm open to alternatives.
I've tried multiple selectors, but it won't move the arrow div :
$( ".dialogArrow, #popupDiv" ).draggable({ scroll: false });
Example code :
<div class="dialogArrow" style="height:0; width: 100%; background: red">I'm the parent but my hitbox is wrong
<div id="popupDiv" style="height: 200px; width: 200px; background: green">actual hitbox</div>
<div>i need to move togheter too</div>
</div>
JSFiddle : https://jsfiddle.net/hvkh7mmq/5/
You can make use of the handle option (demo). Like so:
$(function() {
$(".dialogArrow").draggable({
handle: "div#popupDiv",
scroll: false
});
});
Working example: https://jsfiddle.net/Twisty/hvkh7mmq/3/
I did not see a point to your selector, since you want to drag the parent element, not assign .draggable() to both elements. Since the parent has no render-able HTML, it can't be clicked upon in essence. So using the handle option, we can specify something that can be clicked.
Additional
If you inspect the element after dragging, you will see something like:
<div class="dialogArrow ui-draggable" style="height: 0px; width: 100%; background: red none repeat scroll 0% 0%; position: relative; left: 107px; top: 30px;">
<div id="popupDiv" style="height: 200px; width: 200px; background: green; cursor: inherit;" class="ui-draggable-handle">actual hitbox</div>
<div id="other div that needs to move togheter"></div>
</div>
The structure is not changed. All 3 elements are moved.

How to center <div> inside a <button>?

I have a round < button > with a < div > inside that represents a Unicode image. Currently the button is set to border-radius: 12px; height: 24px; and width: 24px; and the < div > is to font-size: 17px. The < div > Unicode image sits inside but not centered and the button is slightly off to the side.
How can I get the < div > to center inside an oval button despite what font-size the < div > is?
EDIT
I want to create a circle/round button with an emoji center to the middle of the button despite the button's size or the emoji image's size.
CSS for the button and emoji image for div:
#emoji-button {
border-radius: 19px;
width: 38px;
height: 38px;
}
#thumb-emoji:after {
content: "\01F44C";
font-size: 20px;
}
And round/circle button with emoji image inside:
<button
type="submit"
id="emoji-button"
>
<div id="thumb-emoji"></div>
</button>
But it is not centered.
And is there a way to just back the emoji image alone to be clickable for a method?
First off:
A <div> is a block element by nature. It will always become 100% wide. If you want it to not be 100% wide, give it a display:inline-block so it won't get bigger than it needs to be. Then give it a margin:0 auto; or a text-align:center on the parent to center it.
HOWEVER, You are not allowed to put <div>s inside of <buttons>. it is invalid HTML
See this answer for more information:
Why can't a <button> element contain a <div>?
Or, you could read here, from W3 that only phrasing content is expected to be used within a button:
https://www.w3.org/TR/2012/WD-html5-20120329/the-button-element.html#the-button-element
If you do not know what phrasing content is, See this page:
https://www.w3.org/TR/2012/WD-html5-20120329/content-models.html#phrasing-content
-- if you are looking into styling buttons specifically, maybe this very short tutorial would help:
http://web.archive.org/web/20110721191046/http://particletree.com/features/rediscovering-the-button-element/
Here is a fiddle of a working button like yours:
https://jsfiddle.net/68w6m7rr/
I honestly didn't have many problems with this. I only replaced your <div> with a span, that's it.
can you post your code?
You should NOT need a div inside the button. If you need the button to have a specific style give it a class. You could do something like this
CSS:
button.something {
padding: 25px;
border-radius: 100%;
font-size: 20px;
border: none;
}
HTML:
<button class="something">👌</button>
For clean and valid code, you'd better use a :before or :after pseudo-element. This would also take care of the centering by default.
It's even easy to set the content. Either in css only, like this:
1.
button:before {content:"\25b6";}
(put your unicode value there and classes/ids as needed, then specify them in turn in css)
2.
Or if you need to specify the value in mark-up, drop a custom data-* attribute like this:
<button data-myunicode="\25b6"></button>
with each button taking it's own value, then drop this single line in css:
button:before {content:attr(data-myunicode);}
Before answering, let's clear some things out.
div is a block level element, used in an inline element, which is the button element. Browsers will consider this invalid and will fix it by removing the block element from the inline element. For more about CSS concepts like box model, box generation please refer to these resources:
https://developer.mozilla.org/en/docs/Web/HTML/Block-level_elements#Block-level_vs._inline
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Visual_formatting_model
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model
Also, if you are using an IDE, make sure you have installed linting/hinting tools to help you out. These tools can help you in code authoring so, make sure you have them. If you are using software like VSCode or Sublime Editor, there are many free code analysis tools out there.
Let's go back to the code now.
You said
I want to create a circle/round button with an emoji center to the
middle of the button despite the button's size or the emoji image's
size.
I went ahead and created a plunk here where I demonstrate this. Essentially, I wrapped the button around a div which serves as a container and through some CSS magic, I made it to have the same height as its width. More on that you can find at this SO answer.
The #emoji-button then has a border-radius: 100% in order to be round, width is inherited from the parent, meaning it has the same as the container and it position is absolute in order to fit in the container.
The #thumb-emoji has changed to a span element. By user agent styles it has text-align:center.
<div class="button-group">
<button type="submit" id="emoji-button">
<span id="thumb-emoji"></span>
</button>
</div>
CSS:
.button-group {
position: relative;
width: 100px;
}
.button-group:before {
content: "";
display: block;
padding-top: 100%;
}
#emoji-button {
width: inherit;
border-radius: 100%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
#thumb-emoji:after {
content: "\01F44C";
font-size: 200%;
}
You can change the .button-group width to whatever width you want, it will still keep its 1:1 ratio.
You can use then media queries on .button-group to adjust the font-size of your #thumb-emoji, by setting your desired breakpoints.

Font-Awesome icon preventing click in parent button

I'm having a problem where the left two pixels of a Font-Awesome icon I've placed inside of a button element do not trigger the click event of the button.
Here's an example button:
<button class="btn btn-mini">
<i class="icon-edit"></i>
</button>
And here's what it looks like with bootstrap
Any ideas for why those left two pixels don't trigger a click event?
Edit: Here's a test site where I've managed to recreate the issue: http://ace.cwserve.com
I know this post is 4 years old but it might help people understand why a font-awesome "icon" inside a button prevents the click event.
When rendered, the icon class adds a ::before pseudo-element to the icon tag that prevents the button's click event.
Given this situation, we should definitly take a look at the CSS pointer-events Property
The pointer-events property defines whether or not an element reacts
to pointer events.
So we just need to add this css declaration for the "icon" which is inside a button:
button > i {
pointer-events: none;
}
Outline
The outline isn't part of the CSS box, which means it won't fire click events. This is perhaps slightly counter-intuitive, but that's how it works ...
Your page sets an outline on .btn:focus, but this doesn't seem to be the problem, since it has an offset of -2 (meaning it's displayed inside the box, rather than outside of it).
Moving the box on :active
You can move the box on :active, which can cause neat effect, but first the box is moved, and then will the click event be fired, which will use the moved position.
You can see this in action by keeping the mouse button pressed; the box will move, but the event won't be fired until you release the button. So if you move your box to the right by then pixels, then the left 10 pixels won't do anything.
This is according to spec, from the DOM spec:
click
The click event occurs when the pointing device button is clicked over an element. A click is defined as a mousedown and mouseup
over the same screen location. The sequence of these events is:
mousedown
mouseup
click
This seems to be the problem, this following CSS seems to solve it:
button.btn:active {
left: 1px;
top: 1px;
}
Example
Here's a script to demonstrate both issues:
<!DOCTYPE html>
<html><head><style>
body { margin-left: 30px; }
div {
background-color: red;
border: 20px solid green;
outline: 20px solid blue;
width: 100px;
height: 100px;
position: relative;
}
div:active {
left: 20px;
top: 20px;
}
</style></head> <body>
<div></div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$('div').on('click', function(e) {
alert('click!');
});
</script></body></html>

Categories

Resources