1

我在 jQuery 中的<audio>元素timeupdate事件有问题(我使用的是 1.7.1 版)。我的目标是将函数绑定到它,然后取消绑定,然后再次绑定。它的行为与我在 Firefox、Google Chrome 和 Internet Explorer 10 中的预期不同。Firefox 和 Google Chrome 的行为相同,但 Internet Explorer 10 的行为不同(惊喜!)。当然,我希望它适用于所有三个。

我认为最好用代码本身来描述问题(问题的细节在 HTML 的 second 中<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/

有任何想法吗?

4

1 回答 1

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);
});

本质上,它只会执行该回调中的内容一次。

于 2013-04-04T03:40:47.870 回答