使用JQuery的HTML表单中的分层数据

I have very big hierarchical tree objects and i'm building a interactive html form with them. Here is an little abstract:

enter image description here

As you can see, there are different item types. D can be a direct child of the prime father A or a child of B or C. C could also be a direct child of A etc. There is no real order in the item types.

In my form the user can select or deselect any item. So when you select an item B, I want to automatic select all his descendants and A should show a half state indicating that some of the items are selected but not all.

So I'm dealing with 3 states: not selected, completly selected and half selected. (Only D can have 2 states, cause its always the last item if present)

Since there are no nested arrays in JS I should use objects for this or? So i write functions like: check in which object the item is, select all this descendants too, then half select all the ancestors, or fully select the ancestors if all his descendants are selected. etc.

I have all this data in my DB with the closure tables method. My problem is that I have no idea how to deal with this in JavaScript/JQuery.

Thank you for your time!

EDIT: Thank you very much for your help! I never tried prototype JS but I get the idea, and will do that with JQuery.

Here a image relating to the state "half selected":

enter image description here

Yes, you should use Objects, but it's concerning that you ask this question. Perhaps you should look into a pre-built solution like JSTree. The state is either

  • selected
  • not selected

The state you call half-selected is inferred from the children of the node. You haven't specified enough information to implement that.

"use strict";

var NodeObj = function (name, selected) {
  this.state = selected || false;
  this.name = name;
  this.nodeChildren = [];
}

NodeObj.prototype.add_child = function (name) {
  var child = new NodeObj(name);
  this.nodeChildren.push( child );
  return child;
}

NodeObj.prototype.select = function () {
  this.state = true;
  this.nodeChildren.forEach( function(e) { e.select() } );
}
NodeObj.prototype.unselect = function () {
  this.state = false;
  this.nodeChildren.forEach( function(e) { e.unselect() } );
}

var n1 = new NodeObj(null, 'ROOT');
var a = n1.add_child('A');
var d = n1.add_child('D');

var b1 = a.add_child('B1');
var b2 = a.add_child('B2');
var c1 = b1.add_child('C1');
var c2 = b1.add_child('C2');
var c3 = b2.add_child('C3');
var c4 = b2.add_child('C4');
var d1 = c1.add_child('D1');
var d2 = c4.add_child('D2');
var d3 = c4.add_child('D3');

b2.select();
console.log( d1.state );
console.log( n1 );