4

我正在尝试修改行为或 JavaScript 库,基本上是通过对其进行修补(不,没有更好的方法)。

在代码中的某个点,我需要知道是否按下了 Shift。如果此库中的事件处理程序编写正确,它将接收“事件”作为其第一个参数,但不幸的是,它不是(事件与 HTML 中的 onclick 内联连接)

所以,我想看看 jQuery 是否在某处“存储”了最后一个事件对象,或者是否有其他方法可以访问它。

本质上,我想要的是“window.event”,但理想情况下我希望它可以在 Firefox 上运行。

除了向文档添加全局 onKeyDown 处理程序并自己跟踪 Shift 的状态之外,还有什么想法吗?对于我的口味来说,这感觉有点矫枉过正,而且有点过于全球化。

4

3 回答 3

2

正如我在评论中提到的,可以使 window.event 存在于非 IE 浏览器中。它要求您包装 attachEvent/addEventListener。它会是这样的:

var oldAddEventListener = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function(type, listener, useCapture) {
    var wrapped = function(event) {
        window.event = event;

        listener(arguments);
    }

    oldAddEventListener.call(this, type, wrapped , useCapture);
}

正如我所说,我不确定这是否适用于内联事件侦听器,但它可能 :) 如果不是,至少它在这里作为那些寻找类似东西的人的参考。

于 2012-07-20T20:50:22.317 回答
2

你能包装他们使用的函数作为他们的事件处理程序吗?举这个人为的例子:

var someObject = {
    keyDownListener: function() {
        alert('something was pressed!');
    }
}

我们可以用我们自己的接受事件对象的方法替换 keyDownListener。

var someObject = {
    keyDownListener: function() {
        alert('something was pressed!');
    }
}

var oldKeyDownListener = someObject.keyDownListener;
someObject.keyDownListener = function(event) {
    oldKeyDownListener(); // Call the original
    // Do anything we need to do here (or before we call the old one!)
}

如果你能进入函数内部,你也可以检查 arguments 对象。您的事件对象应该在那里(我相信第一项)。

var f = function() {
    console.log(arguments);    
}

f(); //= Logs []
f(1); //= Logs [1]
f(1, 'something'); //= Logs [1, 'something']

编辑(回应下面的评论)。

如果您可以“劫持”该方法,那么这是您可以做到的一种方法。我不确定这是否是一个好方法,但如果你有所有这些限制,它会让你得到你想要的。基本上,这段代码的作用是搜索任何具有 onclick 属性的元素,并更改方法签名以包含事件对象。

然后我们可以包装原始侦听器以从参数中提取事件对象,然后将执行传递回原始函数。

这样做会让你得到你想要的(我想?)。请参阅此代码:

HTML:

<a href="#" onclick="javascript:myFunction(1, 2, 3);">Click Me</a>​

JavaScript:

window.myFunction = function(one, two, three) {
    console.log("one: " + one + ", two: " + two + ", three: " + three);
}

var originalMyFunction = window.myFunction;
window.myFunction = function() {
    var event = arguments[arguments.length - 1]; // The last item in the arguments array is our event object.
    console.log(event);        
    originalMyFunction.apply(this, arguments);
}

$('[onclick]').each(function() {
    var s = $(this).attr('onclick');
    var lastIndex = s.lastIndexOf(')');

    var s2 = s.substring(0, lastIndex);
    var s3 = s.substring(lastIndex, s.length);

    var s4 = s2 + ', event' + s3;

    $(this).attr('onclick', s4);
});

你可以看到它在这个小提琴中工作:http: //jsfiddle.net/84KvV/

编辑 2

如果你想真正喜欢它,你甚至可以自动包装函数。看到这个小提琴:http: //jsfiddle.net/84KvV/2/

请注意,这期望函数字符串采用某种格式,以便它可以解析它(functionName(...))。如果不是那种格式,那么这个确切的代码将不起作用:)

于 2012-07-20T20:07:44.877 回答
0
function eventlessHandler(myVal) {
    var event = window.event || eventlessHandler.caller.arguments[0];
    // some work
}    

根据实际调用链,可能需要遍历.caller多次。

在 IE6、IE11 和最新的 Chrome 上对此进行了测试。也应该适用于大多数其他浏览器。

另请参阅如何在 JavaScript 中找出调用者函数?.

于 2019-04-11T17:22:02.763 回答