I have a small div above (hover) a big one.
I assign onmouseover and onmouseout events to the wrapper div.
For image caption roll-over animation.
The problem is when the mouse is above the caption itself, causing an unwanted result (probably event bubbling).
And another problem: sometimes when you move mouse from outside to container you get a a triple sequence: (it should be just 2):
-I am over-
-I am out-
-I am over-
How to make it work? (no jQuery)
Must work on all browsers.
Demo
I have added firebug console log, to a better debugging.
UPDATE:
I've added this (not in the online demo) in RollOverDescription:
if (!eventHandle) var eventHandle = window.event;
var srcEle = eventHandle.srcElement.id;
if(srcEle=="imageDescription" ){
return;
}
But it doesn't help.
This article on quirksmode ( near the bottom ) has an explanation of what you are experiencing and a script that might help you. There is a lot of cross browser info regarding mouse events too
OK, here's some working code. I don't promise this is the most efficient or that it won't cause memory leaks in IE (or that it works in IE - please let me know ). This is why people use libraries, much safer and easier.
// a general purpose, cross browser event adder
// returns a function that if run removes the event
function addEvent( el, eventType, handler, capturing ) {
if( el.addEventListener ) {
el.addEventListener( eventType, handler, capturing || false );
var removeEvent = function() { el.removeEventListener( eventType, handler, capturing || false ) };
} else if( el.attachEvent ) {
var fn = function() {
handler.call( el, normalise( window.event ) );
};
el.attachEvent( 'on'+eventType, fn );
var removeEvent = function(){ el.detachEvent( 'on'+eventType, fn ) };
}
function normalise( e ) {
e.target = e.srcElement;
e.relatedTarget = e.toElement;
e.preventDefault = function(){ e.returnValue = false };
e.stopPropagation = function(){ e.cancelBubble = true };
return e;
};
return removeEvent;
};
// adds mouseover and mouseout event handlers to a dom element
// mouseover and out events on child elements are ignored by this element
// returns a function that when run removes the events
// you need to send in both handlers - an empty function will do
function addMouseOverOutEvents( element, overHandler, outHandler ) {
function out( e ) {
var fromEl = e.target;
var toEl = e.relatedTarget;
// if the mouseout didn't originate at our element we can ignore it
if( fromEl != element ) return;
// if the element we rolled onto is a child of our element we can ignore it
while( toEl ) {
toEl = toEl.parentNode;
if( toEl == element ) return;
}
outHandler.call( element, e );
}
function over( e ) {
var toEl = e.target;
var fromEl = e.relatedTarget;
// if the mouseover didn't originate at our element we can ignore it
if( toEl != element ) return;
// if the element we rolled from is a child of our element we can ignore it
while( fromEl ) {
fromEl = fromEl.parentNode;
if( fromEl == element ) return;
}
overHandler.call( element, e );
}
var killers = [];
killers.push( addEvent( element, 'mouseover', over ) );
killers.push( addEvent( element, 'mouseout', out ) );
return function() {
killers[0]();
killers[1]();
}
}
Example of use:
// add the events
var remover = addMouseOverOutEvents(
document.getElementById( 'elementId' ),
function( e ) {
this.style.background = 'red';
console.log( 'rolled in: '+e.target.id );
},
function( e ) {
this.style.background = 'blue'
console.log( 'rolled out: '+e.target.id );
}
);
//remove the events
remover();
Related
I'm trying to insert html data dynamically to a list that is dynamically created, but when i try to attach an onclick event for the button that is dynamically created the event is not firing. Solution would be really appreciated.
Javascript code:
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('btnSubmit').addEventListener('click', function () {
var name = document.getElementById('txtName').value;
var mobile = document.getElementById('txtMobile').value;
var html = '<ul>';
for (i = 0; i < 5; i++) {
html = html + '<li>' + name + i + '</li>';
}
html = html + '</ul>';
html = html + '<input type="button" value="prepend" id="btnPrepend" />';
document.getElementsByTagName('form')[0].insertAdjacentHTML('afterend', html);
});
document.getElementById('btnPrepend').addEventListener('click', function () {
var html = '<li>Prepending data</li>';
document.getElementsByTagName('ul')[0].insertAdjacentHTML('afterbegin', html);
});
});
HTML Code:
<form>
<div class="control">
<label>Name</label>
<input id="txtName" name="txtName" type="text" />
</div>
<div class="control">
<label>Mobile</label>
<input id="txtMobile" type="text" />
</div>
<div class="control">
<input id="btnSubmit" type="button" value="submit" />
</div>
</form>
This is due to the fact that your element is dynamically created, so it is attached to the DOM later, but your addEventListener call already occurred in the past.
You should use event delegation to handle the event.
document.addEventListener("click", function(e){
const target = e.target.closest("#btnPrepend"); // Or any other selector.
if(target){
// Do something with `target`.
}
});
closest ensures that the click occurred anywhere inside the target element or is the target element itself.
This is useful if, for example, instead of your <input id="btnPrepend"/> you had a <button id="btnPrepend"><i class="icon">+</i> prepend</button> and you clicked the <i class="icon">+</i>.
jQuery makes it easier:
$(document).on("click", "#btnPrepend", function(){
// Do something with `$(this)`.
});
Here is an article about event delegation.
There is a workaround by capturing clicks on document.body and then checking event target.
document.body.addEventListener( 'click', function ( event ) {
if( event.target.id == 'btnSubmit' ) {
someFunc();
};
} );
The difference is in how you create and append elements in the DOM.
If you create an element via document.createElement, add an event listener, and append it to the DOM. Your events will fire.
If you create an element as a string like this: html += "<li>test</li>"`, the elment is technically just a string. Strings cannot have event listeners.
One solution is to create each element with document.createElement and then add those to a DOM element directly.
// Sample
let li = document.createElement('li')
document.querySelector('ul').appendChild(li)
You must attach the event after insert elements, like that you don't attach a global event on your document but a specific event on the inserted elements.
e.g.
document.getElementById('form').addEventListener('submit', function(e) {
e.preventDefault();
var name = document.getElementById('txtName').value;
var idElement = 'btnPrepend';
var html = `
<ul>
<li>${name}</li>
</ul>
<input type="button" value="prepend" id="${idElement}" />
`;
/* Insert the html into your DOM */
insertHTML('form', html);
/* Add an event listener after insert html */
addEvent(idElement);
});
const insertHTML = (tag = 'form', html, position = 'afterend', index = 0) => {
document.getElementsByTagName(tag)[index].insertAdjacentHTML(position, html);
}
const addEvent = (id, event = 'click') => {
document.getElementById(id).addEventListener(event, function() {
insertHTML('ul', '<li>Prepending data</li>', 'afterbegin')
});
}
<form id="form">
<div>
<label for="txtName">Name</label>
<input id="txtName" name="txtName" type="text" />
</div>
<input type="submit" value="submit" />
</form>
Here's a reusable function that takes advantage of element.matches:
function delegate_event(event_type, ancestor_element, target_element_selector, listener_function)
{
ancestor_element.addEventListener(event_type, function(event)
{
if (event.target && event.target.matches && event.target.matches(target_element_selector))
{
(listener_function)(event);
}
});
}
Here's how you would use it for a click event:
delegate_event('click', document, '.alert-button', your_function_here);
You can do something similar to this:
// Get the parent to attatch the element into
var parent = document.getElementsByTagName("ul")[0];
// Create element with random id
var element = document.createElement("li");
element.id = "li-"+Math.floor(Math.random()*9999);
// Add event listener
element.addEventListener("click", EVENT_FN);
// Add to parent
parent.appendChild(element);
I have created a small library to help with this: Library source on GitHub
<script src="dynamicListener.min.js"></script>
<script>
// Any `li` or element with class `.myClass` will trigger the callback,
// even elements created dynamically after the event listener was created.
addDynamicEventListener(document.body, 'click', '.myClass, li', function (e) {
console.log('Clicked', e.target.innerText);
});
</script>
The functionality is similar to jQuery.on().
The library uses the Element.matches() method to test the target element against the given selector. When an event is triggered the callback is only called if the target element matches the selector given.
var __ = function(){
this.context = [];
var self = this;
this.selector = function( _elem, _sel ){
return _elem.querySelectorAll( _sel );
}
this.on = function( _event, _element, _function ){
this.context = self.selector( document, _element );
document.addEventListener( _event, function(e){
var elem = e.target;
while ( elem != null ) {
if( "#"+elem.id == _element || self.isClass( elem, _element ) || self.elemEqal( elem ) ){
_function( e, elem );
}
elem = elem.parentElement;
}
}, false );
};
this.isClass = function( _elem, _class ){
var names = _elem.className.trim().split(" ");
for( this.it = 0; this.it < names.length; this.it++ ){
names[this.it] = "."+names[this.it];
}
return names.indexOf( _class ) != -1 ? true : false;
};
this.elemEqal = function( _elem ){
var flg = false;
for( this.it = 0; this.it < this.context.length; this.it++ ){
if( this.context[this.it] === _elem && !flg ){
flg = true;
}
}
return flg;
};
}
function _( _sel_string ){
var new_selc = new __( _sel_string );
return new_selc;
}
Now you can register event like,
_( document ).on( "click", "#brnPrepend", function( _event, _element ){
console.log( _event );
console.log( _element );
// Todo
});
Browser Support
chrome - 4.0, Edge - 9.0, Firefox - 3.5 Safari - 3.2, Opera - 10.0 and above
Here's another solution I came up with. I found this much easier to deal with compared to event targets as they do not fire if a child is clicked. The method is to set event listeners and reset them after appending new elements to the document:
function listen() {
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener("click", function(){
console.log("Hello World");
});
});
}
listen();
document.body.innerHTML += "<p class='btn'>Click Here 2.0 .</p>";
listen();
<!DOCTYPE html>
<html>
<body>
<p class='btn'>Click Here.</p>
</body>
</html>
Edit:
To avoid stacked listeners of same event see this: Answer
I have found the solution posted by jillykate works, but only if the target element is the most nested. If this is not the case, this can be rectified by iterating over the parents, i.e.
function on_window_click(event)
{
let e = event.target;
while (e !== null)
{
// --- Handle clicks here, e.g. ---
if (e.getAttribute(`data-say_hello`))
{
console.log("Hello, world!");
}
e = e.parentElement;
}
}
window.addEventListener("click", on_window_click);
Also note we can handle events by any attribute, or attach our listener at any level. The code above uses a custom attribute and window. I doubt there is any pragmatic difference between the various methods.
I know that the topic is too old but I gave myself some minutes to create a very useful code that works fine and very easy using pure JAVASCRIPT.
Here is the code with a simple example:
String.prototype.addEventListener=function(eventHandler, functionToDo){
let selector=this;
document.body.addEventListener(eventHandler, function(e){
e=(e||window.event);
e.preventDefault();
const path=e.path;
path.forEach(function(elem){
const selectorsArray=document.querySelectorAll(selector);
selectorsArray.forEach(function(slt){
if(slt==elem){
if(typeof functionToDo=="function") functionToDo(el=slt, e=e);
}
});
});
});
}
// And here is how we can use it actually !
"input[type='number']".addEventListener("click", function(element, e){
console.log( e ); // Console log the value of the current number input
});
<input type="number" value="25">
<br>
<input type="number" value="15">
<br><br>
<button onclick="addDynamicInput()">Add a Dynamic Input</button>
<script type="text/javascript">
function addDynamicInput(){
const inpt=document.createElement("input");
inpt.type="number";
inpt.value=Math.floor(Math.random()*30+1);
document.body.prepend(inpt);
}
</script>
I've made a simple function for this.
The _case function allows you to not only get the target, but also get the parent element where you bind the event on.
The callback function returns the event which holds the target (evt.target) and the parent element matching the selector (this). Here you can do the stuff you need after the element is clicked.
I've not yet decided which is better, the if-else or the switch
var _case = function(evt, selector, cb) {
var _this = evt.target.closest(selector);
if (_this && _this.nodeType) {
cb.call(_this, evt);
return true;
} else { return false; }
}
document.getElementById('ifelse').addEventListener('click', function(evt) {
if (_case(evt, '.parent1', function(evt) {
console.log('1: ', this, evt.target);
})) return false;
if (_case(evt, '.parent2', function(evt) {
console.log('2: ', this, evt.target);
})) return false;
console.log('ifelse: ', this);
})
document.getElementById('switch').addEventListener('click', function(evt) {
switch (true) {
case _case(evt, '.parent3', function(evt) {
console.log('3: ', this, evt.target);
}): break;
case _case(evt, '.parent4', function(evt) {
console.log('4: ', this, evt.target);
}): break;
default:
console.log('switch: ', this);
break;
}
})
#ifelse {
background: red;
height: 100px;
}
#switch {
background: yellow;
height: 100px;
}
<div id="ifelse">
<div class="parent1">
<div class="child1">Click me 1!</div>
</div>
<div class="parent2">
<div class="child2">Click me 2!</div>
</div>
</div>
<div id="switch">
<div class="parent3">
<div class="child3">Click me 3!</div>
</div>
<div class="parent4">
<div class="child4">Click me 4!</div>
</div>
</div>
Hope it helps!
First of all add the dynamic class to the dynamically created inputboxes
var ele = document.createElement('textarea');
ele.className = "css-class-name"; // set the CSS class
ele.setAttribute('type', 'textarea');
ele.setAttribute('value', '');
ele.setAttribute("id", `row${rcount}_${c}`);
then do the following
const btns = document.querySelectorAll('.css-class-name');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('keyup', function (e) {
console.log(e.target.id);
let textValues = $(`#${e.target.id}`).val()
console.log("=============values =====", textValues)
//on key press take id and set value of that id what i am inputting.
});
}
I like #Pikamander2 solution because it does not involve an event binding on document, or body (you will wake up someday with each click on document triggering dozens of event handlers...).
Here is an improvement of Pikamander2 solution.
If the dynamically added child is itself a dom element with children (ex: <button><u>label</u></button>, the e.target may return the <u> element. So you may use :
function delegateEvent( eventType, ancestorElem, childSelector, eventHandler ) {
// Cancel if ancestorElem does not exists
if( ! ancestorElem || ( typeof ancestorElem === 'string' && ! ( ancestorElem = document.querySelector( ancestorElem ) ) ) ) {
return
}
ancestorElem.addEventListener( eventType, e => {
if( e.target && e.target.closest && e.target.closest( childSelector ) ) {
( eventHandler )( e )
}
} )
}
I also added a snippet to make the function accept a selector for ancestor instead of an element only
This is an old question - but I spent a lot of hours with this problem. Maybe my solution helps someone.
Context: Attaching event listeners to elements dynamically created from an Ajax response. Making an selectable by click, or by keyboard navigation: In both cases, the same function is called.
The first line worked, the second line did not allow me to click on the item:
item.addEventListener("mouseover", this.mouseOver.bind(this) )
item.addEventListener("click", this.clickedItem.bind(this) )
However, this continued to work:
item.click();
(Suggesting the click event was added, and calling the function - but the mouse was not dispatching a click event)
The solution was to change :
item.addEventListener("click", this.clickedItem.bind(this) )
to this:
item.addEventListener("mousedown", this.clickedItem.bind(this) )
I saw on old SO message that suggested that <div>s do not respond to mouse click events - but all the documentation I read contradicted that.
So, I don't know what's going on here.
I've made an editable implementation which behaviour is:
dblclick on element makes it editable:
an input is created
element contents emptied
input appended to element
attach keydown event handler to input, to disable edition when user presses Enter
idem with blur event
It works fine in decents browsers, but it breaks on IE8.
there are two problems:
input.focus() will call the blur event handler (wtf??)
keystrokes won't generate events intercepted by keydown handler, so my handler to validate when enter is hit don't work
I checked clicks events on the input and they are fine
The thing is it still works if I run the sample in a minimalist sample, but in my application, it won't.
what could prevent those keydown events from being fired / catch ?
here's the implementation:
widget.Editable = function( el, options ) {
this.element = $(el).addClass('editable');
this.value = this.element.text();
var _that = this;
this.element.dblclick( function(e) {
_that.enableEdition();
} );
};
widget.Editable.prototype = {
disableEdition: function( save, e ) {
this.value = this.input.val();
this.input.remove();
this.element.text( this.value ).removeClass('dragDisable');
this.editionEnabled = false;
this.onupdate( e, this.value, this.element );
},
/**
* enables the field for edition. Its contents will be placed in an input. Then
* a hit on "enter" key will save the field.
* #method enableEdition
*/
enableEdition: function() {
if (this.editionEnabled) return;
var _that = this;
this.value = this.element.text();
this.input = $( document.createElement('input') ).attr({
type:'text',
value:this.value
});
this.element
.empty().append( this.input )
.addClass('dragDisable'); //We must disable drag in order to not prevent selection
this.input.keydown( function(e) {
IScope.log('keydown editable:', e );
switch ( e.keyCode ) {
case 13:
_that.disableEdition( true );
break;
default:
break;
}
} );
this.input.click( function() {
console.log('input clicked');
});
//if ( !YAHOO.env.ua.ie )
// this.input.blur( function( e ) {
// IScope.log( "editable blurred", e );
// _that.disableEdition( true );
// });
//this.input.focus();
this.editionEnabled = true;
}
};
I have a canvas which listens for mouse down event... but I wanted to make it more detailed by listening on the buttons and if they were double clicks or not.
I have this:
canvas.addEventListener("mousedown", what_button, false);
Then a function named what_button:
function what_button(e){
//check which button on the mouse
//was it a double click ?
}
Is this possible in JavaScript?
I don't think that the 'mousedown' event is able to anticipate whether or not a second mouse click will occur. You'll have to bind to both 'click' and 'dblclick' and then override the behavior if a double-click occurred...
Inside the handler, the e.button property tells you which button was clicked:
0 => left
1 => middle
2 => right
This works for me:
var dblclick;
var timeout;
$( document ).on( 'click', function ( e ) {
if ( !timeout ) {
timeout = setTimeout( function () {
timeout = 0;
handler( dblclick ? 'dblclick' : 'click' );
dblclick = false;
}, 200 );
}
});
$( document ).on( 'dblclick', function ( e ) {
dblclick = true;
});
// this function receives either 'click' or 'dblclick'
// and performs the corresponding action
function handler ( type ) {
alert( type );
}
Live demo: http://jsfiddle.net/f73tY/1/
I use a delay value of 200. I have found that (at least on my machine) a value of 100 does not detect a double-click.
Use click/dblclick:
var button = document.getElementById('myButton');
button.ondblclick = function() {
doubleClick = true;
};
You can even add an normalClick = false then use that information in your code.
have dumb question.
Here I've got three events calling the same function, connected to the same <div>:
<html>
<head>
<script type='text/javascript'>
function universal_action_handler( event ) {
var eType = event.type;
var eTarget = event.target || event.srcElement;
console.log( "Captured Event, type=", eType, ", target=", eTarget );
if( 'mouseover' == eType ) {
console.info( "onMouseOver: set background color to red." );
eTarget.style.backgroundColor = 'red';
eTarget.style.fontSize = '';
}
if( 'mouseout' == eType ) {
console.info( "onMouseOut: set background color to transparent." );
eTarget.style.backgroundColor = 'transparent';
eTarget.style.fontSize = '';
}
if( 'click' == eType ) {
console.info( "click!" );
eTarget.style.fontSize = 'larger';
}
}
</script>
</head>
<body>
<div style='border: 1px dashed red; display: inline-block;'
onClick="universal_action_handler(event);"
onMouseOver="universal_action_handler(event);"
onMouseOut="universal_action_handler(event);">Click me!</div>
</body>
</html>
I have onClick='', onMouseOver='', and onMouseOut='', all connected to the same <div>, and all calling the same function. If I want to add an event, I have to add an onEventThingy='' and call the same universal action handler function above. Inside the function, it decides what kind of event (event.type) and takes action.
Is there an onAnything='' event that I can use to call the universal function for any event which may happen to that <div>?
Instead of all those onevent attributes (which should be avoided anyway), you could set the onevent properties on the DOM element like so:
div.onclick = div.onmouseover = div.onmouseout = universal_action_handler;
where div is a reference to your DIV element.
Btw this is how I would implement the handler:
function universal_action_handler ( e ) {
var target, style;
e = e || window.event;
target = e.target || e.srcElement;
style = target.style;
if ( e.type === 'click' ) {
style.fontSize = 'larger';
} else {
style.backgroundColor = e.type === 'mouseover' ? 'red' : 'transparent';
style.fontSize = '';
}
}
Live demo: http://jsfiddle.net/rPVUW/
No, there is no universal event.
You can try what Šime Vidas suggested, or some libraries (e.g., jQuery) allow you to bind multiple events to the same handler with a single line of code, but either way you do need to explicitly list out the events to be bound.
No, there's no way to attach the same handler to all possible events. Is that really what you want? This could lead to your handler containing a huge if..else block or big switch statement.
If you want to attach common functionality (logging in your example) to all event handlers, consider this JavaScript:
function logAndHandle(event, innerHandler) {
var eType = event.type;
var eTarget = event.target || event.srcElement;
console.log( "Captured Event, type=", eType, ", target=", eTarget );
return innerHandler(event);
}
Which you'd use like this:
<div onclick="logAndHandle(event, yourClickHandler);"
onmouseover="logAndHandle(event, yourMouseOverHandler);"
onmouseout="logAndHandle(event, yourMouseOutHandler)">Click me!</div>
Given that you seem to want some functionality to run for all events, and other functionality to be specific to particular events, I'd combine Jacob's answer with Šime Vidas's:
var log = function(innerHandler) {
return function(event){
var eType = event.type;
var eTarget = event.target || event.srcElement;
console.log( "Captured Event, type=", eType, ", target=", eTarget );
return innerHandler(event);
};
};
And use it thus:
div.onclick = log(yourClickHandler);
div.onmouseover = log(yourMouseOverHandler);
div.onmouseout = log(yourMouseOutHandler);
Currying the log function makes it very easy to compose future "all event" functionality:
var count = function(innerHandler){
var totalCount = 0;
return function(event){
totalCount += 1;
alert("I've been called " + totalCount + " times.");
return innerHandler(event);
};
};
div.onclick = count(log(yourClickHandler));
Anyway, if you want to do functional-style programming in Javascript, you'd also want to look at Function.apply and Function.call.
Using just javascript, no, there is no 'onAnything' attribute. If you have the ability to add jQuery, you can 'bind' multiple events to the same div and then run the same function.
Is there a way to programmatically trigger the onmouseover event in plain JavaScript? or "extract" the method from the onmouseover event to call it directly?
eg
<div id="bottom-div" onmouseover="myFunction('some param specific to bottom-div');">
<div id="top-div" onmouseover="????????"></div>
</div>
top-div is above bottom-div, so the onmouseover won't get fired in bottom-div. i need a way of calling myFunction('some param specific to bottom-div'); from top-div
const mouseoverEvent = new Event('mouseover');
whateverElement.dispatchEvent(mouseoverEvent);
This worked for me in IE9 at least. Should be cross-browser compatible or close to it...
function FireEvent( ElementId, EventName )
{
if( document.getElementById(ElementId) != null )
{
if( document.getElementById( ElementId ).fireEvent )
{
document.getElementById( ElementId ).fireEvent( 'on' + EventName );
}
else
{
var evObj = document.createEvent( 'Events' );
evObj.initEvent( EventName, true, false );
document.getElementById( ElementId ).dispatchEvent( evObj );
}
}
}
For onmouseover example, call the function like this
FireEvent( ElementId, "mouseover" );
For me following worked:
document.getElementById('xyz').dispatchEvent(new MouseEvent('mouseover', { 'bubbles': true }));
Also:
document.getElementById('xyz').dispatchEvent(new MouseEvent('mouseover', { 'view': window, 'bubbles': true, 'cancelable': true }));
Without going into too much detail, I had an img with rollovers, i.e. mouseout/overs that set the img src to hidden form values (or this could have done in a different context with gloabl variables). I used some javascript to swap both of my over/out image values and I called the called FireEvent( ElementId, "mouseover" ); to trigger the change. My javascript was hiding / displaying elements on the page. This caused the cursor to sometimes be over the img I used to trigger the event - which was the same as the one I was swapping out, and sometimes the cursor was not over the img after the click.
Mouseover/out does not fire unless you exit and re-enter an element, so after my event was triggered the mouseover/out needed "retriggering" to account for the new cursor position. Here is my solution. After I hide / display various page elements, and to do my img src swapping as described, I call the function RefreshMouseEvents( ElementId ) instead of FireEvent( ElementId, "mouseover" ).
This works in IE9 (not sure about other browsers).
function RefreshMouseEvents( ElementId )
{
FireEvent( ElementId, 'mouseover' );
setTimeout( "TriggerMouseEvent( '" + ElementId + "' )" , 1 );
}
function TriggerMouseEvent( ElementId )
{
if( IsMouseOver( ElementId, event.clientX, event.clientY ) )
FireEvent( ElementId, 'mouseover' );
else
FireEvent( ElementId, 'mouseout' );
}
function IsMouseOver( ElementId, MouseXPos, MouseYPos )
{
if( document.getElementById(ElementId) != null )
{
var Element = document.getElementById(ElementId);
var Left = Element.getBoundingClientRect().left,
Top = Element.getBoundingClientRect().top,
Right = Element.getBoundingClientRect().right,
Bottom = Element.getBoundingClientRect().bottom;
return ( (MouseXPos >= Left) && (MouseXPos <= Right) && (MouseYPos >= Top) && (MouseYPos <= Bottom))
}
else
return false;
}
function FireEvent( ElementId, EventName )
{
if( document.getElementById(ElementId) != null )
{
if( document.getElementById( ElementId ).fireEvent )
{
document.getElementById( ElementId ).fireEvent( 'on' + EventName );
}
else
{
var evObj = document.createEvent( 'Events' );
evObj.initEvent( EventName, true, false );
document.getElementById( ElementId ).dispatchEvent( evObj );
}
}
}
I had to revise my RefreshMouseEvents set of functions after more testing. Here is the seemingly perfected version (again only IE9 tested):
function RefreshMouseEvents( ElementId )
{
FireEvent( ElementId, 'mouseover' );
setTimeout( "TriggerMouseEvent( '" + ElementId + "', '" + event.clientX + "', '" + event.clientY + "' )", 1 );
}
function TriggerMouseEvent( ElementId, MouseXPos, MouseYPos )
{
if( IsMouseOver( ElementId, (1*MouseXPos), (1*MouseYPos) ) )
FireEvent( ElementId, 'mouseover' );
else
FireEvent( ElementId, 'mouseout' );
}
function IsMouseOver( ElementId, MouseXPos, MouseYPos )
{
if( document.getElementById(ElementId) != null )
{
var Element = document.getElementById(ElementId);
var Left = Element.getBoundingClientRect().left,
Top = Element.getBoundingClientRect().top,
Right = Element.getBoundingClientRect().right,
Bottom = Element.getBoundingClientRect().bottom;
return ( (MouseXPos >= Left) && (MouseXPos <= Right) && (MouseYPos >= Top) && (MouseYPos <= Bottom))
}
else
return false;
}
function FireEvent( ElementId, EventName )
{
if( document.getElementById(ElementId) != null )
{
if( document.getElementById( ElementId ).fireEvent )
{
document.getElementById( ElementId ).fireEvent( 'on' + EventName );
}
else
{
var evObj = document.createEvent( 'Events' );
evObj.initEvent( EventName, true, false );
document.getElementById( ElementId ).dispatchEvent( evObj );
}
}
}
I needed to do something similar, but I'm using jQuery, and I found this to be a better solution:
Use jQuery's trigger function.
$j('#top-div' ).trigger( 'mouseenter' );
You can also add parameters to it if you need to. See the jQuery documentation on .trigger.
<a href="index.html" onmouseover="javascript:alert(0);" id="help">help</a>
document.getElementById('help').onmouseover();
I was working with Angular and trying to do a similar thing.
I fall on this answer from StackOverflow Click here
Basically the idea is to add and remove the hover class
public addHoverOnClick() {
const yourElement = document.getElementById('elementID') as HTMLElement;
yourElement .classList.add('hover')
}
public removeHoverOnClick() {
const yourElement = document.getElementById('elementID') as HTMLElement;
yourElement .classList.remove('hover')
}
You would do it something like this:
document.getElementById('top-div').onmouseover();
However, as mentioned in the comments, it would be worth testing before being considered an issue.