Replace one html tag with another

Whenever an ajax post is made, a full page with html 4 doctype is returned but I want to display that page on the current one. There are also some scripts in the head tag of that returned page that are wrapped in document.ready, which means my options are limited to $.parseHTML i.e. they need to be executed whenever the new document is fully loaded. Below is the current code I’m using

$.post('tet.php', {key: JSON.stringify(payload)}, function(res) {

// res truly returns a full page
 var newPage = $.parseHTML($.trim(res), null, true).find(function (e) {
 try {
  return e.matches('#container'); // this is the one tag I'm interested in
 }
 catch (e) {
  return false;
 }
 });

 $('body').replaceWith(newPage); // errors originate from this line
});

Now the code keeps throwing all sorts of errors revolving around lack of documentFragment or missing clientWidth etc. How do I go about picking out that element and loading into the DOM while still being able to execute the script in its head tag? If that isn’t possible, then how can I remove the current document and install the returned one?

If you are loading a page dynamically from a server then you can target just one element from the loaded page using the following form with .load()

$(selectorWhereToShowNewData).load('pagePath selectorForElementFromNewData');

Ref: https://stackoverflow.com/a/3754166/1136887

Otherwsie, you can filter the returned page for the elements you are looking for:

<!DOCTYPE HTML>
<html lang="en">
  <head>
    <meta chraset="utf-8">
    <title>Ajax stuff</title>
  </head>
  <body>

    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script>
      const doc = `
        <!DOCTYPE html>
        <html lang="en">
        <head>
          <meta charset="UTF-8">
          <title>Document</title>
        </head>
        <body>
          <p>This is what I want</p>
        </body>
        </html>
      `;

      const p = $(doc).filter('p');
      $("body").append(p);
    </script>
  </body>
</html>

First, I can’t load because the method uses get method by default. If you read my code you’ll see I’m trying to make a post request.

I cannot also use the 2nd option you gave–filter. First it throws error “cannot create documentFragment of null”. Second, even if it didn’t, the response page is also dynamic and has some scripts that change its contents. So if I attach that page fragment alone, I’ll miss out on the scripts and their goodies. That’s why I need the page whole or at least with the scripts in its head.

Executing dynamic scripts from a page you got from a POST request doesn’t sound quite right to me. Why not just return a proper JSON response instead, and have your existing script deal with the data?

Now you could use a DOMParser to parse the response, find the desired script, and insert its text content into a newly created script element on the page:

$.post('tet.php', {/* ... */}, data => {
  const parser = new DOMParser()
  const doc = parser.parseFromString(data, 'text/html')
  const script = $(doc).find('script').text()

  $('<script>').appendTo('body').text(script)
})

But really, I’d suggest to find a different solution than loading and executing such “goodies” with each AJAX response. That this textContent workaround is even necessary should be telling enough.

2 Likes

Is it OK I ditch Ajax all together and create a form on the fly and submit. So instead of parsing the new page (and since we’d be exiting the executing script anyway) we abandon the current page and glide over to the response page

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.