2

I'm using the Genius API to retrieve the lyrics for a given song and embed them within an HTML <div> tag. I'm interacting with this API using PHP, via an AJAX GET request.

In the event of a successful AJAX request, I retrieve the following HTML from my 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>

The script tag returned by the Genius API will embed the lyrics and lyric information when executed.

I'm attempting to import this HTML into my already existing <div>. In this case, the <script> portion will not be executed. I've tried to use an eval() within the 'success' function of my AJAX to dynamically execute this script, but I'm having no success:

$.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);
    }
});

I've tried to eval the:

  • .outerHTML -- The console shows this value to be: <script crossorigin="" src="//genius.com/songs/2351532/embed.js"></script>
  • .innerHTML -- Attribute appears to be empty.
  • .src -- The console shows this value to be: http://genius.com/songs/2351532/embed.js. Theeval() function errors on this with Uncaught SyntaxError: Unexpected end of input.

I feel I am potentially doing this backward. Should I execute the script from my AJAX return before I add it to the div? (The script generates quite a few embed div tags)

EDIT

With instruction from answerer Sjoerd de Wit, I attempted to create a new script tag from the source tag's src attribute, and add it via document.head.appendChild. This did not work, providing the warning:

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

2
  • eval() == evil(). Do not use it. You can read everywhere over the internet why it's bad to use it. Commented Mar 13, 2019 at 14:24
  • 1
    @MarkBaijens Noted! Commented Mar 13, 2019 at 14:25

3 Answers 3

1

You should get the src from the script tag and dynamically create and load it in your html

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

document.head.appendChild(script); 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your comment! This did not work for a script containing an embed -- please see warning that I posted in post edit.
Thanks @Mark Baijens, this explains the warning. I don't think I can refactor the script as it is provided by Genius, but I'll try postscribe as mentioned in answers. Cheers!
1

using jQuery's .html() instead of javascript's .innerHTML() will automatically evaluate scripts inside the string

so, try to change this line

//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);

into

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

1 Comment

Thanks scott - this works but I'm still getting the warning mentioned in my EDIT. However this warning seems to be a separate issue related to document.write. Accepting this as best answer in this context.
1

SOLUTION
Answering my own question.

The other answers to this question are perfectly acceptable and work in most situations. However, if the external .js file contains a document.write within it, your browser will give you the following warnings:

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

One of the ways to get around this is to use Postscribe. Postscribe will override any instances of document.write within javascript passed to it.

In the context of my code -- which, rest assured, I will refactor to make it more efficient -- I retrieve my script tag from my div by getting the outerHTML of the element, then I pass it into postscribe.

With this use case, postscribe takes two arguments; the div to pass the script to, and the script itself. Of course -- you can pass the script inline or via a variable as I have done in the below example:

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

Please see the postscribe documentation linked above for installation instructions and further functionality.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.