1

I am working on upgrading some old software that was using jQuery version 1.7.2. I have upgraded this to version 1.12.1 due to some new plugins that have been added and require a newer version of jQuery.

There is however loads of jQuery that uses the jQuery(htmlString) format, for example:

  var html = $("<div>");

  // Prepare the <div> of comments
  $.each(data.comments, function() {
      console.log(this);
    html.append(
      $("<div>").attr("class", "comment").html(
        $("<div>").attr("class", "comment-profile-pic").html("").after(
          $("<div>").attr("class", "comment-text").html(
            $("<h1>").html(
              this.full_name + " at " + this.started_datetime
            ).after(
              $("<p>" + this.text + "</p>")
            )
          )
        )
      )
    );
  });

It looks like $(htmlString) was depreciated in version 1.9 and reading the upgrade guide at https://jquery.com/upgrade-guide/1.9/#jquery-htmlstring-versus-jquery-selectorstring it states the format for recognising if html is passed into the selector has changed however it also says:

When the jQuery Migrate plugin is used, it will use the old rules for determining if the string passed to $() "looks like HTML".

I have attached the jQuery migrate plugin version 1.4.1 but it doesn't seem to have made any difference and will still not recognise HTML in a selector.

EDIT: I have tried reverting jQuery to version 1.8.0 and it works as expected, but then version 1.9.0 breaks it. This means it is definitely an issue with the upgrade to v 1.9.

Also after doing further tests i have realised that passing html into a selector does work when you do something like $("<div>").attr("class", "comment") but does not work when you nest as in the above example.

Is anyone aware of how to get around this issue without re-writing all of the code that passes HTML into a selector?

4
  • 1
    There is no issue here - your code is fine. If you read the upgrade guide you'll see that this is only an issue if the html string does not start with a < character: As of 1.9, a string is only considered to be HTML if it starts with a less-than ("<") character. The Migrate plugin can be used to restore the pre-1.9 behavior. If a string is known to be HTML but may start with arbitrary text that is not an HTML tag, pass it to jQuery.parseHTML() which will return an array of DOM nodes representing the markup Commented Oct 11, 2017 at 16:12
  • did you clear cache of your browser?
    – Tien
    Commented Oct 11, 2017 at 16:12
  • @RoryMcCrossan I have reverted jQuery to v1.8 and it works then on v1.9 it doesn't work so its definitely a problem with the upgrade.
    – SamBremner
    Commented Oct 11, 2017 at 16:22
  • The issue is most likely due to how you're providing a jQuery object to html(). I've added an answer for you below Commented Oct 11, 2017 at 16:22

1 Answer 1

1

If you read the upgrade guide you'll see that this is only an issue if the html string does not start with a < character:

As of 1.9, a string is only considered to be HTML if it starts with a less-than ("<") character. The Migrate plugin can be used to restore the pre-1.9 behavior. If a string is known to be HTML but may start with arbitrary text that is not an HTML tag, pass it to jQuery.parseHTML() which will return an array of DOM nodes representing the markup.

That being said, you should use addClass(), not attr('class', 'foo'), and you really shouldn't pass a jQuery object to the html() method. If you check the documentation you will see that it accepts a HTML string or a function.

You should use one of the element insertion methods instead, such as append(), insert(), insertBefore() etc., something like this:

var data = {
  comments: [{
    text: 'foo1',
    full_name: 'name1',
    started_datetime: 'started1'
  },{
    text: 'foo2',
    full_name: 'name2',
    started_datetime: 'started2'
  }]
}

var $parent = $("<div>").appendTo('body');

$.each(data.comments, function() {
  var $comment = $("<div>").addClass('comment').appendTo($parent);
  var $profilePic = $("<div>").addClass('comment-profile-pic').appendTo($comment);
  $("<div>").addClass('comment-text').html(`<h1>${this.full_name} at ${this.started_datetime}</h1><p>${this.text}</p>`).insertAfter($profilePic);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

1
  • Thanks for your answer Rory. The thing is i'm trying to update the application and there is code like this all through it which was written by a previous dev. I really wanted to avoid having to go through and manually update it all. It may even be that passing an object into the html() method is what is depreciated in v1.9 but there is no reference that i can see to that in the upgrade doc so maybe the previous dev exploited a bug that was fixed in v1.9?
    – SamBremner
    Commented Oct 11, 2017 at 16:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.