我在jQuery中遇到<audio>
元素的timeupdate
事件有问题(我使用的是1.7.1版本)。我的目标是将一个函数绑定到它,然后取消绑定它,然后再绑定它。它在Firefox,谷歌浏览器和Internet Explorer 10中的表现并不像我期望的那样。火狐和谷歌浏览器的行为相同,但Internet Explorer 10表现不一样(惊喜!)。当然,我希望它能在这三种方式中发挥作用。
我认为问题最好用代码本身来描述(问题的细节在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();
});
有什么想法吗?
答案 0 :(得分:2)
看起来问题就是这个问题:
$('.goal, .choices').fadeOut(function() {
$('#audio-try_again').off('timeupdate');
setTimeout(generate_objects, 200);
});
选择器$('.goal, .choices')
将返回一个包含两个元素的jQuery集合,这意味着将调用两次回调函数(每个匹配元素一次)。
根据您的具体应用,快速而肮脏的方法是:
$('.goal, .choices').fadeOut(function() {
if ( $(this).is('.goal') ) return;
$('#audio-try_again').off('timeupdate');
setTimeout(generate_objects, 200);
});
基本上,只执行一次回调中的内容。