NorthFork
NorthFork

Reputation: 665

Use jQuery to update attribute of HTML string in each() loop

I have an HTML string that I'm trying to update attributes on, but I can't seem to see the changes. Here is a simplified example:

var source = '<html><head></head><body><img src="abc" /><img src="abc" /></body></html>';

$(source).filter('img').each(function () {
    $(this).attr('src', '123');
});

// At this point if I look at source in a debugger 
// I'd expect to see the src attributes as all being 
// '123', but I still see them all as 'abc'. 

How should this be written so that source is updated with the changes?

Upvotes: 1

Views: 1069

Answers (2)

THEtheChad
THEtheChad

Reputation: 2432

Jquery uses an array of elements behind the scenes. In your example, this array looks something like ['html'] (in pseudo code), meaning that you only have one element (html). When you use filter, it takes this array removes all the elements that don't match your selector. For example, if you had a list of elements like this: ['div', 'img', 'div', 'img'], using your original code

var only_images = $(source).filter('img');

would result in ['img', 'img'] having removed all of the 'div' tags. That being said, since your example only has one element ['html'], the result ends up being an empty array [].

The find method, however, searches all of the descendents for a match. That means every element in your string is matched against img (except for the original parent element html).

I don't know that I've done a good job of explaining it, but what you ultimately need to do is switch your code up and start using the find method. Example code below:

var source = '<html><head></head><body><img src="abc" /><img src="abc" /></body></html>';

$(source).find('img').each(function () {
    $(this).attr('src', '123');
});

Upvotes: 2

PSL
PSL

Reputation: 123739

This should work fine, but you need to reassign the html to the string back again or append to the DOM as the change doesn't make any effect here as selector is not a DOM element but a string.

var source = '<html><head></head><body><img src="abc" /><img src="abc" /></body></html>';
     var $source = $(source);
     $source.filter('img').each(function () {
             $(this).attr('src', '123');
        });
    console.log($source.wrapAll($('<div/>')).parent().html()); 
    //or
    source = $source.wrapAll($('<div/>')).parent().html();

Fiddle

Or just do

 $(source).filter('img').attr('src', function () {
      return '123';
   }).appendTo('someselector');

Demo

note instead of using an explicit .each you can make use of function argument for attr as in the second example.

Upvotes: 2

Related Questions