views:

87

answers:

7

I am using jquery and the each function but I am having trouble finding the last item in a ul list.

DATA:

<ul id="1">
     <li>1</li>
     <li>2</li>
     <li>3</li>
</ul>
<ul id="2">
     <li>1</li>
     <li>2</li>
     <li>3</li>
</ul>
<ul id="3">
     <li>1</li>
     <li>2</li>
     <li>3</li>
</ul>

I have tried multiple things but nothing is doing what I want. Here is I have tried.

var test = '{';
for (i = 1; i <= 3; i++) {
     test += i+':{';
     $('#'+i+' li').each(function(index,e){
          test += $(this).attr('id');

          // THIS IS THE PROBLEM AREA START
          if(index != $('#'+i).last()){
               test += ',';
          }
          // PROBLEM AREA END

     });
     test += '}';
     if(i != 3){
          test += ',';
     }
}
test += '}';
alert(test);

I have also tried using the "$('#'+i+':last')" but that did not do it ether.

The output I am trying to get is:

{1:{1,2,3},2:{1,2,3},3:{1,2,3}}
+1  A: 

I would recommend you create an array with your strings, then join them with a comma.

So something like this:

var arr = ["1:{1,2,3}", "2:{1,2,3}", "3:{1,2,3}"];

var str = "{" + myArray.join(",") + "}";

So, in each iteration of the each loop you'd construct a string like "1:{1,2,3}" and push it to your array.

Skilldrick
Not a complete solution, but a better answer as most others. You pointed out we should read the question instead of the title. Context matters.
GvS
@GvS - indeed. There's always a balance between answering the question directly, or solving the problem the questioner is having. Programming's all about solving problems when it comes down to it.
Skilldrick
@GvS - and I don't believe in spoonfeeding answers. I think it's best to give the outline of a solution rather than the whole thing (usually).
Skilldrick
+5  A: 

You are trying to select the last element out of the matched set (which only consists out of your ul rather than its children (which are li elements)). You need to do this on the children of the current selection:

$('#'+i).children('li').last()

or (as selector):

$('#'+i+' > li:last')
elusive
+1  A: 

2 Changes

  1. Use

    test += $(this).text();

    instead of

    test += $(this).attr('id');

  2. Change if condition to

if($(this).next().length){

Modified code

var test = '{';
for (i = 1; i <= 3; i++) {
     test += i+':{';
     $('#'+i+' li').each(function(index,e){
          // Change #1
          test += $(this).text();

          // Change #2
          if($(this).next().length){
               test += ',';
          }
     });
     test += '}';
     if(i != 3){
          test += ',';
     }
}
test += '}';
alert(test);
Chinmayee
This worked, thanks.
WAC0020
A: 

jQuery actually utilizes the .length property (http://api.jquery.com/length/) of each object. So, when you are using a selector, and you have a list of matched elements, .length - 1 will be the index of the last element. i.e.:

var test = '{';
for (i = 1; i <= 3; i++) {
     test += i+':{';
     $('#'+i+' li').each(function(index,e){
          test += $(this).attr('id'); //This is erroneous; this (ie e)'s
                                      //id is nonexistent. Do you mean .html()?

          // THIS IS THE PROBLEM AREA START
          if(index != $('#'+i+' li').length - 1){
               test += ',';
          }
          // PROBLEM AREA END

     });
     test += '}';
     if(i != 3){
          test += ',';
     }
}
test += '}';
alert(test);

Although there are more than a few problems here. If you added the class='include' to each <ul>...

var str;
$('.include').each(function (index, e) {
    str += e.attr('id') + ": {";
    e.children().each(function (cIndex, child) {
        str += child.html() + ( cIndex != e.children().length - 1 ) ? ', ' : '';
    });
    str += '}' + ( index != e.parent().children().length - 1);
});

May provide some helpful insights. Basically what you are are trying to write is a JSON serializer. You might want to check out http://flexjson.sourceforge.net/

clarkf
+1  A: 

Firstly, you're output looks like JSON code. Since you're using jQuery already, there are much easier ways to generate JSON code than building the string from scratch.

Secondly, a suggestion: If you use a classname for your <ul> tags, you won't need to mess around with a for() loop for those numeric IDs (do you really need numeric IDs? They'll bite you eventually! -- Bear in mind that IDs should be unique across the page. Plus JSON expects arrays with numeric indices to be denoted with square brackets rather than the curly braces you're using).

<ul class='mylist'>
    <li>1</li>
    ...

Then you can write code like this:

myarray=[];
$('.mylist').each(function(ulindex) {
  myarray[ulindex]=[];
  $(this).children().each(function(liindex) {
    myarray[ulindex][liindex]=$(this).text();
  })
});
$output=$.toJSON(myarray);

Code above not tested, but should be close enough to give you an idea. (note: you may need a jquery plug-in to get the toJSON() method; I can't remember)

Spudley
A: 

After re-reading your question, what you really want is a clever way to make the output, not detecting what is the last element.

You should do something like:

var rootArr = new Array();

for (i = 1; i <= 3; i++) {  
   var liArr = new Array();
   $("#" + i + " li").each(function() {
      // add code to 
      liArr.push($(this).text());
   }
   rootArr.push(i + ":{" + liArr.join(",")  + "}");
}

var result = "{" + rootArr.join(",") + "}";

(Thx to SkillDrick, for pointing in the right direction).

GvS
A: 

One of the problems is you are trying to use numbers for member names in Objects. I will eleminate this by prefixing these in the base object with "id-", and using arrays within the object.

    var out = {};    
    $("ul").each(function() {
        var ul = [];
        $(this).find("li").each(function() {
            ul.push($(this).text()); // maybe .html() ?
        });
        out."id-" + $(this).attr("id") = ul;
    });
    console.log(JSON.parse(out));

I haven't tested this, but you get the idea. Sort through each UL, and sort through each LI of each UL.

Should output:

{"id-1": [1,2,3], "id-2":, [1,2,3], "id-3":[1,2,3]}
Martin
use `[]` instead of `.` for array members when the key is a dynamic value. i.e. `out["id-" + $(this).attr("id")] = ul;`
Protron