2

I am dynamically loading a widget from another webservice that requires a script to be run immediately after it. The example uses document.write() to do this, but this does not work because it doesn't run until after the document has been closed, which means it overwrites the entire document. I am trying to load it via AJAX using pure JavaScript:

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) { // success
    eval(this.responseText);
  }
};
xhttp.open("GET", "https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js", true);
xhttp.setRequestHeader('Content-type', 'application/javascript');
xhttp.send();

but I get the following error:

XMLHttpRequest cannot load https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://example.com' is therefore not allowed access.

I was able to make it work using jQuery on my test server with this code:

$.ajax({
    dataType: "script",
    cache: true,
    url: "https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js"
});

However, I cannot use jQuery on my production server because... well... work politics.

How is jQuery accomplishing this without an error, and how can I do it in pure JavaScript?

Solution

As stated by @shabs, $.ajax adds a script tag to the document.head and then immediately removes it. I checked this by adding a breakpoint and saw it added and removed in Chrome's inspector. It appears to remove the file as soon as the current script completes regardless of what the file is. This works well for immediately invoked scripts, but I don't know how this would work with something like a library.

For a pure JavaScript implementation I used the following code:

var widgetScript = document.createElement("script");
widgetScript.async = true;
widgetScript.src = "https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js";
document.head.append(widgetScript);
widgetScript.remove();
1
  • 1
    append the script tag to the page.... Commented Aug 8, 2017 at 22:06

1 Answer 1

2

The resource in question doesn't support CORS.

This works through $.ajax because when you specify dataType: "script", jQuery actually appends a <script> tag to document.head! *

Is there a particular reason you're not just using something like <script type="text/javascript" src="https://d3gxy7nm8y4yjr.cloudfront.net/js/embed.js"></script>?

* (This is news to me! The documentation for $.ajax mentions that "script [...] requests are not subject to the same origin policy restrictions", and the source code confirms this.)

Sign up to request clarification or add additional context in comments.

1 Comment

I can't use a hard coded <script> tag is because the script is an immediately invoked anonymous function that must run every time I change the <iframe> that contains the widget.

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.