Как динамически вставить тег <script> через jQuery после загрузки страницы?

102

У меня проблемы с этим. Сначала я попытался установить теги сценария как строки, а затем с помощью jquery replaceWith () добавить их в документ после загрузки страницы:

var a = '<script type="text/javascript">some script here</script>';
$('#someelement').replaceWith(a);

Но у меня есть ошибки строкового литерала в этой переменной. Затем я попытался кодировать строку, например:

var a = '&left;script type="text/javascript"&gt;some script here&lt;\/script&gt;';

но отправив это для replaceWith()вывода только этой строки в браузер.

Может кто-нибудь, дайте мне знать, как вы будете динамически добавлять <script>тег в браузер после загрузки страницы, в идеале через jQuery?

Дуг
источник
Можете ли вы объяснить, чего вы пытаетесь достичь, добавляя <script>тег к документу?
Pointy
Ответ @ Rocket - лучший, но если вы определенно хотите добавить встроенный скрипт из строки, вы просто передадите его eval()функции. Но использование eval()почти всегда предполагает, что есть лучший способ сделать то, что вы пытаетесь сделать.
Ник,
мы пытаемся отложить загрузку сторонних объявлений до конца страницы. эти объявления вызываются через 2 тега сценария, поэтому я хотел запустить функцию после загрузки страницы, которая будет динамически их вставлять.
Дуг,
2
Не все сторонние скрипты предназначены для отложенного выполнения. Если скрипт использует document.writeи вы вызываете его после загрузки страницы, он уничтожит страницу.
bob с
1
Почему бы не импортировать эти теги в <iframe>элементы? Вы можете отложить установку <iframe>URL-адреса, пока не будете готовы.
Pointy

Ответы:

103

Вы можете поместить сценарий в отдельный файл, а затем использовать $.getScriptдля его загрузки и запуска.

Пример:

$.getScript("test.js", function(){
    alert("Running test.js");
});
Ракетный Хазмат
источник
2
спасибо, но это вставит это в DOM? Я понимаю, что упустил эту важную информацию, что мне нужно, чтобы тег скрипта был вставлен в DOM, оценен, после чего он возвращает сторонний рекламный код для отображения на нашем сайте в определенном <div>.
Дуг,
1
$.getScriptпросто загрузит файл .js через AJAX и выполнит его. Скрипт не обязательно должен находиться в DOM, чтобы иметь доступ к div на вашей странице.
Rocket Hazmat
6
Но со $.getScript()сценарием нужно будет находиться в одном домене или удаленный домен и браузер должны будут поддерживать CORS.
hippietrail
14
@hippietrail На самом деле это неправда. Он просто вставляет простой тег скрипта, который не требует CORS или того же домена. Я использую это, чтобы сократить код для загрузки, например, Google Analytics, и он отлично загружается. Фактически выполняемый код jquery очень похож на фрагмент кода GA.
Крис Москини
39
Поскольку ответ от @hippietrail привлечет наибольшее внимание своими четырьмя положительными голосами, следует четко указать, что он неверен. Как подчеркивается в $.ajaxпримечаниях документации jQuery : «На запросы сценариев и JSONP не распространяются одни и те же ограничения политики происхождения». источник . Другими словами, вы $.getScriptможете извлекать файлы .js из других доменов, а не только из вашего собственного .
EleventyOne
64

Попробуйте следующее:

<script type="text/javascript">
// Use any event to append the code
$(document).ready(function() 
{
    var s = document.createElement("script");
    s.type = "text/javascript";
    s.src = "http://scriptlocation/das.js";
    // Use any selector
    $("head").append(s);
});

http://api.jquery.com/append

Bassem
источник
4
+1 для использования, appendчтобы добавить скрипт. Добавление вызывает немедленную оценку даже встроенного скрипта (именно то, что мне нужно). Спасибо
Gone Coding
1
У меня в IE8 / 9 возникает множество проблем с этим подходом. А именно ошибки переполнения стека. Я прибег к методу $ .getScript () ниже, чтобы эта работа работала по всем направлениям.
zmonteca 02
1
Да @jcoffland, это было написано в октябре 2010 года :)
Bassem
Если страница, содержащая этот код, загружается с использованием AJAX, браузер выдаст предупреждение «Синхронный XMLHttpRequest в основном потоке устарел из-за его отрицательного воздействия на взаимодействие с конечным пользователем».
Rajshekar Reddy 03
@Reddy Отличный комментарий. Это было опубликовано в октябре 2010 года, я уверен, что к настоящему времени этот метод больше не является допустимым / рекомендуемым подходом, пользователи должны действовать по своему усмотрению.
Bassem
34

Вот правильный способ сделать это с помощью современного (2014) JQuery:

$(function () {
  $('<script>')
    .attr('type', 'text/javascript')
    .text('some script here')
    .appendTo('head');
})

или если вы действительно хотите заменить div, вы можете сделать:

$(function () {
  $('<script>')
    .attr('type', 'text/javascript')
    .text('some script here')
    .replaceAll('#someelement');
});
Jcoffland
источник
3
Или вместо .text ('здесь какой-то скрипт') можно написать .attr ('src', 'path_to_your_js_file')
Сергей Максимчук
12

Более простой способ:

$('head').append('<script type="text/javascript" src="your.js"></script>');

Вы также можете использовать эту форму для загрузки css.

Иман
источник
6
Возможно, вы захотите не помещать строку </script>в свой источник, поскольку это может вызвать проблемы с синтаксическим
анализом
2
спасение от последнего /$('head').append('<script src="your.js"><\/script>');
помогло
5

Этот ответ технически аналогичен тому, что ответил jcoffland, или равен ему. Я просто добавил запрос, чтобы определить, присутствует ли сценарий уже или нет. Мне это нужно, потому что я работаю на веб-сайте интрасети с парой модулей, некоторые из которых совместно используют сценарии или приносят свои собственные, но эти сценарии не нужно загружать каждый раз снова. Я использую этот фрагмент уже более года в производственной среде, он отлично работает. Комментируя про себя: Да, я знаю, правильнее было бы спросить, существует ли функция ... :-)

if (!$('head > script[src="js/jquery.searchable.min.js"]').length) {
    $('head').append($('<script />').attr('src','js/jquery.searchable.min.js'));
}
ddlab
источник
кстати. Я делаю то же самое с таблицами стилей: if (! $ ('Head> link [href = "widgets / css / widgets.css"]'). Length) {$ ('head'). Append ($ ('<link / > '). attr (' rel ',' stylesheet '). attr (' href ',' widgets / css / widgets.css '));}
ddlab
2

Есть одно обходное решение, которое больше похоже на взлом, и я согласен, что это не самый элегантный способ сделать это, но работает на 100%:

Скажите, что ваш ответ AJAX похож на

<b>some html</b>
<script>alert("and some javscript")

Обратите внимание, что я специально пропустил закрывающий тег. Затем в скрипте, загружающем вышеуказанное, сделайте следующее:

$.ajax({
    url: "path/to/return/the-above-js+html.php",
    success: function(newhtml){
        newhtml += "<";
        newhtml += "/script>";
        $("head").append(newhtml);
    }
});

Только не спрашивайте меня, почему :-) Это одна из тех вещей, к которым я пришел в результате отчаянных почти случайных испытаний и неудач.

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

В такие моменты я чувствую, что успешно разделил на ноль.

Боян
источник
3
Это не сработает, если закрывающий тег скрипта является цельным, поскольку браузер видит его как закрывающий тег для вашего скрипта, а не строковый литерал.
Gone Coding
1
<\/script>будет действительным, хотя
SP
Я думаю, что @ TrueBlueAussie высказался в ответ на ваш комментарий: «Только не спрашивайте меня, почему ... но, что интересно, это НЕ сработает, если вы добавите закрывающий тег в одну строку». Он объяснил почему, чтобы любой читатель, который хотел бы получить ответ лучше, чем «я не знаю», мог легче его найти. См. Также: javascript.crockford.com/script.html
jacobq
1
@Sathvik правильный, согласно этой ссылке. Комментарий Эша, похоже, был ответом на комментарий, который был удален.
Арлен Бейлер,
2

Пример:

var a = '<script type="text/javascript">some script here</script>';
$('#someelement').replaceWith(a);

Он должен работать. Я попробовал; тот же результат. Но когда я использовал это:

var length = 1;
var html = "";
for (var i = 0; i < length; i++) {
    html += '<div id="codeSnippet"></div>';
    html += '<script type="text/javascript">';
    html += 'your script here';
    html += '</script>';
}
$('#someElement').replaceWith(a);

Это сработало для меня.

Изменить: я забыл #someelement(кстати, я мог бы использовать #someElementиз-за соглашений)

Самым важным здесь является + =, поэтому html добавляется, а не заменяется.

Оставьте комментарий, если не сработало. Я хочу вам помочь!

Сантинобонора
источник
2

Вот более понятный способ - без jQuery - который добавляет скрипт в качестве последнего дочернего элемента <body>:

document.body.innerHTML +='<script src="mycdn.js"><\/script>'

Но если вы хотите добавлять и загружать скрипты, используйте метод Rocket Hazmat .

Гагик Саргсян
источник
-4

Если вы пытаетесь запустить динамически сгенерированный JavaScript, вам будет немного лучше, используя eval. Однако JavaScript - настолько динамичный язык, что в нем действительно не должно быть необходимости.

Если скрипт статический, то getScript-предложение Rocket - правильный выбор.

Магнар
источник