0

I'm curious about the effects of the following scenarios:

Suppose I'm defining a jQuery click event, for example

$(function()
{
    $('.someElement').click(function() { /*do something*/ };
};

which gets loaded in some arbitrary HTTP GET request.
But this .someElement does not initially exists in the DOM when requesting.

Now if I also have an asynchronous AJAX call which inserts some piece of html that does have this .someElement defined, for example

$.ajax(
{
    //options omitted for readability
    success: function(responseData)
    {
        $('#elementToInsert').html(responseData);
    }
});

loads and inserts <div class="someElement"></div> into the page.
It seems that when clicking on the .someElement element, the script in the jQuery click event gets executed.

It somehow bugs me that this works. Would someone explain me why this works?

Also imagine the next scenario:

As in the previous example, I'm requesting the same arbitrary HTTP GET. But in this request, the click event is not included. The same ajax call is included though.

Now the html in the responseData looks like this

<div class="someElement"></div>
<script>
    $(function()
    {
        $('.someElement').click(function() { /*do something*/ };
    };
</script>

When I click on .someElement, I get the exact same behavior as in the first scenario. This bugs me even more, so could someone also explain to me why this works?

Some notes:

  • The responseData that gets inserted into the DOM, would be somewhere before the jQuery library.
  • I don't think it should matter which server side framework is used, but in my case it would be ASP.NET MVC 5.
  • These scenarios are tested in the most recent versions of the following browsers: IE, Firefox, Chrome.

To summarize my question: How is it possible that the mentioned scenarios works (e.g. that the jQuery gets executed)?

P.S. The funny thing is that in the answer for this question, it's explained that

JavaScript inserted as DOM text will not execute.

while in my case it is executed.
It also refers to another question that explains that eval() has to be called in order to execute javascript.
Also this article explains the opposite of my scenarios and mentions the use of eval().

Community
  • 1
  • 1
QuantumHive
  • 5,613
  • 4
  • 33
  • 55

1 Answers1

2

What you're seeing is the expected behaviour.

If you load HTML containing script tags, those script tags will be executed in some cases.
For instance if the dataType is html or the Content-type header is set in such a way on the server that jQuery parses it as HTML, the documentation states

"html": Returns HTML as plain text; included script tags are evaluated when inserted in the DOM.

In many cases, where the dataType is not set, and there are no headers or mime type for jQuery to infer the type of data loaded, the default will most likely be text, where no parsing will be done, and no scripts will be executed

"text": A plain text string

Even jQuery load() has this behaviour now, and the documentation explicitly states that

When calling .load() using a URL without a suffixed selector expression, the content is passed to .html() prior to scripts being removed. This executes the script blocks before they are discarded.

So yes, jQuery will execute script blocks in HTML content gotten with ajax calls

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • IIS Express is used in my test cases (with ASP.NET MVC 5 as mentioned) and while inspecting the network tab in the developer tabs of the browser, the content type is `text/html`. So because the server adds the `text/html` in the response header's content-type, the browser can understand and evaluate the javascript? – QuantumHive Oct 05 '16 at 15:22
  • 1
    Yes, because the correct content type is set, jQuery is able to infer the data type, even when the `dataType` option is not set, and parse the content as HTML and execute the script tags. – adeneo Oct 05 '16 at 15:24