Firefox supports relatedTarget for the focus/blur but not the focusin/focusout event.
IE supports it only for the focusin/focusout but not the focus/blur event.
Chrome supports both.
Is there a way to use relatedTarget across browsers?
Here is a blur example (working in Chrome and FF but not IE):
https://jsfiddle.net/rnyqy78m/
And here a focusin example (working in Chrome and IE but not FF):
https://jsfiddle.net/rnyqy78m/1/
Edit
I ended up using browser detection. So I use
var eventType;
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
eventType = 'blur';
} else {
eventType = 'focusout';
}
and then ….addEventListener(eventType, …).
(Posting as an answer so I can use code sample. Although this is more meant to be a comment.)
There's alot of duplicates of this question on SO, just no answers that work 100% of the time. Then again, this problem doesn't come up that often once you get to large/complex apps. If I need the order a user manipulated stuff in, I just save it as a variable.
So my code would just reverse the logic and use 'focus' instead of blur if you need it to work for the first focus as well.
If the blur event also needs to happen if the user doesn't click another input event, I would also bind the focus event handler to any click event on the page.
This kind of strategy would be crossbrowser, it's just not pretty and/or efficient.
This isn't perfect, since it will trigger two events after the first click, but that can be solved easily. But with playign around with the code a bit, it should be possible to find a combination of events that mimic the behaviour needed. (So I'd need more details on when the console element should get the id written or not to write anm exact implementation.)
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
</head>
<body>
<input id="one" value="focus me first">
<input id="two" value="focus me next">
<input id="console">
<script>
var currentElement,
inputOne = document.getElementById('one'),
inputTwo = document.getElementById('two'),
inputConsole = document.getElementById('console'),
focusHandler = function( event ) {
if (currentElement) inputConsole.value += currentElement.id;
currentElement = event.target;
};
inputOne.addEventListener('focus', focusHandler);
inputTwo.addEventListener('focus', focusHandler);
// optional handler for 'focus non-input elements', aka blur the prev clicked element.
document.addEventListener('click', focusHandler);
</script>
</body>
</html>
Related
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("p").on("click", function(event){
console.log("print originalEvent name", event.originalEvent.constructor.name)
});
});
</script>
<p>Click this paragraph.</p>
I recently found that when using mouse click on Safari, "event.pointerType" is undefined where as in chrome it is coming as "mouse" .
I need to do a similar check in safari browser to pass my condition.
I tried couple of things, like using pointerDown eventListener but due to some limitations(like my pointerDown listner code is inside a different jQuery.On listener and due to that it is not triggering on first click and also only either of those listeners are executing skipping the other which should not happen in my case. As i do not have control on jQuery listener trigger i am not able use all eventListener options for this approach to work).
So after some debugging I found on Safari Browser for mouse click events the value of below is coming as "MouseEvent" which works for my requirement. But can i rely on this value for this and is it ok to use the constructor name here.
$(document).on("click", ".my-btn-class", function(evtParam){
if(evtParam.originalEvent && evtParam.originalEvent.constructor &&
evtParam.originalEvent.constructor.name === "MouseEvent"){
//do my logic
}
})
I have a element which contains an element. I've found that in Internet Explorer and Firefox, the mouseover event doesn't fire when I move over the element inside the button. In Chrome it does. Which browser(s) is behaving correctly and where might I go to report the bug? (this might not be the correct place to ask the question)
<button><img id="TheImage" src="Images/Action.gif" /></button>
<script type="text/javascript">
window.addEventListener("load", function() {
document.getElementById("TheImage").addEventListener("mouseover", function(event) {
console.log(event);
});
});
</script>
I want the event to fire and it seems like it should since that's the behavior on every other parent element.
It may be related to bug in FF:
https://github.com/mootools/mootools-core/issues/2662
Though it should works good in IE.
How can I handle the paste selected through right click in javascript?
I tried with "onpaste" event and all other html events available but nothing works.
The onpaste event should work in all modern browsers (UPD Including Opera >= 12.101).
Bind it in jQuery like this:
$('#txt').on('paste', function() {console.log('text pasted!')})
Here's a live example:
http://jsfiddle.net/7N6Xq/
In pure JavaScript it would look something like this for modern browsers
elem.addEventListener ("paste", handler, false); // all browsers and IE9+
and for old IE versions:
elem.attachEvent ("onpaste", handler); // IE<9
You can also combine it with oninput and other events (change, propertychange, dragdrop, etc.) to create a relatively bulletproof tracking of content change.
Footnotes:
1 Opera supports Clipboard API starting from Presto/2.10.286 which corresponds to 12.10 as suggested here. Blink versions of Opera (starting from 15) should also support it but I am unable to test it as there is still no Linux version.
The event isn't exposed by default as "onpaste" IIRC. You can do it quite simply in jQuery by issuing
jQuery(document).bind('paste', function(e){ alert('paste event caught') });
I was surprised question #4532473 got closed unanswered about what happens if you want to capture the afterpaste event. As this is probably the problem half of the cases a possible approach in firefox (tested) is to register an oninput event right inside the onpaste handler and remove the oninput handler as soon as it's done executing.
In ie the onpropertychange should be used instead of oninput. (not tested)
Nice pure JS solution (as requested...) is available on the Mozilla dev site
<!DOCTYPE html>
<html>
<head>
<title>onpaste event example</title>
</head>
<body>
<h1>Play with this editor!</h1>
<textarea id="editor" rows="3" cols="80">
Try pasting text into this area!
</textarea>
<script>
function log(txt) {
document.getElementById("log").appendChild(document.createTextNode(txt + "\n"));
}
function pasteIntercept(evt) {
log("Pasting!");
}
document.getElementById("editor").addEventListener("paste", pasteIntercept, false);
</script>
<h2>Log</h2>
<textarea rows="15" cols="80" id="log" readonly="true"></textarea>
</body>
</html>
In the past, the best method to check for the presence of a mouse was to look for touch event support. However, desktop Chrome now supports touch events, making this test misfire.
Is there a way to test directly for mouseover event support, rather than inferring it based on the presence of touch events?
Resolution: Here is the code that worked, based on the answer from AshleysBrain.
jQuery(function()
{
// Has mouse
jQuery("body").one("mousemove", function(e)
{
attachMouseEvents();
});
// Has touchscreen
jQuery("body").one("touchstart", function(e)
{
// Unbind the mouse detector, as this will fire on some touch devices. Touchstart should always fire first.
jQuery("body").unbind("mousemove");
attachTouchEvents();
});
});
You could do the opposite of the solution for detecting keyboard or touch input. Just wait for an actual touch event or mouse move event and decide based off that. If you check the presence of an event handler, the browser may indicate it has the event even if it is not currently running on hardware that supports it, so the only reliable thing to do is wait and see which actual events fire.
You might want to think about using Modernizr, you could do something like the following using the Modernizer.hasEvent()(docs) method:
Modernizr.hasEvent("mouseover", document);
I have try this and it's work.
<html>
<head>
<script type="text/javascript">
function isEventSupported(eventName) {
var el = document.createElement("body"[eventName] || "div");
var isSupported = "on" + eventName.toLowerCase() in el || top.Event && typeof top.Event == "object" && eventName.toUpperCase() in top.Event;
el = null;
return isSupported;
}
</script>
</head>
<body onload="alert(isEventSupported('mouseover'));">TEST mouseover event</body>
</html>
I took the function isEventSupported from http://www.strictly-software.com/eventsupport.htm
If web sites can detect that you're using a mobile browser as accurately as they do why can't you use the same technique to infer they don't have mouseover support?
I have a div which onmouseover, displays a panel and onmouseout makes it disappear. JavaScript code is as follows:
function ShowPanel() {
document.getElementById("thePanel").style.display = "inline";
}
function HidePanel() {
document.getElementById("thePanel").style.display = "none";
}
The code works in Firefox and IE perfectly. The problem is Chrome. It works until the mouse is on the textbox in the panel. When the mouse goes on the textbox the onmouseout event is called even though the textbox is part of the panel and should remain open.
What you need is the behavior of the onmouseenter event instead of onmouseover and onmouseleave instead of onmouseout. The problem is that those events work only in IE (they actually got those ones right). You either need to simulate that behavior taking into account all of the differences in the event handling in different browsers, or just use a good JavaScript library that would take care of that for you. For example jQuery has .mouseenter() and .mouseleave() that are simulated on browser that don't support those events natively, and even a nice shortcut .hover() to set both at the same time.
I wouldn't recommend doing it manually unless you really know all of the quirks and inconsistencies of event models in different browsers (and you don't since you asked this question) but if you want to see how jQuery is doing it then see events.js and search for mouseenter and mouseleave.
In Chrome as you've found the mouseout event is fired whenever you move from the parent element (on which the handler is registered) and child elements contained within it.
The simple fix is to use jQuery, which will simulate mouseleave events (which don't suffer that problem) on browsers that don't support it.
Alternatively, in your mouseout handler, look at the toElement property of the event, and traverse its parent list and see if your original parent is in that list. Only process your action if it was not in the list.
document.getElementById('outer').addEventListener('mouseout', function(ev) {
var el = ev.toElement;
while (el && el !== document.body) {
if (el === this) {
console.log('mouseout ignored');
return; // enclosed - don't do anything
}
el = el.parentNode;
}
console.log('mouseout');
}, false);
demo at http://jsfiddle.net/raybellis/s4EQT/