Невозможно добавить элемент <script>

Любая идея, почему часть кода ниже не добавляет элемент script в DOM?

var code = "<script></script>";
$("#someElement").append(code);

Ответ 1

Я видел проблемы, когда некоторые браузеры не уважают некоторые изменения, когда вы делаете их напрямую (под этим я подразумеваю создание HTML из текста, как вы пытаетесь использовать тег script), но когда вы их делаете со встроенными командами все идет лучше. Попробуйте следующее:

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.src = url;
$("#someElement").append( script );

От: JSON для jQuery

Ответ 2

Хорошие новости это:

Это 100% работает.

Просто добавьте что-нибудь внутри тега script, например alert('voila!'); , Правильный вопрос, который вы, возможно, захотите задать, возможно, "Почему я не видел его в DOM?" ,

Карл Сведберг сделал приятное объяснение комментариям посетителей на сайте jQuery API. Я не хочу повторять все его слова, вы можете прочитать прямо здесь, здесь (мне было трудно перемещаться по комментариям там).

Все методы вставки jQuery используют внутреннюю функцию domManip для очистки/обработки элементов до и после их вставки в DOM. Одна из функций, которую выполняет функция domManip, - это извлечь все элементы сценария, которые собираются вставить, и запустить их через "подпрограмму evalScript", а не вставлять их с остальной частью фрагмента DOM. Он вставляет сценарии отдельно, оценивает их, а затем удаляет их из DOM.

Я полагаю, что одной из причин, по которой jQuery делает это, является предотвращение ошибок "Permission Denied", которые могут возникать в Internet Explorer при вставке сценариев при определенных обстоятельствах. Это также позволяет избежать повторной вставки/оценки одного и того же сценария (который потенциально может вызвать проблемы), если он находится внутри содержащего элемента, который вставляется, а затем перемещается по DOM.

Далее я .append() итог плохих новостей, используя .append() для добавления сценария.


И плохие новости это..

Вы не можете отлаживать свой код.

Я не шучу, даже если вы добавите debugger; Ключевое слово между строкой, которую вы хотите установить в качестве точки останова, в конечном итоге вы получите только стек вызовов объекта, не видя точку останова в исходном коде (не говоря уже о том, что это ключевое слово работает только в браузере WebKit, все остальные основные браузеры, кажется, опускают это ключевое слово).

Если вы полностью понимаете, что делает ваш код, это будет незначительным недостатком. Но если вы этого не сделаете, вы добавите debugger; Ключевое слово повсюду, чтобы узнать, что не так с вашим (или моим) кодом. В любом случае, есть альтернатива, не забывайте, что javascript может манипулировать HTML DOM.


Обходной путь.

Используйте JavaScript (не JQuery) для управления HTML DOM

Если вы не хотите потерять возможность отладки, тогда вы можете использовать нативную HTML-манипуляцию с DOM. Рассмотрим этот пример:

var script   = document.createElement("script");
script.type  = "text/javascript";
script.src   = "path/to/your/javascript.js";    // use this for linked script
script.text  = "alert('voila!');"               // use this for inline script
document.body.appendChild(script);

Вот оно, как в старые добрые времена, не так ли? И не забывайте убирать вещи, будь то в DOM или в памяти, для всех объектов, на которые есть ссылки и которые больше не нужны, чтобы предотвратить утечки памяти. Вы можете рассмотреть этот код, чтобы очистить вещи:

document.body.removechild(document.body.lastChild);
delete UnusedReferencedObjects; // replace UnusedReferencedObject with any object you created in the script you load.

Недостаток этого обходного пути заключается в том, что вы можете случайно добавить дубликат сценария, и это плохо. Отсюда вы можете слегка имитировать .append(), добавив проверку объекта перед добавлением и удалив сценарий из DOM сразу после его добавления. Рассмотрим этот пример:

function AddScript(url, object){
    if (object != null){
        // add script
        var script   = document.createElement("script");
        script.type  = "text/javascript";
        script.src   = "path/to/your/javascript.js";
        document.body.appendChild(script);

        // remove from the dom
        document.body.removeChild(document.body.lastChild);
        return true;
    } else {
        return false;
    };
};

function DeleteObject(UnusedReferencedObjects) {
    delete UnusedReferencedObjects;
}

Таким образом, вы можете добавить скрипт с возможностью отладки, в то же время не подвергаясь дублированию скриптов. Это всего лишь прототип, вы можете расширить его до того, что хотите. Я использовал этот подход и вполне доволен этим. Конечно же, я никогда не буду использовать jQuery .append() для добавления скрипта.

Ответ 3

Можно динамически загружать файл JavaScript с помощью функции jQuery getScript

$.getScript('http://www.whatever.com/shareprice/shareprice.js', function() {
  Display.sharePrice();
});

Теперь будет вызываться внешний script, и если он не может быть загружен, он будет изящно деградировать.

Ответ 4

Что значит "не работает"?

jQuery обнаруживает, что вы пытаетесь создать элемент SCRIPT и будете автоматически запускать содержимое элемента в глобальном контексте. Вы говорите мне, что это не работает для вас? -

$('#someElement').append('<script>alert("WORKING");</script>');

Изменить: если вы не видите элемент SCRIPT в DOM (например, в Firebug) после запуска команды, так как jQuery, как я уже сказал, запустит код, а затем удалит SCRIPT элемент - я считаю, что элементы SCRIPT всегда добавляются к телу... но в любом случае - размещение абсолютно не влияет на выполнение кода в этой ситуации.

Ответ 5

Это работает:

$('body').append($("<script>alert('Hi!');<\/script>")[0]);

Кажется, что jQuery делает что-то умное со сценариями, поэтому вам нужно добавить элемент html, а не объект jQuery.

Ответ 6

Попробуйте это может быть полезно:

var fileref=document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src","scriptAnalytics.js");
document.getElementsByTagName("head")[0].appendChild(fileref);

Ответ 7

Я хочу сделать то же самое, но добавить тэг script в другой фрейм!

var url = 'library.js'; 
var script = window.parent.frames[1].document.createElement('script' ); 
script.type = 'text/javascript'; 
script.src = url;
$('head',window.parent.frames[1].document).append(script);

Ответ 8

<script>
    ...
    ...jQuery("<script></script>")...
    ...
</script>

</script> внутри строкового литерала завершает весь script, чтобы избежать использования "</scr" + "ipt>".

Ответ 9

Добавление sourceURL в файл script помогло, как указано на этой странице: https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/

  • В файле script добавьте оператор с sourceURL, например "//@sourceURL = foo.js"
  • Загрузите script с помощью jQuery $.getScript(), а script будет доступен на вкладке "sources" в инструментах chrome dev

Ответ 10

Выполняется ваш script, вы просто не можете использовать document.write из него. Используйте предупреждение, чтобы проверить его и не использовать document.write. Заявления вашего js файла с document.write не будут выполнены, а остальная часть функции будет выполнена.

Ответ 11

Это то, что я считаю лучшим решением. Google Analytics вводится таким образом.

var (function(){
    var p="https:" == document.location.protocol ? "https://" : "http://";
        d=document,
        g=d.createElement('script'),
        s=d.getElementsByTagName('script')[0];
        g.type='text/javascript';
        g.src=p+'url-to-your-script.js';
        s.parentNode.insertBefore(g,s); })();

Ответ 12

Вам не нужен jQuery для создания Script DOM-элемента. Это можно сделать с помощью vanilla ES6 примерно так:

const script = "console.log('Did it work?')"
new Promise((resolve, reject) => {
  (function(i,s,o,g,r,a,m){
      a=s.createElement(o),m=s.getElementsByTagName(o)[0];
      a.innerText=g;
      a.onload=r;m.parentNode.insertBefore(a,m)}
  )(window,document,'script',script, resolve())
}).then(() => console.log('Sure did!'))

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

Ответ 13

Добавить script в тело:

$(document).ready(function() {
    $("<script>", {  src : "bootstrap.min.js",  type : "text/javascript" }).appendTo("body");
});

Ответ 14

Другой способ сделать это, если вы хотите добавить код, - это использовать метод document.createElement, но затем использовать .innerHTML вместо .src.

var script = document.createElement( 'script' );
script.type = 'text/javascript';
script.innerHTML = 'alert("Hey there... you just appended this script to the body");';
$("body").append( script );

Ответ 15

Я пробовал этот один и отлично работает. Просто замените символ < на \x3C.

// With Variable
var code = "\x3Cscript>SomeCode\x3C/script>";
$("#someElement").append(code);

или

//Without Variable
$("#someElement").append("\x3Cscript>SomeCode\x3C/script>");

Вы можете протестировать код здесь.

Ответ 16

Можете попробовать это

var code = "<script></" + "script>";
$("#someElement").append(code);

Единственная причина, по которой вы не можете выполнить "<script></script>" - это то, что строка не разрешена внутри javascript, потому что слой DOM не может разобрать, что js и какой HTML.

Ответ 17

Я написал пакет npm, который позволяет вам взять строку HTML, включая теги скриптов, и добавить ее в контейнер при выполнении сценариев

Пример:

import appendHtml from 'appendhtml';

const html = '<p>Hello</p><script src="some_js_file.js"></script>'; 
const container = document.getElementById('some-div');

await appendHtml(html, container);

// appendHtml returns a Promise, some_js_file.js is now loaded and executed (note the await)

Найдите его здесь: https://www.npmjs.com/package/appendhtml

Ответ 18

Просто создайте элемент, проанализируя его с помощью jQuery.

<div id="someElement"></div>
<script>
    var code = "<script>alert(123);<\/script>";
    $("#someElement").append($(code));
</script>

Рабочий пример: https://plnkr.co/edit/V2FE28Q2eBrJoJ6PUEBz