20

我正在尝试修改页面上的所有链接,以便在单击它们时执行一些额外的工作。

一个简单的方法可能是这样的:

function adaptLinks()
{
    var links = document.getElementsByTagName('a');
    for(i = 0; i != links.length; i++)
    {
        links[i].onclick = function (e)
        {
            <do some work>
            return true;
        }
    }
}

但是一些链接已经有一个应该保留的onClick处理程序。我尝试了以下方法:

function adaptLinks()
{
    var links = document.getElementsByTagName('a');
    for(i = 0; i != links.length; i++)
    {
        var oldOnClick = links[i].onclick;
        links[i].onclick = function (e)
        {
            if(oldOnClick != null && !oldOnClick())
            {
                return false;
            }
            <do some work>
            return true;
        }
    }
}

但这不起作用,因为oldOnClick仅在调用处理程序时评估(它包含最后一个链接的值作为这一点)。

4

7 回答 7

20

不要直接分配给事件处理程序:改用订阅模型addEventListener / attachEvent(它们也有删除对!)。

很好的介绍在这里

于 2009-05-21T09:18:00.483 回答
18

您需要创建一个闭包来保留onclick每个链接的原始值:

<a href="#" onclick="alert('hi');return false;">Hi</a>
<a href="#" onclick="alert('there');return true;">There</a>
<script type="text/javascript">
function adaptLinks() {
    var links = document.getElementsByTagName('a');
    for (i = 0; i != links.length; i++) {
        links[i].onclick = (function () {
            var origOnClick = links[i].onclick;
            return function (e) {
                if (origOnClick != null && !origOnClick()) {
                    return false;
                }
                // do new onclick handling only if
                // original onclick returns true
                alert('some work');
                return true;
            }
        })();
    }
}
adaptLinks();
</script>

请注意,如果原始 onclick 处理程序返回 true,则此实现仅执行新的 onclick 处理。如果这是您想要的,那很好,但请记住,如果您想执行新的 onclick 处理,即使原始处理程序返回 false,您也必须稍微修改代码。

comp.lang.javascript FAQDouglas Crockford中了解更多关于闭包的信息。

于 2009-05-21T16:39:32.777 回答
4

在addEventListener(支持浏览器的 DOM)或attachEvent (IE)周围使用包装器。

请注意,如果您想在变量中存储一个值而不覆盖旧值,您可以使用闭包

function chain(oldFunc, newFunc) {
  if (oldFunc) {
    return function() {
      oldFunc.call(this, arguments);
      newFunc.call(this, arguments);
    }
  } else {
    return newFunc;
  }
}

obj.method = chain(obj.method, newMethod);

面向方面的编程中,这被称为“建议”。

于 2009-05-21T09:18:18.330 回答
0

设置怎么样oldClick = links[i].onclick or an empty function。像这样

var oldOnClick = links[i].onclick || function() { return true; };

links[i].onclick = function (e)
   {
       if (!oldOnClick())
           return false;
       //<do some work>
       return true;
   }

或者你可以使用attachEventaddEventListener其他人推荐的

function addEvent(obj, type, fn) {
        if (obj.addEventListener)
                obj.addEventListener(type, fn, false);
        else if (obj.attachEvent)
                obj.attachEvent('on' + type, function() { return fn.apply(obj, [window.event]);});
}

并像这样使用

addEvent(links[i], 'click', [your function here]);
于 2009-05-21T09:19:28.873 回答
0

使用 JQuery,以下代码有效:

function adaptLinks(table, sortableTable)
{
    $('a[href]').click(function (e)
    {
        if(!e.isDefaultPrevented())
        {
            <do some work>
        }
    });
}

这需要使用额外的库,但可以避免 addEventListener/attachEvent 存在的一些问题(例如后者的this references问题)。

只有一个陷阱:如果原始的onClick处理程序是使用“普通”JavaScript 分配的,则该行

...
if(!e.isDefaultPrevented())
...

将始终解析为true,即使原始处理程序通过返回 false 取消了事件。要解决此问题,原始处理程序也必须使用 JQuery。

于 2009-05-21T11:14:52.213 回答
0

此功能应该可用(事件侦听器方法):

function addEventListener(element, eventType, eventHandler, useCapture) {
    if (element.addEventListener) {
        element.addEventListener(eventType, eventHandler, useCapture);
        return true;
    } else if (element.attachEvent) {
        return element.attachEvent('on' + eventType, eventHandler);
    }
    element['on' + eventType] = eventHandler;
}

或者您可以保存更多添加此函数的代码(如果您需要将相同的事件侦听器添加到许多元素):

function addClickListener(element) {
    addEventListener(element, 'click', clickHandler, false);
}
于 2009-08-06T19:27:46.627 回答
0

我在以简单的方式重载时遇到了问题 - 这个页面是一个很好的资源 http://www.quirksmode.org/js/events_advanced.html

于 2010-01-08T03:20:11.917 回答