Мне нужен обходной путь для ошибки Safari / Chrome, которая становится бельмом на моей стороне - PullRequest
6 голосов
/ 24 ноября 2010

Итак, у меня есть эта замечательная небольшая функция JavaScript, которую я использую для печати текста в окне браузера в классном стиле командной строки. Он берет строку и печатает ее по одному символу за раз в окне с заданным интервалом. Вот оно: (Я вырезал все ненужные части, чтобы это работало как отдельный пример.)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
    <script type="text/javascript">
        var letterIndex = 0;
        var intervalId = 0;

        function writeOneLetter(myString)
        {
            var char = myString[letterIndex];
            $('#display').append(char);
            letterIndex++;
            if (letterIndex >= myString.length)
            {
                letterIndex = 0;
                clearInterval(intervalId);
            }
        }

        $(function ()
        {
            $('#caret').html('\u2588'); //This will help you visualize where the script is at in it's sequence and make it painfully obvious when the freezing issue occurs.

            // The following string sample is so long because it is important that you be able to duplicate this error to understand my question.
            var myString = "Quisque vestibulum consequat orci, in euismod tortor dapibus eu. Duis nec urna nec erat sagittis pretium vel ac diam. Nulla mi lorem, tempor ut cursus in, mattis non libero. Curabitur eget venenatis justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas blandit ante in ligula tincidunt quis vehicula massa scelerisque. Pellentesque nec posuere massa. Sed eget nunc a erat dictum faucibus. In vitae tempor lorem. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean vel imperdiet tellus. Suspendisse ultricies sem a libero sagittis feugiat. Ut convallis magna eu mauris molestie dapibus. Nulla feugiat urna non ante facilisis non ultrices nisi viverra. Aliquam vitae magna libero. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur at odio sit amet nisi dapibus scelerisque. In fringilla lorem at sapien rutrum scelerisque."

            intervalId = setInterval(function () { writeOneLetter(myString); }, 15);
        });

    </script>
</head>
<body>
    <span id="display">
    </span><span id="caret"></span>
</body>
</html>

Перейдите сюда http://www.jsfiddle.net/Chevex/6n5VV/, чтобы опробовать приведенный выше пример кода.

Если вы находитесь в IE или FF, код будет работать точно так, как ожидается, записывая каждый символ в строке до его завершения. Однако, если вы запустите этот код в Chrome или Safari, вы получите интересную ошибку. Иногда, когда строка попадает на сторону контейнера и слова переносятся и переходят на следующую строку, она останавливается. Печатание перестает отображаться в браузере, но оно все еще происходит в DOM, потому что, если страница изменяется или размер браузера изменяется, то оставшийся текст появляется сразу.

Пара вещей, которые я заметил по этому поводу, заключается в том, что это, кажется, происходит только тогда, когда оно опускается вниз по строке с начальным пробелом. Кроме того, если вы измените размер окна браузера во время работы скрипта или после его завершения, он внезапно вернется к действию, и вы увидите остальную часть текста. При любом изменении размера, максимизации и т. Д. Буквы снова появляются; только чтобы заморозить позже, конечно.

Это очень расстраивает, так как никогда не показывает остальную часть строки, если страница не будет изменена с помощью большего количества javascript впоследствии или размер браузера не изменится. Когда это происходит, это полностью отрицает всю цель написания сценария.

Есть идеи? Я в полном замешательстве, и Google ничего не показывает.

EDIT:

Если вы не можете воспроизвести ошибку, возможно, это из-за того, что у вас разрешение экрана отличается от моего, и вам повезло. Попробуйте изменить размер окна браузера, контейнера отображения jsFiddle или их обоих, а затем снова запустите сценарий. Это не должно занять много времени, прежде чем вы увидите, что он замерзнет. Постарайтесь прицелиться, чтобы одна из строк заполняла слово пробелом, это, по-видимому, и происходит в основном.

Я сделал это в Chrome и Safari на 3 разных компьютерах, один в совершенно другой сети. Если вы все еще не видите ошибку, запустите ее в Chrome и Firefox рядом. Если хром, кажется, заканчивается раньше, чем FF, то это замораживающий сбой в действии. Если вы измените размер браузера или измените каким-либо образом страницу, внезапно весь оставшийся текст появится сразу.

Ответы [ 2 ]

5 голосов
/ 24 ноября 2010

Это работает, если вы не добавляете каждый символ как отдельный узел, а обновляете все текстовое содержимое диапазона каждый раз, когда вызывается функция writeOneLetter:

    function writeOneLetter(myString)
    {
        var char = myString[letterIndex];
        $('#display').text($('#display').text()+char);
        letterIndex++;
        if (letterIndex >= myString.length)
        {
            letterIndex = 0;
            clearInterval(intervalId);
        }
    }

Попробуйте здесь: http://www.jsfiddle.net/5R3JP/

1 голос
/ 24 ноября 2010

Странная ошибка, я согласен. Я получаю то же поведение, которое вы описываете (Chrome 7.0.517.44 под Windows). В моем случае, если возникает ошибка, я даже не получаю весь текст, отображаемый после завершения сценария.

Один трюк, который, кажется, работает для меня, - это чередовать внешний вид каретки (я думаю, это заставляет Chrome сделать какое-то изменение). Это ужасно, я знаю, и, очевидно, намного медленнее (хотя и не заметно на моей машине), но, возможно, вы можете использовать его как временное решение?

var letterIndex = 0;
var intervalId = 0;

function writeOneLetter(myString)
{
  var char = myString[letterIndex];
  $('#display').append(char);
  $('#caret').css("font-weight", letterIndex % 2 ? "bold" : "normal");
  letterIndex++;
  if (letterIndex >= myString.length)
  {
    letterIndex = 0;
    clearInterval(intervalId);
  }
}

Примечание: установка жирным шрифтом символа каретки фактически не меняет его внешний вид, поэтому вы фактически не увидите чередования для каждого символа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...