Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   HTML и JS-код в innerHTML (https://javascript.ru/forum/misc/45094-html-i-js-kod-v-innerhtml.html)

mcfly 14.02.2014 02:04

HTML и JS-код в innerHTML
 
Здравствуйте, гуру!
Прошу помощи в нелегкой для меня задаче.

На странице 1 имеется див и инклуд JS-файла.

Возможно ли из этого JS-файла в див поместить смешенный текст HTML+JS (например: Привет <script>alert('HI!');</script>), так чтобы HTML вывелся и JS отработал, как будто я бы этот код изначально в див прописал?

Я знаю как вывести HTML и выполнить JS, но отдельно друг от друга, но строка может содержать беспорядочную последовательность перемешанного HTML и JS-кода.

Спасибо!

Vlasenko Fedor 14.02.2014 03:27

С помощью eval и регулярных выражений
<div id="test"></div>
<script>
  window.onload = function () {
    var txt = "Hi-<script>alert('HI!'); <" + "/script>hi \
        	   Ha-<script>alert('HA!'); <" + "/script>ha";
    test.innerHTML = txt.replace(/<script>(.*?)<\/script>/ig, function (a, b) {
      eval(b);
      return a;
    });
  }
</script>

mcfly 14.02.2014 03:55

Спасибо за ответ.

Я пошел немного дальше и в скрипте своем учитывал не только JS-контейнеры с кодом, но и инклуды:

divObj = document.getElementById('test');
divObj.innerHTML = "ТУТ КОД";
var scripts = divObj.getElementsByTagName("script");
var script;
for(var i = 0; script = scripts[i]; i++)
{
  // Если инклуд JS-скрипта
  if(script.src !== undefined && script.src != '')
  {
    var newScript = document.createElement('script');
    newScript.type = 'text/javascript';
    newScript.src = script.src;
    script.parentNode.insertBefore(newScript, script);
    script.parentNode.removeChild(script);
  }
  // Если просто контейнер с JS-кодом
  else
    eval(script.innerHTML);
}


Все работает отлично. НО, если в инклуде встречается document.write() то FF ругается: Вызов document.write() из асинхронно-загруженного внешнего сценария был проигнорирован.

Можно ли как-то избавиться от этой ошибки и игнора вызова document.write() ?

ADD: Появилась мысль, а что если, при инклуде, через AJAX получать код скрипта и его запускать функцией eval? Это поможет?

danik.js 14.02.2014 08:43

Цитата:

Сообщение от mcfly
script.src !== undefined

Свойство src никогда не бывает undefined. На скриптах оно всегда определено.
Цитата:

Сообщение от mcfly
var newScript = document.createElement('script');

А разве script.cloneNode(true) не подходит?
Цитата:

Сообщение от mcfly
else
    eval(script.innerHTML);

А разве для инлайновых скриптов та же методика перевставки в DOM не подходит? На сколько я знаю с eval'ом траблы кое-какие. Та же jQuery вроде использует вставку в DOM в качестве $.globalEval()

mcfly 14.02.2014 11:31

Цитата:

Сообщение от danik.js
Свойство src никогда не бывает undefined. На скриптах оно всегда определено.

Вы правы, оставил только script.src != '' в условии

Цитата:

Сообщение от danik.js
А разве script.cloneNode(true) не подходит?

Заменил с:
var newScript = document.createElement('script');
      newScript.type = 'text/javascript';
      newScript.src = script.src;
      script.parentNode.insertBefore(newScript, script);
      script.parentNode.removeChild(script);

на:
var newScript = script.cloneNode(true);
      script.parentNode.insertBefore(newScript, script);
      script.parentNode.removeChild(script);

Результат - перестал инклудить. Может если делать клон, то клонирование не заставляет script тэг выполниться заново?

Цитата:

Сообщение от danik.js
А разве для инлайновых скриптов та же методика перевставки в DOM не подходит?

Не совсем понял про какую методику вы имеете в виду и проблема возникает не в инлайновом скрипте, а в инклуженном.

В общем проблема осталась нерешенной: как избавиться от ошибки "Вызов document.write() из асинхронно-загруженного внешнего сценария был проигнорирован".

danik.js 14.02.2014 11:49

Цитата:

Сообщение от mcfly
      script.parentNode.insertBefore(newScri pt, script);
      script.parentNode.removeChild(script);

Это заменяется на script.parentNode.replaceChild(newScript, script)
Цитата:

Сообщение от mcfly
Не совсем понял про какую методику вы имеете в виду

имею ввиду что для инлайн-скриптов тоже создавать новый тег, копировать свойство text (не уверен что кроссбраузерно), и заменять старый тег. То есть вообще не делать различий между инлайн/неинлайн скриптами, и обрабатывать одинаково.

Цитата:

Сообщение от mcfly
как избавиться от ошибки "Вызов document.write()

document.write() не должен вызываться асинхронно. Вообще, после DOMContentLoaded события не должен.
На ум приходит только патч функции document.write (не уверен что кроссбраузерно)


Часовой пояс GMT +3, время: 19:33.