为什么事件不止一次被触发?

时间:2014-01-07 19:41:52

标签: javascript jquery soundmanager2

我正在尝试使用SoundManager2为音频Javascript插件添加事件处理程序。这是播放歌曲并等待歌曲结束再次执行该功能的功能:

    function songPlay (newSrc) {

            htmlSound.src = newSrc;
            htmlSound.load();

            thisPlayer.find( ".total-position-scrubber" ).bind( "slide", function(event, ui) {
                htmlSound.currentTime = ui.value;
            });

            var currentArtist = currentRow.find(".total-artist").text();
            var currentTitle =  currentRow.find(".total-title").text();

            thisPlayer.find(".total-playing-artist").html(currentArtist);
            thisPlayer.find(".total-playing-title").html(currentTitle);

            htmlSound.addEventListener("timeupdate", function() {
                var newVolume = thisPlayer.find( ".total-volume-slider" ).slider("option", "value");
                htmlSound.volume = newVolume;

                var duration = htmlSound.duration * 1000;
                var durationTime = convertMilliseconds(duration, "mm:ss");
                thisPlayer.find(".total-song-duration").html(durationTime.clock );

                var position = htmlSound.currentTime * 1000;
                var positionTime = convertMilliseconds(position, "mm:ss");
                thisPlayer.find(".total-song-position").html(positionTime.clock );

                thisPlayer.find( ".total-position-scrubber" ).slider("option", "max", duration/1000);
                thisPlayer.find( ".total-position-scrubber" ).slider("option", "value", position/1000);

            });

            htmlSound.addEventListener("ended", function() {

                        // Find next checked song

                        currentRow = currentRow.nextAll(".can-play:first");

                        // If checked song exists after current song, load it
                        if(currentRow.length > 0)
                        {
                            var newSrc = currentRow.find("[src]").attr("src");
                            songPlay(newSrc);
                        }

                        else
                        {
                            // If no checked song exists after current song, load the first checked song in playlist
                            if(thisPlayer.find(".can-play").length > 0)
                            {
                                currentRow = thisPlayer.find(".can-play:first");
                                var newSrc = currentRow.find("[src]").attr("src");
                                songPlay(newSrc);
                            }
                            // Change pause button to play button
                            else
                            {
                                thisPlayer.find(".total-play").removeClass("total-pause");  
                            }

                        }
                        // If song is playing while next button is clicked play next song
                        if(thisPlayer.find(".total-pause").length > 0)
                        {
                            htmlSound.play();

                        }

            });

            thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
            currentRow.find(".total-not-playing").addClass("total-playing");
        }

唯一的问题是"结束"每次歌曲结束时,事件会被触发多次。在"结束后#34; event,执行函数,然后再次执行songPlay()函数(这是预期的行为),然后,"结束"在歌曲结束之前,事件再次被触发,而它应该等待歌曲的结束。知道这种行为的原因吗?

newSrc变量始终是正确的值。

这是"结束" SoundManager2中的事件定义:

_html5_events = {

  // HTML5 event-name-to-handler map
  ...
  ended: _html5_event(function() {

  var t = this._t;

  _s._wD(_h5+'ended: '+t.sID);
  t._onfinish();

 }),
 ...
}

修改

令人惊讶的是,它只是用声明的函数替换匿名函数,如下所示:

function eventListenerFunction() {

        // Find next checked song

        currentRow = currentRow.nextAll(".can-play:first");

        // If checked song exists after current song, load it
        if(currentRow.length > 0)
        {
            var newSrc = currentRow.find("[src]").attr("src");
            songPlay(newSrc);
        }

        else
        {
            // If no checked song exists after current song, load the first checked song in playlist
            if(thisPlayer.find(".can-play").length > 0)
            {
                currentRow = thisPlayer.find(".can-play:first");
                var newSrc = currentRow.find("[src]").attr("src");
                songPlay(newSrc);
            }
            // Change pause button to play button
            else
            {
                    thisPlayer.find(".total-play").removeClass("total-pause");  
            }

        }
        // If song is playing while next button is clicked play next song
        if(thisPlayer.find(".total-pause").length > 0)
        {
            htmlSound.play();

        }

});

function songPlay (newSrc) {

    htmlSound.src = newSrc;
    htmlSound.load();

    thisPlayer.find( ".total-position-scrubber" ).bind( "slide", function(event, ui) {
        htmlSound.currentTime = ui.value;
    });

    var currentArtist = currentRow.find(".total-artist").text();
    var currentTitle =  currentRow.find(".total-title").text();

    thisPlayer.find(".total-playing-artist").html(currentArtist);
    thisPlayer.find(".total-playing-title").html(currentTitle);

    htmlSound.addEventListener("timeupdate", function() {
        var newVolume = thisPlayer.find( ".total-volume-slider" ).slider("option", "value");
        htmlSound.volume = newVolume;

        var duration = htmlSound.duration * 1000;
        var durationTime = convertMilliseconds(duration, "mm:ss");
            thisPlayer.find(".total-song-duration").html(durationTime.clock );

        var position = htmlSound.currentTime * 1000;
        var positionTime = convertMilliseconds(position, "mm:ss");
        thisPlayer.find(".total-song-position").html(positionTime.clock );

        thisPlayer.find( ".total-position-scrubber" ).slider("option", "max", duration/1000);
        thisPlayer.find( ".total-position-scrubber" ).slider("option", "value", position/1000);

    });

    htmlSound.addEventListener("ended", eventListenerFunction)

    thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
    currentRow.find(".total-not-playing").addClass("total-playing");
}

但是,我想我应该在触发函数之后使用$('body').off("ended")删除事件监听器,正如@Fallenreaper建议的那样。

1 个答案:

答案 0 :(得分:1)

你在一个听众中调用歌曲,然后再将它应用于另一个时间....另一个时间和另一个时间。

递归。

>_>