2013-04-03 56 views
1

我在使用jQuery(我使用的是1.7.1版本)中的<audio>元素的timeupdate事件時遇到問題。我的目標是綁定一個函數,然後解除綁定,然後再綁定一次。它在Firefox,Google Chrome和Internet Explorer 10中表現的並不像我期望的那樣。Firefox和Google Chrome的表現相同,但Internet Explorer 10的行爲有所不同(令人驚訝!)。當然,我會喜歡它在所有三個方面工作。「timeupdate」事件函數重新綁定兩次後觸發

我認爲這個問題是代碼本身(問題的細節是在HTML的第二<p>)最好的描述:

HTML

<p>Click the circle on the right whose color matches the circle on the left. Do this four times.</p> 

<p>Clicking the incorrect color will play audio. As soon as the singing starts, a message is logged to the console. This works the first time, but after that, it starts happening twice.</p> 

<div class="goal"></div> 
<div class="choices"></div> 

<audio id="audio-try_again" preload="auto"> 
    <source src="try_again.ogg"> 
    <source src="try_again.mp3"> 
</audio> 

CSS

.goal, .choices { 
    float: left; 
    width: 50%; 
} 

JavaScript

$.randomize = function(arr) { 
    for (var j, x, i = arr.length; i; j = parseInt(Math.random() * i, 10), x = arr[--i], arr[i] = arr[j], arr[j] = x); 
    return arr; 
}; 

function factorial(num) { 
    var rval = 1; 

    for (var i = 2; i <= num; i++) { 
     rval = rval * i; 
    } 

    return rval; 
} 

function generate_objects() { 
    this_pair = get_object_pair(); 

    if (used_pairs.length < total_permutations) { 
     while ($.inArray(this_pair, used_pairs) > -1) { 
      this_pair = get_object_pair(); 
     } 
    } 
    else { 
     used_pairs = []; 
    } 

    used_pairs.push(this_pair); 

    objects = this_pair.split('|'); 

    object_to_find = objects[0]; 
    other_object = objects[1]; 

    $('.goal').html('<a href="javascript:void(0);"><img src="' + images[object_to_find] + '" alt=""></a>'); 
    $('.choices').html(''); 

    choices = [ 
     $('<a href="javascript:void(0);" class="correct"><img src="' + images[object_to_find] + '" alt=""></a>'), 
     $('<a href="javascript:void(0);" class="incorrect"><img src="' + images[other_object] + '" alt=""></a>') 
    ]; 

    $.randomize(choices); 

    $.each(choices, function(index, value) { 
     $('.choices').append(value); 
    }); 

    $('#audio-try_again').on('timeupdate', function() { 
     if (try_again_audio_element.currentTime >= 5) { 
      $(this).off('timeupdate'); 

      console.log('Highlight the correct image.'); 

      $('.correct').animate({opacity: 0.25}, 200, function() { 
       $(this).animate({opacity: 1}, 200, function() { 
        $('.correct').animate({opacity: 0.25}, 200, function() { 
         $(this).animate({opacity: 1}, 200); 
        }); 
       }); 
      }); 
     } 
    }); 

    $('.goal, .choices').fadeIn(); 
} 

function get_object_pair() { 
    object_to_find = other_object = get_random_index(); 

    while (other_object == object_to_find) { 
     other_object = get_random_index(); 
    } 

    return object_to_find + '|' + other_object; 
} 

function get_random_index() { 
    return Math.floor(Math.random() * total_images); 
} 

function question_answered() { 
    if (correct_answers == 4) { 
     alert('You have correctly answered four questions.'); 
    } 
    else { 
     $('.goal, .choices').fadeOut(function() { 
      $('#audio-try_again').off('timeupdate'); 

      setTimeout(generate_objects, 200); 
     }); 
    } 
} 

$(document).ready(function() { 
    correct_answers = 0; 

    images = [ 
     'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAcUlEQVR42qXT0QnAIAxFUUfJNJlOp+gwWUfIAOkTUpBAC/V9nI9KuKDV1iIqhQEGM1muaZ3fPwQ6OMQLzxmpAYGrDH+5QPZAh/ipPwEFPwg4aMvDiUNjBYwI2ApMIjDpAL0F+hDp30heJP4q84+Jfs43txnFT7FsW/cAAAAASUVORK5CYII=', 
     'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAcUlEQVR42qWT0QnAIAxEHSXTZDqdosNknYADpCekIJZW2kPeh3I8TIwl7ktBAwY8sTzTNT1vBFTQQTzQMyOrQMCRoS2ZlVlQQXykXgJ9u/amHC3ZnPhJGwIjBDYETgicFtAl0E2kn5EcJH6U+c9Ef+cTtijFT/BuGVoAAAAASUVORK5CYII=', 
     'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAcUlEQVR42qWT0QnAIAxEHSXTOF2dosNkHcEB0hMOwUAp9j7eh3J5YExKRMlU0ICDTpx3NWW3g4ELDBAvDGYsCwzcDH3CrC0BrXECa9abx6mANbWwOfGTNgUuCHwKuiDoskB+gtxE+RvFQdJHWV8meZ0ftTfFT731dloAAAAASUVORK5CYII=', 
     'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAa0lEQVR42qXT0QnAIAwE0IziNE6XTOEwWSeQAex9hFKKbaknvB+JB1Eji9XBwCGK116Xl9VAIWE+yKppq8PjLPw27iEK8ye99pwbAVlnxWBuMhAnAhwkiICgA+gW6Eukn5H8SPxX5oeJHucDimXHMWd8ov0AAAAASUVORK5CYII=' 
    ]; 

    total_images = images.length; 
    total_permutations = factorial(total_images)/factorial(total_images - 2); 

    try_again_audio_element = $('#audio-try_again')[0]; 

    $(document).on('click', '.correct', function() { 
     if (!$(this).hasClass('disabled')) { 
      $('.correct, .incorrect').addClass('disabled'); 

      correct_answers++; 
      question_answered(); 
     } 
    }).on('click', '.incorrect', function() { 
     if (!$(this).hasClass('disabled')) { 
      $('.correct, .incorrect').addClass('disabled'); 

      try_again_audio_element.play(); 
     } 
    }); 

    $('#audio-try_again').on('ended', function() { 
     question_answered(); 
    }); 

    used_pairs = []; 
    generate_objects(); 
}); 

演示:http://jsfiddle.net/j8LXE/

任何想法?

+0

你能否提供一些有關確切步驟的更多信息來重現此事件觸發兩次?從演示中看到你想如何工作並不是很清楚。 –

+0

@KevinEnnis對不起。當您進入演示時,打開您的瀏覽器控制檯(同樣,我感興趣的唯一瀏覽器是Firefox,Google Chrome和Internet Explorer 10),然後單擊右側的*顏色與*不匹配的顏色左邊。這會導致音頻播放。 5秒鐘進入音頻,* 1 *消息將出現在控制檯中。這就是我想要的。現在再做一次。這次,兩個*消息將出現在控制檯中。 – Nick

回答

2

貌似問題是這樣的塊:

$('.goal, .choices').fadeOut(function() { 
    $('#audio-try_again').off('timeupdate'); 
    setTimeout(generate_objects, 200); 
}); 

選擇器$('.goal, .choices')將返回包含兩個元素一個jQuery集合,這意味着callback函數被調用兩次(每一個匹配元素一次)。

一個快速和骯髒的方式來解決這個問題,爲特定應用程序,將是:

$('.goal, .choices').fadeOut(function() { 
    if ($(this).is('.goal')) return; 
    $('#audio-try_again').off('timeupdate'); 
    setTimeout(generate_objects, 200); 
}); 

這將本質上,只有執行的東西,裏面回調一次。

+0

啊,當然!這解決了它。我應該親眼看到這一點。我知道選擇器是這樣工作的;我錯過了它。感謝您爲我解決這個問題! – Nick