Создание Node Style, добавление innerHTML, добавление в DOM и проблемы с IE - PullRequest
3 голосов
/ 08 марта 2011

У меня есть вопрос из двух частей.

Сначала сценарий:

Из-за некоторых странных проблем, с которыми мы столкнулись в связи с поддержкой мобильных браузеров NOSCRIPT, мне поручено предложить альтернативное решение для «обнаружения» JS. Логика решения состоит в том, чтобы на странице было два DIV. Одним из них является ошибка, указывающая на то, что у вас нет JS и его показывается по умолчанию. Если у вас есть JS, мы хотим добавить новый блок STYLE в HEAD, который переопределяет предыдущий CSS, скрывает ошибку и вместо этого показывает содержимое.

Пример HTML:

<div id="div1">div 1 (should be shown if JS enabled)</div>
<div id="div2">div 2 (should be hidden if JS enabled)</div>

Это JS, с которой я начал:

  var styleNode = document.createElement('style');
  styleNode.setAttribute("type", "text/css");
  styleNode.innerHTML = "#div1 {display: block;} #div2 {display: none;}";
  headTag.appendChild(styleNode);

Но у меня были проблемы. Некоторое гугление приводит к описанию проблемы безопасности, которая может возникнуть в IE, если вы попытаетесь вставить innerHTML в созданный элемент перед помещением его в DOM:

http://karma.nucleuscms.org/item/101

Итак, я изменил скрипт так:

  var styleNode = document.createElement('style');
  styleNode.setAttribute("type", "text/css");
  var headTag = document.getElementsByTagName("head")[0];
  headTag.appendChild(styleNode);
  var aStyleTags = headTag.getElementsByTagName("style");
  var justAddedStyleTag = aStyleTags[aStyleTags.length-1];
  justAddedStyleTag.innerHTML = "#div1 {display: block;} #div2 {display: none;}";

вопрос 1 : это верный обходной путь для проблемы IE? Есть ли более эффективное решение?

вопрос 2 : даже с настройкой скрипт все равно не работает в IE. В Firefox он работает нормально, но в IE 7 я получаю «неизвестную ошибку времени выполнения».

У меня есть образец этого кода на JSBIN:

http://jsbin.com/ucesi4/4

Кто-нибудь знает, что происходит с IE?

UPDATE:

Я наткнулся на эту ссылку через Google. Обратите внимание на последний комментарий:

http://msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx

Тем не менее, вы действительно должны положить все правила стиля в HEAD для строгих соответствие XHTML. Делать это можно также быть немного хитрым, потому что вы не может использовать innerHTML для внедрения в элемент HEAD или STYLE напрямую. (Оба эти тега предназначены только для чтения.)

Eep! Правда? FireFox просто чрезмерно прощает? Или это просто очень странная странность IE?

ОБНОВЛЕНИЕ 2:

Немного больше информации о том, что мы пытаемся здесь решить. Мы имеем дело с мобильными устройствами, и некоторые из устаревших устройств а) не поддерживают NOSCRIPT и б) имеют медленные движки JS.

Так как они не поддерживают NOSCRIPT, мы по умолчанию показываем ошибку, затем скрываем ее через JS, если она есть, и представляем им соответствующий контент. Из-за медленных движков JS на них люди видят «мерцание» показа / скрытия DIV. Это было предлагаемое решение, чтобы справиться с этим, так как он будет загружать CSS еще до того, как DIV будут отображены.

Так как он кажется недействительным, решение будет состоять в том, что на этих старых устройствах мы будем использовать этот метод (как кажется, он работает, даже если не в IE), а затем все другие правильные браузеры будут делать то, что предложено. ... мы просто обновим свойство DISPLAY CSS через встроенный JS после загрузки каждого DIV в DOM.

При всем этом мне все еще интересно, является ли эта проблема ошибкой IE, или же IE действительно придерживается надлежащих стандартов, делая STYLE элементом только для чтения.

Ответы [ 3 ]

6 голосов
/ 04 сентября 2011

В IE вы можете использовать style.styleSheet.cssText:

var style = document.createElement('style');
style.type = 'text/css';

if (style.styleSheet) { // IE
    style.styleSheet.cssText = css;
} else {
    style.appendChild(document.createTextNode(css));
}

document.getElementsByTagName('head')[0].appendChild(style);

Попробуйте это здесь: http://jsfiddle.net/QqF77/

См. Ответ на этот вопрос: Как создать тег

1 голос
/ 08 марта 2011

Не используйте innerHTML, используйте document.createTextNode(), и ваша жизнь станет бесконечно лучше;)

var styleNode = document.createElement('style');
styleNode.setAttribute("type", "text/css");
var textNode = document.createTextNode("#div1 {display: block;} #div2 {display: none;}");
styleNode.appendChild(textNode);
headTag.appendChild(styleNode);

EDIT:

Поскольку это решение, похоже, не работает для вас, я бы от него отказался. Вместо этого перейдите к решению, где стили уже определены и где вы просто отключили / включили стили через javascript, если он доступен.

Вы можете сделать это следующим образом:

<head>
<style>
.jsenabled #div2, #div1 { display: none;}
.jsenabled #div1, #div2 { display: block;}
</style>
<script>
//i know you don't use jQuery, but the solution should still be valid as a concept
//bind to DOM-ready, then set the class jsenabled on the body tag
$(function() {
 $(document.body).addClass('jsenabled');
});
</script>
</head>
<body>
<div id="div1">div 1 (should be shown if JS enabled)</div>
<div id="div2">div 2 (should be hidden if JS enabled)</div>
</body>

РЕДАКТИРОВАТЬ 2:

Если это нужно сделать до того, как DOM будет готов, вы можете сделать что-то вроде этого:

<head>
<style>
#div2, .show { display: block;}
#div1, .hide { display: none;}
</style>
</head>
<body>
<div class="hide">
<script>document.write('</div><div id="div1">');</script>
   div 1 (should be shown if JS enabled)
</div>
<script>document.write('<div class="hide">');</script>
<div id="div2">div 2 (should be hidden if JS enabled)</div>
<script>document.write('</div>');</script>
</body>

Или для простоты, вы можете просто сделать

<head>
<script>document.write('<style>#div1 {display: block;} #div2 {display: none;}</style>');
</head>
<body>
<div id="div1">div 1 (should be shown if JS enabled)</div>
<div id="div2">div 2 (should be hidden if JS enabled)</div>
</body>
0 голосов
/ 12 июня 2013

Лучше всего ставить все

...