Как устранить пост-рендер "мерцание"?

Я изо всех сил старался быть пуристом с использованием методов Javascript/Ajax, гарантируя, что все Ajax-y поведение является улучшением базовых функций, а сайт также полностью работоспособен, когда Javascript отключен. Однако это вызывает некоторые проблемы.

В некоторых случаях DOM node должен отображаться только в том случае, если в браузере включен Javascript. В других случаях он должен быть видимым только при отключении. Возьмем, например, кнопку отправки в форме, которая имеет выпадающий список с обработчиком onchange, который автоматически отправляет (используя плагин формы JQuery):

<form method="post" action=".">
    <label for="id_state">State:</label>
    <select name="state" id="id_state" onchange="$(this.form).ajaxSubmit(ajax_submit_handler);">
        <option value="AL">Alabama</option>
        <option value="AK">Alaska</option>
    </select>
    <input class="with_js_disabled" type="submit" value="OK" />
</form>

и Javascript:

<script type="text/javascript">
    $(document).ready(function()
    {
        $(".with_js_disabled").hide();
    });
</script>

Когда Javascript включен, кнопка отправки не требуется (из-за обработчика onchange). Однако функция JQuery $(document).ready(и более прямая document.onload) вызывается только после того, как страница была полностью загружена и отображена - следовательно, сначала отображается кнопка отправки и появляется "вспышка", когда Javascript и на дисплее node установлено значение "none".

Я принял это как стоимость ведения бизнеса и не нашел пути вокруг него. Но есть ли техника, о которой я не знаю, что минимизирует эффект или даже полностью устранит ее?

EDIT:

Решение <noscript>, упомянутое многими людьми ниже, кажется многообещающим, но не работает для меня в Safari. Однако предварительное предложение Престола прекрасно работает:

<body>
    <script type="text/javascript">
        document.body.className += ' has_js';
    </script>
    <!-- the rest of your page -->
</body>

В этом случае можно использовать стильный CSS:

body .js_enabled_only { display: none; }
body .js_disabled_only { display: block; }
body.has_js .js_enabled_only { display: block; }
body.has_js .js_disabled_only { display: none; }

Эта вторая строка предназначена только для справки и может (и должна) удаляться, чтобы избежать ситуаций, когда ваш элемент не должен отображаться: block. Аналогично, для других стилей отображения вам могут потребоваться разные варианты в третьей строке. Но это решение красиво и чисто, IMO, и в моих тестах полностью устраняет эффект мерцания.

Ответы

Ответ 1

Как объединить некоторые из этих решений:

<style type="text/javascript">
    .only-without-script {
        display: none;
    }
</style>
<noscript>
    <style type="text/javascript">
        .only-with-script {
            display: none;
        }
        .only-without-script {
            display: block;
        }
    </style>
</noscript>

или я предпочитаю добавлять класс в тело (поместите тэг <script> в верхнюю часть тела и не используйте событие .ready):

<head>
    <style type="text/javascript">
        body.has-script .something-not-ajaxy {
            display: none;
        }

        input.ajaxy-submit {
            display: none;
        }
        body.has-script input.ajaxy-submit {
            display: inline;
        }
    </style>
</head>
<body>
    <script type="text/javascript">
        document.body.className += ' has-script';
    </script>
    <!-- the rest of your page -->
</body>

Ответ 2

В ситуациях, идентичных вашим, я обычно помещаю кнопку отправки вокруг тега <noscript>. Никто не предложил это, поэтому я не уверен, что это считается плохой практикой вокруг этих частей, но это то, что я использую, и это работает для меня.

Если вы хотите, чтобы только node отображался, когда включен Javascript, вы можете сделать это в голове:

<noscript>
    <style type="text/css">
    .js-enabled { display: none; }
    </style>
</noscript>

И затем дайте любым Javascript-элементам класс js-enabled.

Ответ 3

Как и Дэвид сказал, вы можете добавить Javascript, который добавляет таблицу стилей, чтобы скрыть все "лишние" html-элементы:

<head>
  ...
  <script type="text/javascript" language="javascript">
    document.write('<style type="text/css"> .disabled-if-javascript { display: none; } </style>');
  </script>
</head>
...

Если Javascript включен, он устанавливает все элементы класса "disabled-if-javascript" в спрятанное, прежде чем тело будет загружено. Просто добавьте этот класс ко всем элементам, которые должны быть скрыты, если включен javascript. Вам также может понадобиться класс enabled-if-javascript, который делает обратное, чтобы показать определенные элементы, которые будут скрыты для не-javascript. Возможно, вам нужно добавить "!important" в ваше определение стиля там, чтобы переопределить существующие (не javascript) правила.

Ответ 4

Я могу представить два метода:

1 - Предварительно определите, включен ли Javascript и сохранит эту информацию в файле cookie/сеансе. Это можно сделать на первой странице и устранить большинство мерцаний.

2 - Используйте livequery plugin, который обнаруживает элементы, поскольку они добавлены в DOM. Вы можете запустить его сразу, когда Javascript заканчивает загрузку, что должно быть намного до документа (это его в голове).

$('.with_js_disabled').livequery(function() {
     $(this).hide();
});

Ответ 5

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

Ответ 6

Простая вещь: добавьте <script>jQuery.ready();</script> прямо перед закрытием тега body.

Это заставит все привязки к событию "ready" для запуска. И если вы запустите их в конце документа, DOM будет загружен и готов к работе, даже если "родное" событие onDomContentLoaded еще не запущено.

Это обычно работает для меня, когда я хочу удалить мерцание, особенно в IE/win, поскольку IE имеет собственный эмулятор domready в событии jQuery "ready".