1

I have an HTML definition list, and I want to use jQuery to turn that into a nested JavaScript array. What's the simplest way to do this? Thanks for your help.

My input looks like this:

<dl>
  <dt>A</dt>
   <dd>A1</dd>
  <dt>B</dt>
   <dd>B1</dd>
   <dd>B2</dd>
</dl>

I want my output to look like this:

[['A', 'A1'], ['B', 'B1', 'B2']]
0

5 Answers 5

4
var final_array = []; 

$('dl dt').each(function(){
   var dt_dds = [];   /* array to hold the dt_dds */ 
   dt_dds.push( $(this).text() );  /* push the dt */ 
   dds = $(this).nextUntil('dt'); /* get all dd's until the next dt */ 
   dds.each(function(){  dt_dds.push( $(this).text() )}); /** push all dd's into the array*/ 
   final_array.push( dt_dds ); 
})

console.log( final_array ); 

Here's a fiddle.

Sign up to request clarification or add additional context in comments.

2 Comments

[["A", "B"], ["A1", "B1", "B2"]] !== [["A", "A1"], ["B", "B1", "B2"]]
Hah you're right john, i didn't pay close attention, modified the code :-)
1

This isn't very elegant but you can iterate through the child elements of the <dl> tag, build an array for each set of <dt>/<dd> tags and .push that array into an output array:

//setup two arrays, one as a final output and one that will hold each sub-array
var output = [],
    temp   = [];

//iterate through each child element of the `<dl>` element
$('dl').children().each(function () {

    //if this element is a `<dt>` tag
    if (this.tagName == 'DT') {

        //if the `temp` array is not empty
        if (0 in temp) {

            //`.push` the `temp` array onto the `output` array
            output.push(temp);
        }

        //add the text of this `<dt>` tag to the `temp` array as the first key (erasing any data that was inside the `temp` array)
        temp = [$(this).text()];
    } else {

        //if the tag found was anything other than a `<dt>` tag (I'm assuming it's a `<dd>` tag) then `.push` its text into the `temp` array
        temp.push($(this).text());
    }
});

//make sure to add the last iteration of the `temp` array to the `output` array
output.push(temp);

//for the structure supplied in the question, the output looks like this: [["A", "A1"], ["B", "B1", "B2"]]

A demonstration of this code can be found at: http://jsfiddle.net/qkjKp/

Comments

1

You could try something like this:

var a = [];
var b = [];

var dlc = $("dl").children();

dlc.each(function (i) {
    if (this.nodeName == "DT") {
       if (b.length) a.push(b);
       b = [$(this).html()]; 
    } else {
       b.push($(this).html());   
    }
    if (i == (dlc.length-1)) {
        a.push(b);
        console.log(a);
    }
});

Comments

1

You can use .map() to do that:

var array = $('dl dt').map(function() {
  // Get the ['A1'] and ['B1', 'B2']
   var items = $(this).nextUntil('dt', 'dd').map(function() {
    return $(this).text();
  }).get();

  // Prepend the dt's value
  items.unshift($(this).text());

  // Needs to be wrapped in a second array so that .map() doesn't flatten.
  return [ items ];
}).get();

Demo: http://jsfiddle.net/LjZDt/1/

More info about that technique here: http://encosia.com/use-jquery-to-extract-data-from-html-lists-and-tables/

1 Comment

This is great, elegant, and the shortest answer posted. I ended up accepting a marginally longer approach because it struck me as a bit more readable, but I'd also mark yours as accepted if I could. Thanks, Dave.
1

nextUntil(...) will do the trick to get the proper dd's

var result = [];

$("dt").each(function() {
    var el = $(this),
        tmp = [el.text()];

    el.nextUntil("dt").each(function() {
        tmp.push($(this).text());
    });

    result.push(tmp);
});

console.log(result);

fiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.