0

I have an ASP.NET MVC 4 application where a list of classes, with their full namespaces, are bound to a listbox. This generates HTML as follows:

<select id="myclasses">
  <option>Api.Domain.Interfaces.MyClass1</option>
  <option>Api.Domain.Interfaces.MyClass2</option>
  <option>Api.Domain.Interfaces.MyClass3</option>
  <option>Api.Domain.Models.MyModel1</option>
  <option>Api.Domain.Models.MyModel2</option>
  <option>Api.Infrastructure.Repositories.MyRepo1</option>
  <option>Api.Infrastructure.Repositories.MyRepo2</option>
</select>

I would like to use JavaScript/jQuery to generate a JSON representation of this HTML stored in a variable as follows:

var classes = 
[{ "text": "Api", "children": 
    [{ "text": "Domain", "children": 
        [{ "text": "Interfaces", "children": 
            [{ "text": "MyClass1" }, { "text": "MyClass2" }, { "text": "MyClass3" }]
         },
         { "text": "Models", "children": 
           [{ "text": "MyModel1" }, { "text": "MyModel2" }] 
        }]
    },
    { "text": "Infrastructure", "children": 
       [{ "text": "Repositories", "children": 
           [{ "text": "MyRepo1" }, { "text": "MyRepo2" }] 
       }]
    }]
}];

The fully qualified class names are already in a tree-like structure, so I would imagine that there should be a fairly easy way to achieve what I'm trying to do. Should I be getting the inner HTML of the element using $("#myclasses").html() and then performing string manipulations, or is there a simpler way?

08Dc91wk
  • 4,254
  • 8
  • 34
  • 67
  • Did you look http://stackoverflow.com/questions/6232753/convert-delimited-string-into-hierarchical-json-with-jquery or http://stackoverflow.com/questions/2294695/creating-a-json-tree-from-a-string-hierarchy – Michael Laffargue Jun 10 '15 at 09:40
  • Both of those convert from a JavaScript array with multiple children. Neither of them convert from HTML. I will update the question to make this more clear. – 08Dc91wk Jun 10 '15 at 09:56
  • Look my answer, not that hard to go from text to Javascript array ... – Michael Laffargue Jun 10 '15 at 10:07
  • No, there is no simpler way than using string manipulation – charlietfl Jun 10 '15 at 12:00

1 Answers1

1

Here is a try with Jquery, though you'll have an empty list of children for the last element. Could be modified if that's a problem. I added multi selection also to give a shot.

http://jsfiddle.net/c8e7kkhh/1/

$(function() {
    $("#button").click(function(){
        var output = [];
        var input = $( "#myclasses option:selected" );

        for (var i = 0; i < input.length; i++) {
            var chain = input[i].text.split(".");

            var currentNode = output;
            for (var j = 0; j < chain.length; j++) {
                var wantedNode = chain[j];
                var lastNode = currentNode;
                for (var k = 0; k < currentNode.length; k++) {
                    if (currentNode[k].text == wantedNode) {
                        currentNode = currentNode[k].children;
                        break;
                    }
                }
                // If we couldn't find an item in this list of children
                // that has the right name, create one:
                if (lastNode == currentNode) {
                    var newNode = currentNode[k] = {text: wantedNode, children:[]};
                    currentNode = newNode.children;
                }
            }
        }

        $("#result").html(JSON.stringify(output));
    });
});
Michael Laffargue
  • 10,116
  • 6
  • 42
  • 76