Динамическое выполнение тега с внешним атрибутом src с использованием eval

#javascript #php #jquery #html #ajax

#javascript #php #jquery #HTML #ajax

Вопрос:

Я использую Genius API для извлечения текста для данной песни и встраивания их в HTML <div> -тег. Я взаимодействую с этим API с помощью PHP, через запрос GET AJAX.

В случае успешного AJAX-запроса я извлекаю следующий HTML-код из моего PHP:

 <div id='rg_embed_link_2351532' class='rg_embed_link' data-song-id='2351532'>
    Read <a href='https://genius.com/The-1975-the-sound-lyrics'>“The Sound” by The 1975</a> on Genius
</div> 
<script crossorigin src='//genius.com/songs/2351532/embed.js'></script>
  

Тег script, возвращаемый Genius API, при выполнении встроит текст песни и текстовую информацию.

Я пытаюсь импортировать этот HTML-код в мой уже существующий <div> . В этом случае <script> часть не будет выполнена. Я пытался использовать eval() внутри функции ‘success’ моего AJAX для динамического выполнения этого скрипта, но у меня ничего не получается:

 $.ajax({
    url: 'lyrics.php',
    type: 'GET',
    async: true,
    success: function(success){
        geniusHTML = success;

        //Insert geniusHTML including script tag into div
        var lyricsDiv = document.getElementById("lyricsDiv");
        lyricsDiv.innerHTML = geniusHTML;

        //Get the script tag from the html and use eval on it
        var innerScript = lyricsDiv.getElementsByTagName('script')
        eval(innerScript.outerHTML);
    }
});
  

Я попытался оценить:

  • .outerHTML — Консоль показывает, что это значение равно: <script crossorigin="" src="//genius.com/songs/2351532/embed.js"></script>
  • .innerHTML — Атрибут кажется пустым.
  • .src — Консоль отображает это значение как: http://genius.com/songs/2351532/embed.js . eval() Функция выдает ошибку при этом с помощью Uncaught SyntaxError: Unexpected end of input .

Я чувствую, что потенциально делаю это в обратном направлении. Должен ли я выполнить скрипт из моего возврата AJAX перед добавлением его в div? (Скрипт генерирует довольно много встроенных тегов div)

Редактировать

Следуя инструкциям от ответчика Сьер де Вита, я попытался создать новый тег script из src атрибута исходного тега и добавить его через document.head.appendChild. Это не сработало, выдав предупреждение:

Не удалось выполнить ‘write’ в ‘Document’: невозможно выполнить запись в документ из асинхронно загружаемого внешнего скрипта, если он явно не открыт.

Комментарии:

1. eval() == evil() . Не используйте его. Вы можете прочитать везде в Интернете, почему это плохо использовать.

2. @MarkBaijens Отметил!

Ответ №1:

Вы должны получить src из тега script и динамически создать и загрузить его в свой html

 var script = document.createElement("script");  
var innerScript = lyricsDiv.getElementsByTagName('script')
script.src = innerScript.src; 

document.head.appendChild(script); 
  

Комментарии:

1. Спасибо за ваш комментарий! Это не сработало для скрипта, содержащего embed — пожалуйста, смотрите предупреждение, которое я опубликовал в post edit.

2. Спасибо @Mark Baijens, это объясняет предупреждение. Я не думаю, что смогу реорганизовать скрипт, поскольку он предоставлен Genius, но я попробую postscribe, как указано в ответах. Приветствия!

Ответ №2:

использование jQuery .html() вместо javascript .innerHTML() автоматически оценит скрипты внутри строки

итак, попробуйте изменить эту строку

 //Insert geniusHTML including script tag into div
var lyricsDiv = document.getElementById("lyricsDiv");
lyricsDiv.innerHTML = geniusHTML;

//Get the script tag from the html and use eval on it
var innerScript = lyricsDiv.getElementsByTagName('script')
eval(innerScript.outerHTML);
  

в

 $("#lyricsDiv").html(geniusHTML);
  

Комментарии:

1. Спасибо, Скотт — это работает, но я все еще получаю предупреждение, упомянутое в моей правке. Однако это предупреждение, похоже, является отдельной проблемой, связанной с document.write . Принимаем это как лучший ответ в данном контексте.

Ответ №3:

РЕШЕНИЕ
Отвечая на мой собственный вопрос.

Другие ответы на этот вопрос вполне приемлемы и работают в большинстве ситуаций. Однако, если внешний файл .js содержит в себе document.write, ваш браузер выдаст вам следующие предупреждения:

Не удалось выполнить ‘write’ в ‘Document’: невозможно выполнить запись в документ из асинхронно загружаемого внешнего скрипта, если он явно не открыт.

Один из способов обойти это — использовать Postscribe. Postscribe переопределит все переданные ему экземпляры document.write в javascript.

В контексте моего кода — который, будьте уверены, я проведу рефакторинг, чтобы сделать его более эффективным — я извлекаю свой тег script из своего div, получая outerHTML элемента, затем я передаю его в postscribe.

В этом случае postscribe принимает два аргумента; div для передачи скрипта и сам скрипт. Конечно, вы можете передать скрипт встроенным или через переменную, как я сделал в примере ниже:

 var myScript = myDiv.getElementsByTagName('script')[0].outerHTML;
postscribe('#myDiv', myScript);
  

Пожалуйста, ознакомьтесь с документацией postscribe, связанной выше, для получения инструкций по установке и дальнейшей функциональности.