2

I have an ajax POST request, this request comes with html with <script src=""> tags referencing external js files, when I insert this html in DOM the JS are not loaded, what I'm doing wrong? I can remember see this working loading the external script1 and script2 without problems.

Request:

$.ajax({
    type: 'POST',
    dataType: 'xml/html',
    cache: false,
    url: "/html/with/scripttags",
    data: {somedata:'value'},
    success: function(data) {
      $('body').append(data)
    }
  });

Content loaded:

<link rel="stylesheet" media="all" href="http://domain.com/application.css" />
<script src='http://domain.com/script.js' type='text/javascript'></script>
<script src='http://domain.com/script2.js' type='text/javascript'></script>
<script type='text/javascript'>alert('executed')</script>
<div>BLAALBLABLAB</div>

However the alert in script tag is is executed without problems and the application.css external file is loaded without problems. Looks like jQuery doesn't load the files, I also check the network tab..

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Javier del Saz
  • 846
  • 1
  • 9
  • 16
  • It's my guess but perhaps dataType should be 'script'. Also, this jQuery method would be helpful if I understand the problem correctly - https://api.jquery.com/jquery.getscript/. Also, have a look at similar question http://stackoverflow.com/questions/950087/include-a-javascript-file-in-another-javascript-file. – Karolis Ramanauskas Apr 26 '16 at 14:27
  • no, that's normal behaviour – n00dl3 Apr 26 '16 at 14:27
  • @KarolisRamanauskas you misunderstand - the "Content loaded" section in the question shows the HTML code that the OP is loading. He does not want to load just a particular script; he wants to load HTML that contains ` – Pointy Apr 26 '16 at 14:28
  • Are you async loading both your CSS and your JS for the page? If so, try using blocking on the JS load for any script that must act on the DOM on load completion. Load the JS on the callback so that you are sure your DOM is fully loaded before you try applying your scripting to it. With Async alone you cant really guarantee which file is going to make it though the web to your client first. So if the script makes it first and tries to act on DOM elements that have not made it yet - your going to not only throw errors - but the rest of the loading of the page is going to fail. – Korgrue Apr 26 '16 at 14:29
  • @Pointy Oh right, I got confused with the question, thanks! – Karolis Ramanauskas Apr 26 '16 at 14:30
  • 1
    @Korgrue no. The OP is trying to load a *single* block of HTML. That fetching the content is asynchronous is irrelevant, as the failure is happening *after* the ajax call completes. – Pointy Apr 26 '16 at 14:32
  • @Pointy Ohhhh. His question was oddly worded. My bad. – Korgrue Apr 26 '16 at 14:32
  • Javier what version of jQuery are you using? – Pointy Apr 26 '16 at 14:32
  • 2
    Just wondering: How are you verifying if external script.js is not getting loaded ?...Have you tried loading in some test page? – Mahesh Chavda Apr 26 '16 at 14:40
  • Should `dataType` be `html`? What is purpose of including `xml` at `dataType`? Multiple data types should be separated by space. There is not an `xml/html` MIME type. Can you create a plnkr http://plnkr.co to demonstrate ` ` ? What does `script.js` and `script2.js` do? – guest271314 Apr 26 '16 at 14:46
  • 1
    _"I also check the network tab"_ Are `script.js`, `script2.js` requested? – guest271314 Apr 26 '16 at 14:52

2 Answers2

2

That's jQuery's normal behaviour, if you want to include your scripts, you need to parse the html and add them manually.

Bad news: you can't even select script tags in strings with $()...

I didn't test that, but this quick and dirty example should work:

function createGetScriptCallback(url) {
  return function () {
    return $.getScript(url);
  }
}
$.ajax({
  type: 'POST',
  dataType: 'xml/html',
  cache: false,
  url: "/html/with/scripttags",
  data: {
    somedata: 'value'
  },
  success: function (data) {
    var parser, doc, scriptsEl, callbacks;
    parser = new DomParser();
    doc = parser.parseFromString(data, "text/html")
    scriptsEl = doc.querySelectorAll("script[src]");
    callbacks = []
    for (var i = 0; i < scriptsEl.length; i++) {
      callbacks.push(createGetScriptCallback(scriptsEl[i].getAttribute("src")));
    }
    $.when.apply($, callbacks)
      .fail(function (xhr, status, err) {
        console.error(status, err);
      });
    $('body').append(data);
  }
});

But you should not depend on the html to load your scripts.

edit: less dirty code (inspired by @guest271314 's answer)

n00dl3
  • 21,213
  • 7
  • 66
  • 76
0

The simplest approach would be to remove

<script src='http://domain.com/script.js' type='text/javascript'></script>
<script src='http://domain.com/script2.js' type='text/javascript'></script>

from "/html/with/scripttags", then call

$.when($.getScript('http://domain.com/script.js')
      , $.getScript('http://domain.com/script2.js'))
.fail(function(jqxhr, textStatus, errorThrown) {
  console.log(textStatus, errorThrown)
})

at $.ajax() success.

See also $.ajax() at dataType

multiple, space-separated values: As of jQuery 1.5, jQuery can convert a dataType from what it received in the Content-Type header to what you require. For example, if you want a text response to be treated as XML, use "text xml" for the dataType. You can also make a JSONP request, have it received as text, and interpreted by jQuery as XML: "jsonp text xml". Similarly, a shorthand string such as "jsonp xml" will first attempt to convert from jsonp to xml, and, failing that, convert from jsonp to text, and then from text to xml.

"xml/html" is not a valid MIME type or expected parameter to dataType

guest271314
  • 1
  • 15
  • 104
  • 177