Question

I'm pretty sure there is a way to shorten this, but I don't know how.

img[1] = $('#img1').attr('src');
img[2] = $('#img2').attr('src');
img[3] = $('#img3').attr('src');
img[4] = $('#img4').attr('src');

title[1] = $('#title1').text();
title[2] = $('#title2').text();
title[3] = $('#title3').text();
title[4] = $('#title4').text();

desc[1] = $('#description1').attr('value');
desc[2] = $('#description2').attr('value');
desc[3] = $('#description3').attr('value');
desc[4] = $('#description4').attr('value');

url[1] = $('#url1').attr('value');
url[2] = $('#url2').attr('value');
url[3] = $('#url3').attr('value');
url[4] = $('#url4').attr('value');

The arrays have already be created, i just decided to exclude them from this becuase it's not really needed here. I'm just basically pulling some data the DOM.

Was it helpful?

Solution

for(i=1;i<=4;i++) {
   img[i] = $('#img'+i).attr('src');
   title[i] = $('#title'+i).text();
   desc[i] = $('#description'+i).attr('value');
   url[i] = $('#url'+i).attr('value');
}

OTHER TIPS

You could simplify with it a for loop e.g.

for(i = 1; i < 5; i++) {
      img[i] = $('#img' + i).attr('src');
      title[i] = $('#title' + i).text();
      desc[i] = $i'#description' + i).attr('value');
      url[i] = $("#url' + i).attr('value');
}

You can do

img = $('#img1, #img2, #img3, #img4')
            .map(function(){ return this.src; })
            .get();

title = $('#title1, #title2, #title3, #title4')
            .map(function(){ return $(this).text(); })
            .get();

desc = $('#description1, #description2, #description3, #description4')
            .map(function(){ return this.value; })
            .get();

url = $('#url1, #url2, #url3, #url4')
            .map(function(){ return this.value; })
            .get();

but better yet to add a class to each group and use that to target the elements..

img = $('.img')
          .map(function(){ return this.src; }) 
          .get();

title = $('.title')
            .map(function(){ return $(this).text(); })
            .get();

desc = $('.description')
           .map(function(){ return this.value; })
           .get();

url = $('.url')
          .map(function(){ return this.value; })
          .get();

stretching it

Now if you wanted to automate this even more you could do

jQuery.fn.propAsArray = function(property){
   return this.map(function(){
       if (jQuery.fn[property]){
            return $(this)[property]();
       } else {
           return $(this).prop(property);
       }
   }).get();
}

and use it like this

img = $('.img').propAsArray('src');
title = $('.title').propAsArray('text');
desc = $('.description').propAsArray('value');
url = $('.url').propAsArray('text');

This would do the same:

for (var i = 1; i <= 4; i++) {
  img[i] = $('#img' + i).attr('src');
  title[i] = $('#title' + i).text();
  desc[i] = $('#description' + i).attr('value');
  url[i] = $('#url' + i).attr('value');
}
var data = new Array();
for (var i=1; i<5; i++) {
    data[i-1] = {
        img:   $('#img' + i).attr('src'),
        title: $('#title' + i).text(),
        desc:  ${'#description' + i).attr('value'),
        url:   $('#url' + i).attr('value')
    };
}

First things first, we'll use just your images for example.

Add a class name to all the images that is the same, like "my-images".

Then use the images class name to call on each image in one jQuery call and do what you need too.

Example

$(".my-images").each(function(i) {
    //    i is an integer representing the elements index
    //    Here you can manipulate this element all you need, add classes, 
    //        add inner elements, remove items, change properties...
    //    
    //    below i'm simply console loggin the images existing src link
    console.log( $(this).attr("src") );
    //    or to set the src from a matching array of links
    $(this).attr("src", araUrls[i]);
});

Or you could use those for loops everyone else is suggesting, and manipulate the data all at once with possibly more complication. However, jQuery designed the .each method just for iterating over multiple elements with ease and being able to manipulate each element with precision.

In the interest of doing something different that was data driven rather than code driven here's another approach.

You can also use this utility function to retrieve any kind of data from sequential identifiers and to specify more objects with different data to retrieve, you just add a new row to the table.

function getDataFromDom(spec) {
    var item;
    for (var i = 0; i < spec.length; i++) {
        item = spec[i];
        for (var j = item.start, stop = item.last; j <= stop; j++) {
            item.dest[j] = $(item.selBase + j)[item.method](item.arg);
        }
    }
}
var whatData = [
    {selBase: "#img", method: "attr", arg: "src", first: 1, last: 4, dest: img},
    {selBase: "#title", method: "text", arg: undefined, first: 1, last: 4, dest: title},
    {selBase: "#description", method: "attr", arg: "value", first: 1, last: 4, dest: desc},
    {selBase: "#url", method: "attr", arg: "value", first: 1, last: 4, dest: url}
];

getDataFromDOM(whatData);

You just fill in the various parameters for each object type in the table (selector base, jQuery method name to call, arg for that method, first number to get, last number to get and destination array to store the data) and the function just iterates through the table operating on each type of object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top