修改querySelector以应用于所有页面元素(querySelectorAll)

时间:2018-12-15 10:19:02

标签: javascript

我正在尝试创建一个通用例程,该例程将在重定向到链接的指定href之前先播放声音。我正在尝试尽可能保持动态,以避免不得不手动将onclick事件添加到每个链接等。

从stackoverflow和其他地方的其他代码中,我已经设法找到了几乎所需的内容。

    document.querySelector('.playsound').onclick = function (evt) {
        evt = evt || window.event;

        playThenRedirectTo('sndButton', this.href);

        // prevent the link from being followed, until we want to later on
        if (evt.preventDefault) {
            evt.preventDefault();
        } else {
            evt.returnValue = false;
        }
    }

    function play_single_sound(target) {
        document.getElementById(target).play();
    }
    function newPage(url) {
        location.href = url;
    }
    function playThenRedirectTo(audioTarget, url) {
        var time = 0;

        play_single_sound(audioTarget);

        setInterval(function () {
            var end = document.getElementById(audioTarget).played.end(0);
            if (end > time) {
                time = end;
            } else {
                newPage(url);
            }
        }, 250);
    }

这适用于页面上的第一个元素。在重定向之前播放声音文件。但是我不确定如何使它适用于所有具有css类匹配playsound的元素,因为现在它仅适用于第一个。

我假设使用querySelectorAll,并且需要某种forEach,但是我不知道使用它的语法是什么。任何建议将不胜感激!

1 个答案:

答案 0 :(得分:1)

虽然您可以 使用querySelectorAll向页面上的每个<a>添加一个侦听器,但您可以考虑使用事件委托:添加一个单个单击文档的侦听器,然后单击某些内容,然后检查目标是否为a。如果是这样,请致电playThenRedirectTo

document.addEventListener('click', (e) => {
  if (!e.target.matches('a')) return;
  // if you only want `.playSound` `a`s to trigger this behavior, instead use
  // if (!e.target.matches('a.playSound')) return;

  playThenRedirectTo('sndButton', e.target.href);
  if (e.preventDefault) {
    e.preventDefault();
  } else {
    e.returnValue = false;
  }
});

querySelectorAll版本涉及使用forEach遍历所有元素,并将侦听器附加到每个元素:

Array.prototype.forEach.call(
  document.querySelectorAll('a.playsound'), // or whatever selector you want
  playsound => playsound.onclick = e => {
    playThenRedirectTo('sndButton', playsound.href);
    if (e.preventDefault) {
      e.preventDefault();
    } else {
      e.returnValue = false;
    }
  }
);

(尽管在较新的浏览器上,您可以直接在forEach返回的NodeListquerySelectorAll,例如call返回,为了使网站访问者能够可靠地工作,您需要使用polyfill ,即Array方法的In-Memory Cache