Search code examples
javascriptjqueryarrayscasperjs

Create array, grouping based on child elements


I have this html:

<select id="this_id">
 <option value="0" class="empty-item">Choose Type</option>
 <optgroup label="FirstGrouping"></optgroup>
 <option value="2">Thing1</option>
 <optgroup label="SecondGrouping"></optgroup>
 <option value="8">Thing4</option>
 <option value="4">Thing3</option>
 <optgroup label="ThirdGrouping"></optgroup>
 <option value="7">Thing8</option>
 <option value="5">Thing9</option>
</select>

What I am trying to do is to create an array that would look like this:

"data": [{
    "Label": "FirstGrouping",
    "Options": ["Thing1"]
}, {
    "Label": "SecondGrouping",
    "Options": ["Thing4", "Thing3"]
}, {
    "Label": "ThirdGrouping",
    "Options": ["Thing8", "Thing9"]
}]

There is no given ordering of optgroup and option elements. So basically I need to group first optgroup and the following options elements in first object inside data array. Where "Label" is optgroup and "Options" are all the option elements before the next following optgroup element. Second object inside data has next optgroup as its "Label" and "Options" are the following option elements before the following optgroup element. And so on.

If optgroup would wrap option elements, then I could do something like:

var yearz = [];
var yearz2 = $('#this_id');
yearz2.each(function() {
    var thelabel = $(this).attr('label');
    var lengthch = $(this).children().length;
    var thisch = $(this).children();
    var theobj = [];
    var alls = [];
    for (var i = 0; i < lengthch; i++) {
        alls.push({
            "Value": thisch.eq(i).val(),
            "Text": thisch.eq(i).text()
        });
    }
    theobj = {
        Label: thelabel.trim(),
        Options: alls
    };

    yearz.push(theobj);
});

But ´optgroup´ does not wrap option elements. Is there any clever way to do it? Best Regards


Solution

  • You could use this ES5 code:

    var data = [];
    var elems = document.getElementById('this_id').children;
    for (var i=0; i<elems.length; i++) {
        var el = elems[i];
        if (el.tagName === 'OPTGROUP') {
            data.push({ label: el.getAttribute('label'), options: []});
        } else if(el.tagName === 'OPTION' && data.length) {
            data[data.length-1].options.push(el.textContent);
        }
    }
    console.log(data);
    <select id="this_id">
     <optgroup label="FirstGrouping"></optgroup>
     <option value="2" style="text-indent: 10px;">Thing1</option>
     <optgroup label="SecondGrouping"></optgroup>
     <option value="8" style="text-indent: 10px;">Thing4</option>
     <option value="4" style="text-indent: 10px;">Thing3</option>
     <optgroup label="ThirdGrouping"></optgroup>
     <option value="7" style="text-indent: 10px;">Thing8</option>
     <option value="5" style="text-indent: 10px;">Thing9</option>
    </select>