JavaScript中如何以编程方式触发onmouseover事件

65

在纯JavaScript中,有没有一种以编程方式触发onmouseover事件的方法?或者从onmouseover事件中“提取”该方法以直接调用它?

例如:

<div id="bottom-div" onmouseover="myFunction('some param specific to bottom-div');">
    <div id="top-div" onmouseover="????????"></div>
</div>

由于top-div在bottom-div上面,所以在bottom-div中不会触发onmouseover事件。我需要一种方法从top-div中调用myFunction('some param specific to bottom-div');


2
你试过这个吗?由于事件传播,onmouseover事件应该也会触发父级事件。 - Tatu Ulmanen
好的,我没有考虑到那一点,抱歉。这个例子有点不太恰当,因为在我的应用程序中它们实际上并不是嵌套元素。顶部的 div 元素是绝对定位在其他多个元素之上的。 - fearofawhackplanet
@Piskvor:我试图将一个非常复杂的HTML片段简化为一个简单的例子,但我犯了一个错误。如果这使你不满意,请原谅。 - fearofawhackplanet
2
@fearofawhackplanet:我为我的傲慢评论道歉,已删除。(事实部分:“元素重叠!=元素嵌套”) - Piskvor left the building
一行代码版本(在Chrome控制台中测试): element.dispatchEvent(e=(document.createEvent('Events')),e.initEvent("mouseenter", true, false),e) - Tom
@fearofawhackplanet 我通常不建议屈服于同侪压力,但这一次,我建议你考虑更改你对那个问题的接受答案。 - SteeveDroz
9个回答

85
const mouseoverEvent = new Event('mouseover');

whateverElement.dispatchEvent(mouseoverEvent);

4
滚动页面,希望能找到像这样的内容。 - ESR
7
有时鼠标悬停无效,但 mouseenter 可以。 const evt = new Event('mouseenter'); whateverElement.dispatchEvent(evt); - brianf
不错,这些是不同的活动。 - undefined
无法在手机上工作 - undefined

39

这至少对我在IE9上有效。应该是跨浏览器兼容的,或者非常接近。

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 );
        }
    }
}

例如,在onmouseover事件中,可以像这样调用该函数

FireEvent( ElementId, "mouseover" );

10
就此而言,“initEvent”已被弃用,根据MDNhttps://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent 不应依赖它。在上面的“else”块中可能的示例是:var event = new MouseEvent(EventName, { 'view': window, 'bubbles': true, 'cancelable': true }); document.getElementById(ElementId).dispatchEvent(event); - james
这是我在2021年在Chrome上工作的唯一解决方案 :) - Csa77
var evObj = document.createEvent('Events'); evObj.initEvent(EventName, true, false); document.getElementById(ElementId).dispatchEvent(evObj); 这个非常好用 :) - Mahmoud Aly

35

对我来说,以下方法起作用:

​document.getElementById('xyz').dispatchEvent(new MouseEvent('mouseover', { 'bubbles': true }));

此外:

​document.getElementById('xyz').dispatchEvent(new MouseEvent('mouseover', { 'view': window, 'bubbles': true, 'cancelable': true }));

7

不详细解释,我有一个带有rollovers的img,即鼠标移入/移出时将img src设置为隐藏表单值(或者在不同上下文中可以使用全局变量)。我使用了一些javascript来交换我的over/out image值,并调用了FireEvent(ElementId,“mouseover”)来触发更改。我的javascript正在隐藏/显示页面元素。这导致光标有时会悬停在我用于触发事件的img上 - 这与我要交换的光标相同,有时点击后光标不在img上。

除非您退出并重新进入元素,否则mouseover/out不会触发,因此在触发我的事件后,mouseover/out需要“重新触发”以考虑新的光标位置。这是我的解决方案。在隐藏/显示各种页面元素并执行我所描述的img src交换之后,我调用RefreshMouseEvents(ElementId)函数而不是FireEvent(ElementId,“mouseover”)。

此解决方案适用于IE9(不确定其他浏览器)。

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 );
        }
    }
}

2
不要使用setTimeout作为eval!相反,使用Function.prototype.bind - Jack G

7

经过更多测试,我不得不修订我的RefreshMouseEvents函数集。这里是看起来完美的版本(仅在IE9上测试):

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 );
        }
    }
}

3

我需要做类似的事情,但是我正在使用jQuery,并且我发现这是更好的解决方案:

使用jQuery的触发器函数。

$j('#top-div' ).trigger( 'mouseenter' );

如有需要,您还可以添加参数。请参阅jQuery .trigger相关文档


1
当有人对一个答案进行负评,又不给出任何理由时,我觉得很滑稽。所以,无论是谁给我的答案点了踩,请解释一下原因,这样我就可以学到新的东西了。我并不认为我的答案是最好的,但它确实在我这里起作用了。如果你发现了问题,请添加一条评论,以便我们知道原因,更好的做法是让我改进我的答案。 - thephatp
12
也许是因为原贴提到他们正在寻找一个“纯粹的 Javascript”解决方案? - bigsee

0
​<a href="index.html" onmouseover="javascript:alert(0);" id="help"​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​>help</a>​​​​​​​​​​​​​​​​​​​​​​​​​​​

​document.getElementById('help').onmouseover();​​​​​​​

0

我正在使用Angular并尝试做类似的事情。 我在StackOverflow上找到了这个答案点击这里 基本思路是添加和删除悬停类

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')
}

-30
你可以这样做:

document.getElementById('top-div').onmouseover();

然而,正如评论中所提到的,值得在被认为是问题之前进行测试。

我没想到它这么简单!我肯定以前尝试过使用onclick做类似的事情,但没有成功。也许我的记忆有误。 - fearofawhackplanet
3
我不确定这个曾经是否有效,但我认为至少应该去掉“on”前缀。 - Ja͢ck
21
不工作 未捕获的TypeError:e.previousElementSibling.onmouseover不是一个函数(…) - Green
4
@fearofawhackplanet 请考虑接受一个不同的答案。这个答案在大多数情况下是不适用的,并且不被鼓励使用——它仅在函数绑定到 onmouseover 属性时才有效,但是 addEventListener 是更优选的方法。这个答案不适用于标准 API,但是最得票的答案对任何方法都适用。 - Sebastian Simon
它所做的就是调用之前分配给“onmouseover”的函数(如果已经分配,否则将出现'Uncaught TypeError')。这就是为什么.mouseover()不起作用(除非你确实分配了一个函数)。但最终,你并没有触发悬停 - 你只是调用处理程序。 - Christian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接