Disable permanent active state - javascript

I have a link, and if you drag this link then release, the link will keep his active state.
Example: http://jsfiddle.net/Ek43k/3/
<a href="javascript:void(0);" id="foo" >Drag me</a>
#foo:active{
color:red;
}
How can I prevent this?
(Only in IE and FF)

This is a known bug in Firefox, see https://bugzilla.mozilla.org/show_bug.cgi?id=193321
The bug has had an on-and-off status with several reports; the behavior is non-standard and browser-specific.
You can build a work-around for it, but you're stuck with javascript. After much searching, I determined that unless you're running in privileged mode (i.e. your code is in an extension), you cannot directly influence the pseudo-selector states. That means you're left with adding/removing a class name:
<a href="#" onmousedown="this.className = '';" ondragend="this.className = 'inactive';" id="foo" >Drag me</a>
Try it: http://jsfiddle.net/frsRS/
If you do have privileged mode, you can use the method that Firebug employs in their CSS Panel, using inIDOMUtils.setContentState
var node = document.getElementById("foo");
var domUtil = Components.classes["#mozilla.org/inspector/dom-utils;1"].getService(Components.interfaces.inIDOMUtils);
domUtil.setContentState( node , 1);
Edit
Here is specific code for binding cross-browser delegates rather than putting the javascript inline (shown here for demonstration purposes, but generally bad practice)
function addEvent(ele, evnt, funct) {
if (ele.addEventListener) // W3C
return ele.addEventListener(evnt,funct,false);
else if (ele.attachEvent) // IE
return ele.attachEvent("on"+evnt,funct);
}
addEvent(document.body, 'mousedown', function (e) {
if(e.target.tagName == 'A') e.target.style.color = '';
});
addEvent(document.body, 'dragend', function (e) {
if(e.target.tagName == 'A') e.target.style.color = 'blue';
});
Try it: http://jsfiddle.net/HYJCQ/
This uses the element's style rather than a css class, you can swap out the methods as desired.
Another way, as suggested by Supr, is to remove and immediately re-add the element from DOM. You can accomplish this using a delegate as well:
function addEvent(ele, evnt, funct) {
if (ele.addEventListener) // W3C
return ele.addEventListener(evnt,funct,false);
else if (ele.attachEvent) // IE
return ele.attachEvent("on"+evnt,funct);
}
addEvent(document.body, 'dragend', function (e) {
if(e.target.tagName != 'A') return;
var parent = e.target.parentNode;
var sib = e.target.nextSibling;
parent.insertBefore(
parent.removeChild(e.target),
sib
);
});
Try it: http://jsfiddle.net/ymPfH/
Both methods that utilize delegation are better approaches than looping elements -- that way, the script will apply to any a tags added to the page after load (similar to how jQuery's live or on methods work).
Documentation
Bugzilla entry - https://bugzilla.mozilla.org/show_bug.cgi?id=193321
Drag and Drop on MDN (ondragend) - https://developer.mozilla.org/en-US/docs/Drag_and_Drop
inIDOMUtils - https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/inIDOMUtils

Detach and reattach the link from the DOM tree to disable its active state. Do this when the drag ends and you've got this:
$('a').on('dragend',function(){
var $this = $(this),
$parent = $this.parent(),
$next = $(this.nextSibling); // $.next() doesn't include text
$this.detach().insertBefore($next);
});
No need to mess with your HTML or CSS or do away with :active. Seems to work in both FF and IE.
Edit: I don't usually write pure Javascript for DOM-handling so the quality of this might not be top notch, but here it is without jQuery:
(function(){
var previousOnload = window.onload || function noop(){};
window.onload = function (){
// Call any previously added onload callbacks
previousOnload();
// Add deactivator to each <a> element
var elements = document.getElementsByTagName('a');
for (var i=0; i<elements.length; i++){
elements[i].ondragend = deactivate;
}
function deactivate(){
var parent = this.parentNode,
position = this.nextSibling;
parent.removeChild(this);
// Using insertBefore instead of appendChild so that it is put at the right position among the siblings
parent.insertBefore(this, position);
}
};
})();
I took care of a few issues that came to mind to make it fully plug-and-play. Tested in Opera, Chrome, Firefox and Internet Explorer.
Edit 2: Inspired by Chris, another way to apply the fix is to use the ondragend attribute directly to connect the deactivator (not tested):
<head>
<script>
function deactivate(){
var parent = this.parentNode,
position = this.nextSibling;
parent.removeChild(this);
// Using insertBefore instead of appendChild so that it is put at the right position among the siblings
parent.insertBefore(this, position);
}
</script>
</head>
<body>
Drag me
<body>
The downside is that it requires the ondragend attribute with javascript to be specified on each link manually/explicitly. I guess it's a matter of preference.
Final (?) Edit: See comments for delegate/live versions of these and Chris' answer.

If jQuery is an option, I think this code works, at least in FF: http://jsfiddle.net/Ek43k/89/
HTML
<a href="#" id="foo" class="inactive" >Drag me</a>
CSS
.inactive:active{color:red;}
.active:active{color:blue;}
jQuery
$('body').on('mousedown', 'a.inactive', function() {
$(this).on('mousemove', function() {
$(this).removeClass().addClass('active');
});
});
$('body').on('mousedown', 'a.active', function() {
$(this).removeClass().addClass('inactive');
});

just add this CSS:
#foo:hover {
color: green;
}

Related

javascript to check a link for string & launch modal

Have a page containing links.
When a link is clicked I want Javascript (or other) to check if the link contains (e.g. cheese)
If if does, then a modal should launch displaying the link.
example:
http://mylink/just-normal/ -- when this clicked, should proceed as normal
http://mylink/with-cheese/ -- when this clicked, should launch modal
http://mylink/another-link/ -- when this clicked, should proceed as normal
http://mylink/other-link/ -- when this clicked, should proceed as normal
Modal should display the full link.
Any assistance is appreciated.
Below is what I've got so far.
My specific question is:
Question: When I click any link on the site, a modal opens. It seems to be targeting all links and not just the links containing the specific word(s).
jQuery(function () {
jQuery(document).on('click', jQuery('a') , function(event){
var e = event;
event.preventDefault;
var that = event.target;
if(jQuery(that).is("span")){
that = jQuery(event.target).parent();
}
if(jQuery(that).attr('href')){
var url = jQuery(that).attr('href').toLowerCase();
if(jQuery.browser.webkit || jQuery.browser.mozilla && (url.indexOf('.my.test.here/') >=0)) {
ie_pointer(e, that);
}
else if (jQuery.browser.webkit && || jQuery.browser.mozilla (url.indexOf('something.else/') >=0)){
var overall = jQuery('.overall');
ie_pointer(e, overall, that);
}
}
});
});
function ie_pointer(event, obj, that){
event.preventDefault();
if(that){
var url = jQuery(that).attr('href');
}
else{
var url = jQuery(obj).attr('href');
}
jQuery('<div class="modal-backdrop"></div>').hide().appendTo(document.body).fadeIn();
jQuery(obj).after('<div class="modal-content" style="padding:10px"><h3 style="color:#333">Please copy the blue link below into Internet Explorer</h3><p style="font-size: 1.2rem; color:#333">This form is currently unavailable in Firefox & Chrome.</p><h4 style="color: #0099cc; max-width: 400px; word-wrap:break-word;">'+url+'</h4><i onclick="close_modal()" class="icon-remove"></i></button></div>');
}
function close_modal(){
jQuery(".modal-backdrop").fadeOut(function(){jQuery(this).remove()});
jQuery('.modal-content').fadeOut(function(){jQuery(this).remove()});
}
Your click event handler is set up for event delegation so that it only responds when event.target is an <a>:
jQuery(document).on('click', jQuery('a') , function(event){
Yet, inside of the handler, you have this:
if(jQuery(that).is("span")){
that = jQuery(event.target).parent();
}
Since you have that set to event.target, this if condition will never be true, so I'm not sure what you are trying to accomplish with it.
The remainder of the function runs when the <a> element has an href, but there too, you have if conditions that don't quite make sense:
if(jQuery.browser.webkit ||
jQuery.browser.mozilla && (url.indexOf('.my.test.here/') >=0)) {
ie_pointer(e, that);
} else if (jQuery.browser.webkit && ||
jQuery.browser.mozilla (url.indexOf('something.else/') >=0)){
var overall = jQuery('.overall');
ie_pointer(e, overall, that);
}
Your first condition will be true if the browser is webkit or if it is mozilla and the attribute contains your test string. Why don't you want to test for the string when the browser is webkit?
Your else if condition does the same thing, but you have a syntax error in it because you forget && here:
jQuery.browser.mozilla (url.indexOf('something.else/') >=0))
And, perhaps more importantly, why do you care what browser it is? JQuery deprecated the browser flags in version 1.9 because they are based on the navigator.userAgent, which has always been an unreliable way of browser sniffing.
Here's a slimmed down example of getting links that contain a certain string in their href to do one thing and all others to do something else using the standard CSS attribute selector:
var url = "console";
// Simply use the attribute wildcard selector to make sure
// you are only selecting links you care about in the first place
$("a[href*='" + url + "']").on("click", function(evt){
evt.preventDefault();
alert("You clicked a link that I care about!");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I should cause an alert().<br>
I should cause an alert().<br>
I should NOT cause an alert().<br>
I should NOT cause an alert().

getting the item under the cursor when the cursor is clicked in google chrome [duplicate]

I want a function that tells me which element the mouse cursor is over.
So, for example, if the user's mouse is over this textarea (with id wmd-input), calling window.which_element_is_the_mouse_on() will be functionally equivalent to $("#wmd-input").
DEMO
There's a really cool function called document.elementFromPoint which does what it sounds like.
What we need is to find the x and y coords of the mouse and then call it using those values:
document.addEventListener('mousemove', e => {
console.clear()
console.log( document.elementFromPoint(e.clientX, e.clientY) )
}, {passive: true})
[class^='level']{
width: 100px;
height: 100px;
padding: 15px;
background: #00000033;
}
<div class='level-1'>
<div class='level-2'>
<div class='level-3'>
Hover
</div>
</div>
</div>
document.elementFromPoint
jQuery event object
In newer browsers, you could do the following:
document.querySelectorAll( ":hover" );
That'll give you a NodeList of items that the mouse is currently over in document order. The last element in the NodeList is the most specific, each preceding one should be a parent, grandparent, and so on.
Although the following may not actually answering the question, since this is the first result of googling (the googler may not asking exactly the same question:), hope it will provide some extra input.
There are actually two different approaches to get a list of all elements the mouse is currently over (for newer browsers, perhaps):
The "structural" approach - Ascending DOM tree
As in dherman's answer, one can call
var elements = document.querySelectorAll(':hover');
However, this assumes that only children will overlay their ancestors, which is usually the case, but not true in general, especially when dealing with SVG where element in different branches of the DOM tree may overlap each other.
The "visual" approach - Based on "visual" overlapping
This method uses document.elementFromPoint(x, y) to find the topmost element, temporarily hide it (since we recover it immediately in the same context, the browser will not actually renders this), then go on to find the second topmost element... Looks a little hacky, but it returns what you expect when there are, e.g., siblings elements in a tree occluding each other. Please find this post for more details,
function allElementsFromPoint(x, y) {
var element, elements = [];
var old_visibility = [];
while (true) {
element = document.elementFromPoint(x, y);
if (!element || element === document.documentElement) {
break;
}
elements.push(element);
old_visibility.push(element.style.visibility);
element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
}
for (var k = 0; k < elements.length; k++) {
elements[k].style.visibility = old_visibility[k];
}
elements.reverse();
return elements;
}
Try both, and check their different returns.
elementFromPoint() gets only the first element in DOM tree. This is mostly not enough for developers needs. To get more than one element at e.g. the current mouse pointer position, this is the function you need:
document.elementsFromPoint(x, y) . // Mind the 's' in elements
This returns an array of all element objects under the given point.
Just pass the mouse X and Y values to this function.
More information is here: DocumentOrShadowRoot.elementsFromPoint()
For very old browsers which are not supported, you may use this answer as a fallback.
The following code will help you to get the element of the mouse pointer. The resulted elements will display in the console.
document.addEventListener('mousemove', function(e) {
console.log(document.elementFromPoint(e.pageX, e.pageY));
})
Mouseover events bubble, so you can put a single listener on the body and wait for them to bubble up, then grab the event.target or event.srcElement:
function getTarget(event) {
var el = event.target || event.srcElement;
return el.nodeType == 1? el : el.parentNode;
}
<body onmouseover="doSomething(getTarget(event));">
You can look at the target of the mouseover event on some suitable ancestor:
var currentElement = null;
document.addEventListener('mouseover', function (e) {
currentElement = e.target;
});
Here’s a demo.
Demo :D
Move your mouse in the snippet window :D
<script>
document.addEventListener('mouseover', function (e) {
console.log ("You are in ", e.target.tagName);
});
</script>
<!-- One simple solution to your problem could be like this: -->
<div>
<input type="text" id="fname" onmousemove="javascript: alert(this.id);" />
<!-- OR -->
<input type="text" id="fname" onclick="javascript: alert(this.id);" />
</div>
<!-- Both mousemove over the field & click on the field displays "fname"-->
<!-- Works fantastic in IE, FireFox, Chrome, Opera. -->
<!-- I didn't test it for Safari. -->
You can use this selector to undermouse object and then manipulate it as a jQuery object:
$(':hover').last();
2022 Update:
document.elementsFromPoint() (Note the 's' in elements) is compatible with all major browsers. It basically does the same thing that elementFrompoint does, but retrieves all the elements in DOM order.
Mozilla has a good example of this:
HTML
<div>
<p>Some text</p>
</div>
<p>Elements at point 30, 20:</p>
<div id="output"></div>
JavaScript
let output = document.getElementById("output");
if (document.elementsFromPoint) {
let elements = document.elementsFromPoint(30, 20);
for (var i = 0; i < elements.length; i++) {
output.textContent += elements[i].localName;
if (i < elements.length - 1) {
output.textContent += " < ";
}
}
} else {
output.innerHTML = "<span style=\"color: red;\">" +
"Browser does not support <code>document.elementsFromPoint()</code>" +
"</span>";
}
Output
Some text
Elements at point 30, 20:
p < div < body < html
https://developer.mozilla.org/en-US/docs/Web/API/Document/elementsFromPoint
The target of the mousemove DOM event is the top-most DOM element under the cursor when the mouse moves:
(function(){
//Don't fire multiple times in a row for the same element
var prevTarget=null;
document.addEventListener('mousemove', function(e) {
//This will be the top-most DOM element under cursor
var target=e.target;
if(target!==prevTarget){
console.log(target);
prevTarget=target;
}
});
})();
This is similar to #Philip Walton's solution, but doesn't require jQuery or a setInterval.
Here's a solution for those that may still be struggling. You want to add a mouseover event on the 'parent' element of the child element(s) you want detected. The below code shows you how to go about it.
const wrapper = document.getElementById('wrapper') //parent element
const position = document.getElementById("displaySelection")
wrapper.addEventListener('mousemove', function(e) {
let elementPointed = document.elementFromPoint(e.clientX, e.clientY)
console.log(elementPointed)
});
Demo on CodePen
Let me start out by saying that I don't recommend using the method I'm about to suggest. It's much better to use event driven development and bind events only to the elements you're interested in knowing whether or not the mouse is over with mouseover, mouseout, mouseenter, mouseleave, etc.
If you absolutely must have the ability to know which element the mouse is over, you'd need to write a function that binds the mouseover event to everything in the DOM, and then store whatever the current element is in some variable.
You could so something like this:
window.which_element_is_the_mouse_on = (function() {
var currentElement;
$("body *").on('mouseover', function(e) {
if(e.target === e.currentTarget) {
currentElement = this;
}
});
return function() {
console.log(currentElement);
}
}());
Basically, I've created an immediate function which sets the event on all elements and stores the current element within the closure to minimize your footprint.
Here's a working demo that calls window.which_element_is_the_mouse_on every second and logs what element the mouse is currently over to the console.
http://jsfiddle.net/LWFpJ/1/

How to get DOM or jQuery element by mouse coordinates? [duplicate]

I want a function that tells me which element the mouse cursor is over.
So, for example, if the user's mouse is over this textarea (with id wmd-input), calling window.which_element_is_the_mouse_on() will be functionally equivalent to $("#wmd-input").
DEMO
There's a really cool function called document.elementFromPoint which does what it sounds like.
What we need is to find the x and y coords of the mouse and then call it using those values:
document.addEventListener('mousemove', e => {
console.clear()
console.log( document.elementFromPoint(e.clientX, e.clientY) )
}, {passive: true})
[class^='level']{
width: 100px;
height: 100px;
padding: 15px;
background: #00000033;
}
<div class='level-1'>
<div class='level-2'>
<div class='level-3'>
Hover
</div>
</div>
</div>
document.elementFromPoint
jQuery event object
In newer browsers, you could do the following:
document.querySelectorAll( ":hover" );
That'll give you a NodeList of items that the mouse is currently over in document order. The last element in the NodeList is the most specific, each preceding one should be a parent, grandparent, and so on.
Although the following may not actually answering the question, since this is the first result of googling (the googler may not asking exactly the same question:), hope it will provide some extra input.
There are actually two different approaches to get a list of all elements the mouse is currently over (for newer browsers, perhaps):
The "structural" approach - Ascending DOM tree
As in dherman's answer, one can call
var elements = document.querySelectorAll(':hover');
However, this assumes that only children will overlay their ancestors, which is usually the case, but not true in general, especially when dealing with SVG where element in different branches of the DOM tree may overlap each other.
The "visual" approach - Based on "visual" overlapping
This method uses document.elementFromPoint(x, y) to find the topmost element, temporarily hide it (since we recover it immediately in the same context, the browser will not actually renders this), then go on to find the second topmost element... Looks a little hacky, but it returns what you expect when there are, e.g., siblings elements in a tree occluding each other. Please find this post for more details,
function allElementsFromPoint(x, y) {
var element, elements = [];
var old_visibility = [];
while (true) {
element = document.elementFromPoint(x, y);
if (!element || element === document.documentElement) {
break;
}
elements.push(element);
old_visibility.push(element.style.visibility);
element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
}
for (var k = 0; k < elements.length; k++) {
elements[k].style.visibility = old_visibility[k];
}
elements.reverse();
return elements;
}
Try both, and check their different returns.
elementFromPoint() gets only the first element in DOM tree. This is mostly not enough for developers needs. To get more than one element at e.g. the current mouse pointer position, this is the function you need:
document.elementsFromPoint(x, y) . // Mind the 's' in elements
This returns an array of all element objects under the given point.
Just pass the mouse X and Y values to this function.
More information is here: DocumentOrShadowRoot.elementsFromPoint()
For very old browsers which are not supported, you may use this answer as a fallback.
The following code will help you to get the element of the mouse pointer. The resulted elements will display in the console.
document.addEventListener('mousemove', function(e) {
console.log(document.elementFromPoint(e.pageX, e.pageY));
})
Mouseover events bubble, so you can put a single listener on the body and wait for them to bubble up, then grab the event.target or event.srcElement:
function getTarget(event) {
var el = event.target || event.srcElement;
return el.nodeType == 1? el : el.parentNode;
}
<body onmouseover="doSomething(getTarget(event));">
You can look at the target of the mouseover event on some suitable ancestor:
var currentElement = null;
document.addEventListener('mouseover', function (e) {
currentElement = e.target;
});
Here’s a demo.
Demo :D
Move your mouse in the snippet window :D
<script>
document.addEventListener('mouseover', function (e) {
console.log ("You are in ", e.target.tagName);
});
</script>
<!-- One simple solution to your problem could be like this: -->
<div>
<input type="text" id="fname" onmousemove="javascript: alert(this.id);" />
<!-- OR -->
<input type="text" id="fname" onclick="javascript: alert(this.id);" />
</div>
<!-- Both mousemove over the field & click on the field displays "fname"-->
<!-- Works fantastic in IE, FireFox, Chrome, Opera. -->
<!-- I didn't test it for Safari. -->
You can use this selector to undermouse object and then manipulate it as a jQuery object:
$(':hover').last();
2022 Update:
document.elementsFromPoint() (Note the 's' in elements) is compatible with all major browsers. It basically does the same thing that elementFrompoint does, but retrieves all the elements in DOM order.
Mozilla has a good example of this:
HTML
<div>
<p>Some text</p>
</div>
<p>Elements at point 30, 20:</p>
<div id="output"></div>
JavaScript
let output = document.getElementById("output");
if (document.elementsFromPoint) {
let elements = document.elementsFromPoint(30, 20);
for (var i = 0; i < elements.length; i++) {
output.textContent += elements[i].localName;
if (i < elements.length - 1) {
output.textContent += " < ";
}
}
} else {
output.innerHTML = "<span style=\"color: red;\">" +
"Browser does not support <code>document.elementsFromPoint()</code>" +
"</span>";
}
Output
Some text
Elements at point 30, 20:
p < div < body < html
https://developer.mozilla.org/en-US/docs/Web/API/Document/elementsFromPoint
The target of the mousemove DOM event is the top-most DOM element under the cursor when the mouse moves:
(function(){
//Don't fire multiple times in a row for the same element
var prevTarget=null;
document.addEventListener('mousemove', function(e) {
//This will be the top-most DOM element under cursor
var target=e.target;
if(target!==prevTarget){
console.log(target);
prevTarget=target;
}
});
})();
This is similar to #Philip Walton's solution, but doesn't require jQuery or a setInterval.
Here's a solution for those that may still be struggling. You want to add a mouseover event on the 'parent' element of the child element(s) you want detected. The below code shows you how to go about it.
const wrapper = document.getElementById('wrapper') //parent element
const position = document.getElementById("displaySelection")
wrapper.addEventListener('mousemove', function(e) {
let elementPointed = document.elementFromPoint(e.clientX, e.clientY)
console.log(elementPointed)
});
Demo on CodePen
Let me start out by saying that I don't recommend using the method I'm about to suggest. It's much better to use event driven development and bind events only to the elements you're interested in knowing whether or not the mouse is over with mouseover, mouseout, mouseenter, mouseleave, etc.
If you absolutely must have the ability to know which element the mouse is over, you'd need to write a function that binds the mouseover event to everything in the DOM, and then store whatever the current element is in some variable.
You could so something like this:
window.which_element_is_the_mouse_on = (function() {
var currentElement;
$("body *").on('mouseover', function(e) {
if(e.target === e.currentTarget) {
currentElement = this;
}
});
return function() {
console.log(currentElement);
}
}());
Basically, I've created an immediate function which sets the event on all elements and stores the current element within the closure to minimize your footprint.
Here's a working demo that calls window.which_element_is_the_mouse_on every second and logs what element the mouse is currently over to the console.
http://jsfiddle.net/LWFpJ/1/

Determine which element the mouse pointer is on top of in JavaScript

I want a function that tells me which element the mouse cursor is over.
So, for example, if the user's mouse is over this textarea (with id wmd-input), calling window.which_element_is_the_mouse_on() will be functionally equivalent to $("#wmd-input").
DEMO
There's a really cool function called document.elementFromPoint which does what it sounds like.
What we need is to find the x and y coords of the mouse and then call it using those values:
document.addEventListener('mousemove', e => {
console.clear()
console.log( document.elementFromPoint(e.clientX, e.clientY) )
}, {passive: true})
[class^='level']{
width: 100px;
height: 100px;
padding: 15px;
background: #00000033;
}
<div class='level-1'>
<div class='level-2'>
<div class='level-3'>
Hover
</div>
</div>
</div>
document.elementFromPoint
jQuery event object
In newer browsers, you could do the following:
document.querySelectorAll( ":hover" );
That'll give you a NodeList of items that the mouse is currently over in document order. The last element in the NodeList is the most specific, each preceding one should be a parent, grandparent, and so on.
Although the following may not actually answering the question, since this is the first result of googling (the googler may not asking exactly the same question:), hope it will provide some extra input.
There are actually two different approaches to get a list of all elements the mouse is currently over (for newer browsers, perhaps):
The "structural" approach - Ascending DOM tree
As in dherman's answer, one can call
var elements = document.querySelectorAll(':hover');
However, this assumes that only children will overlay their ancestors, which is usually the case, but not true in general, especially when dealing with SVG where element in different branches of the DOM tree may overlap each other.
The "visual" approach - Based on "visual" overlapping
This method uses document.elementFromPoint(x, y) to find the topmost element, temporarily hide it (since we recover it immediately in the same context, the browser will not actually renders this), then go on to find the second topmost element... Looks a little hacky, but it returns what you expect when there are, e.g., siblings elements in a tree occluding each other. Please find this post for more details,
function allElementsFromPoint(x, y) {
var element, elements = [];
var old_visibility = [];
while (true) {
element = document.elementFromPoint(x, y);
if (!element || element === document.documentElement) {
break;
}
elements.push(element);
old_visibility.push(element.style.visibility);
element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
}
for (var k = 0; k < elements.length; k++) {
elements[k].style.visibility = old_visibility[k];
}
elements.reverse();
return elements;
}
Try both, and check their different returns.
elementFromPoint() gets only the first element in DOM tree. This is mostly not enough for developers needs. To get more than one element at e.g. the current mouse pointer position, this is the function you need:
document.elementsFromPoint(x, y) . // Mind the 's' in elements
This returns an array of all element objects under the given point.
Just pass the mouse X and Y values to this function.
More information is here: DocumentOrShadowRoot.elementsFromPoint()
For very old browsers which are not supported, you may use this answer as a fallback.
The following code will help you to get the element of the mouse pointer. The resulted elements will display in the console.
document.addEventListener('mousemove', function(e) {
console.log(document.elementFromPoint(e.pageX, e.pageY));
})
Mouseover events bubble, so you can put a single listener on the body and wait for them to bubble up, then grab the event.target or event.srcElement:
function getTarget(event) {
var el = event.target || event.srcElement;
return el.nodeType == 1? el : el.parentNode;
}
<body onmouseover="doSomething(getTarget(event));">
You can look at the target of the mouseover event on some suitable ancestor:
var currentElement = null;
document.addEventListener('mouseover', function (e) {
currentElement = e.target;
});
Here’s a demo.
Demo :D
Move your mouse in the snippet window :D
<script>
document.addEventListener('mouseover', function (e) {
console.log ("You are in ", e.target.tagName);
});
</script>
<!-- One simple solution to your problem could be like this: -->
<div>
<input type="text" id="fname" onmousemove="javascript: alert(this.id);" />
<!-- OR -->
<input type="text" id="fname" onclick="javascript: alert(this.id);" />
</div>
<!-- Both mousemove over the field & click on the field displays "fname"-->
<!-- Works fantastic in IE, FireFox, Chrome, Opera. -->
<!-- I didn't test it for Safari. -->
You can use this selector to undermouse object and then manipulate it as a jQuery object:
$(':hover').last();
2022 Update:
document.elementsFromPoint() (Note the 's' in elements) is compatible with all major browsers. It basically does the same thing that elementFrompoint does, but retrieves all the elements in DOM order.
Mozilla has a good example of this:
HTML
<div>
<p>Some text</p>
</div>
<p>Elements at point 30, 20:</p>
<div id="output"></div>
JavaScript
let output = document.getElementById("output");
if (document.elementsFromPoint) {
let elements = document.elementsFromPoint(30, 20);
for (var i = 0; i < elements.length; i++) {
output.textContent += elements[i].localName;
if (i < elements.length - 1) {
output.textContent += " < ";
}
}
} else {
output.innerHTML = "<span style=\"color: red;\">" +
"Browser does not support <code>document.elementsFromPoint()</code>" +
"</span>";
}
Output
Some text
Elements at point 30, 20:
p < div < body < html
https://developer.mozilla.org/en-US/docs/Web/API/Document/elementsFromPoint
The target of the mousemove DOM event is the top-most DOM element under the cursor when the mouse moves:
(function(){
//Don't fire multiple times in a row for the same element
var prevTarget=null;
document.addEventListener('mousemove', function(e) {
//This will be the top-most DOM element under cursor
var target=e.target;
if(target!==prevTarget){
console.log(target);
prevTarget=target;
}
});
})();
This is similar to #Philip Walton's solution, but doesn't require jQuery or a setInterval.
Here's a solution for those that may still be struggling. You want to add a mouseover event on the 'parent' element of the child element(s) you want detected. The below code shows you how to go about it.
const wrapper = document.getElementById('wrapper') //parent element
const position = document.getElementById("displaySelection")
wrapper.addEventListener('mousemove', function(e) {
let elementPointed = document.elementFromPoint(e.clientX, e.clientY)
console.log(elementPointed)
});
Demo on CodePen
Let me start out by saying that I don't recommend using the method I'm about to suggest. It's much better to use event driven development and bind events only to the elements you're interested in knowing whether or not the mouse is over with mouseover, mouseout, mouseenter, mouseleave, etc.
If you absolutely must have the ability to know which element the mouse is over, you'd need to write a function that binds the mouseover event to everything in the DOM, and then store whatever the current element is in some variable.
You could so something like this:
window.which_element_is_the_mouse_on = (function() {
var currentElement;
$("body *").on('mouseover', function(e) {
if(e.target === e.currentTarget) {
currentElement = this;
}
});
return function() {
console.log(currentElement);
}
}());
Basically, I've created an immediate function which sets the event on all elements and stores the current element within the closure to minimize your footprint.
Here's a working demo that calls window.which_element_is_the_mouse_on every second and logs what element the mouse is currently over to the console.
http://jsfiddle.net/LWFpJ/1/

How to get the id of an element on a button click in mootools(1.1)

I have a bunch of links with non-pre-determined id's like so:
Remove 123
Remove 234
Remove 567
Remove 890
I have an event handler like so:
$$('.remove_pid').addEvents({
'click': removePid
});
which calls this function
function removePid(event)
{
alert('yo what is my element id???');
}
So the question is how do i get the element id in the function removePid()?
UPDATE:
#Aishwar, event.target.id seems to work in the following case, but not specifically in my case
<img src="/123.jpg" id="pid_123">
UPDATE 2:
I thought it was inconsequential, but instead of the text "Remove 123" I actually have an image like so:
<img src="/123.jpg">
So, thanks for #Dimitra for pointing it out. I was surprised with the de-vote but am happy to say i probably deserve it.
I do not have experience working with mootools. But I would guess you can just do something along these lines, in removePid:
var element = event.srcElement || event.target
element.id // is the element's id, element is the DOM element itself
as per the markup posted in the FINAL update:
http://www.jsfiddle.net/dimitar/Sr8LC/
$$('.remove_pid').addEvents({
'click': function(e) {
new Event(e).stop();
var id = this.getProperty("id");
alert(id);
alert(id.replace("pid_", ""));
}
});
to use a named function and keep the event:
var removeProduct = function(e) {
new Event(e).stop();
var id = this.getProperty("id");
alert(id);
alert(id.replace("pid_", ""));
};
$$('a.remove_pid').each(function(el) {
el.addEvents({
'click': removeProduct.bind(el)
});
});
within both functions, this will refer to the trigger element (the anchor), so you can read it's property, etc. this.getFirst() will reference the image (if you want it).
Think I found it:
function removePid(event)
{
//alert('yo what is my element id???');
$(event.target).getParent('a').getProperty('id');
}
This works in FF 3.6

Categories