2014-01-07 73 views
0

我想添加一個使用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"); 
     } 

唯一的問題是,「結束」事件被觸發不是每次一遍,一首歌結束。在「結束」事件之後,該功能被執行,然後再次執行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建議的那樣觸發函數來移除事件監聽器。

+0

仔細檢查所有基本情況。由於有些情況下,您可以在歌曲播放器內部應用的監聽器中調用歌曲播放功能,因爲您點擊時會有一個循環結構,它將繼續應用新的監聽器。 – Fallenreaper

+0

@Fallenreaper - 但我想每次都應用一個新的監聽器,那麼爲什麼不在監聽器函數中再次調用該函數呢? – Manolo

+0

您可能想要刪除先前的偵聽器和REAPPLY,而不是追加新的偵聽器。問題在於你點擊並且事件觸發一次,然後再次點擊它會觸發兩次,再次點擊,觸發4次等。如果你想申請一個新的偵聽器,你可以,但是我會相應地通知你。你會想要覆蓋原來的。這樣做和$(「item」)一樣簡單。off(「functionName」);在jQuery中。 – Fallenreaper

回答

1

你把一個監聽器裏面的歌曲稱爲另一個時間......並在另一個時間和另一個時間使用它。

遞歸。

>_> 
相關問題