1

I'm working on something at the minute that is giving me a lot of grief. Basically I'm using bootstrap and jQuery to design a webpage and its got to the point where I'm sending JSON over the network to save to a hibernate back end. All of the objects are set up fine and are working, but I'm looking for a "better" solution to generate the array than the one I've currently got. The relationships are like this:

Parent -> Child -> GrandChild
      `-> Child -> GrandChild

All of the mappings are one to many relationships, and the way the divs are laid out on the screen is basically like this:

<div id="left">
    <div id="parent"></div>
    <div id="Child"></div>
    <div id="GrandChild"></div>
</div>
<div id="right">
    <div id="Child"></div>
    <div id="GrandChild"></div>
</div>

(again you can have many "Child" divs, and many "GrandChild" divs between each "Child" div, and the same for the right side - the nesting actually goes deeper than this, but if I can figure out this to start with then I can adapt it). What I am doing at the minute is when the user presses "Save" is to build the tree by renaming the name element of every input in every div in order for the mapping to work when I seriallize the whole page. What I am finding is that this requires a horrendous function to essentially loop through all of the divs and reset counters whenever a new parent object is encountered. For example assume (on the left side):

<div id="left">
    <div id="Parent"></div>
    <div id="Child"></div>
    <div id="GrandChild"></div>
    <div id="GrandChild"></div>
    <div id="GrandChild"></div>
    <div id="Child"></div>
    <div id="GrandChild"></div>
</div>

My javscript would essentially do this (pseudocode):

childCounter = -1;
grandChildCounter = -1;

for each div {
   if div == Parent { skip };
   if div == Child { childCounter +=1; grandChildCounter = -1; childDiv.name = childArray[childCounter] };
   if div == GrandChild { grandChildCounter += 1; grandChildDiv.name = childArray[childCounter].grandChildArray[grandChildCounter] };
}

Obviously with more nested levels this kind of code just gets insane... so I've been trying to generate the array recursively by building everyone's children beforehand and appending it to the object as an array - but I run into the same issue of needing manually traverse down the nest just to append the array of children to their correct parent. Either way seems cumbersome and produces really sloppy code - I am new to javascript and jQuery so I do wonder if I'm going about this whole thing the wrong way and am looking for some advice.

It's worth noting that the whole thing is dynamic, and the addition of new divs in the correct order based on pressing buttons on the page already works perfectly. The tree HAS to be generated when the user presses save.

I'm also sorry about the lack of proper code but the work isn't at home. Thanks in advance

4
  • 2
    are grandchildren nodes not nested in the children nodes? If not nested, how do you tell a grandchild belongs to which child? Commented Nov 25, 2015 at 23:05
  • And... is there a reason not to nest them properly in the DOM when the user adds them? If you're writing all of that JS because of a CSS problem... Commented Nov 25, 2015 at 23:16
  • @ochi I wondered the same. Looks like a grandchild always belongs to the last instance of a child. Commented Nov 25, 2015 at 23:17
  • yes grandchildren are nested within the children nodes and that's how I want the JSON to be, but they are just sibling div's within the html - the issue is "mapping" the html structure into its proper JSON form. Commented Nov 25, 2015 at 23:25

2 Answers 2

1

Still not quite sure why it's not nested within the DOM to begin with but you can skip the mapping/looping/counter headache by nesting it before you create your JSON object.

Note: I changed the IDs to classes since a page can only have one instance of a given ID.

$(document).ready(function(){
     $('.Child').each(function(){
       $(this).nextUntil('.Child', '.GrandChild').appendTo(this);
     });  
  
    //now it's nested... run json generating code here
});
.GrandChild { color: blue;}
.Child .GrandChild { color: red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="left">
<div class="Parent">P</div>
<div class="Child">C1</div>
<div class="GrandChild">GC1a</div>
<div class="GrandChild">GC1b</div>
<div class="GrandChild">GC1c</div>
<div class="Child">C2</div>
<div class="GrandChild">GC2a</div>
<div class="Child">C3</div>
<div class="GrandChild">GC3a</div>
<div class="GrandChild">GC3b</div>
</div>

If you don't want to mess with the DOM presented to the user, you can clone the entire thing, hide it, do the transformation and delete it until the next time they hit save.

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

2 Comments

It's not nested like that because it messes up the layout to the user - I'm using bootstrap to show these things in a certain way and I can't have the divs be inside one another (even though that's how they're supposed to be modelled). What you mentioned about cloning and then re-ordering in the fashion here looks promising - but I still need to generate the JSON such that all of the child divs for a parent are an array within the parent
@Offbeat That's what I suspected. Why not post an example of what you have so far? Fixing the actual problem (CSS) is going to be way less headache in the long run.
0

Adapting the code from the answer provided previously by @Will you can clone the DOM, hide it and do your thing that generates the JSON string using the clonedDom

Credit to @Will

$(document).ready(function() {
  var clonedDom;
  $("#save").on('click', function() {
    // clone dom and hide it
    clonedDom = $('#left').clone();
    $(clonedDom).hide();

    // do the nesting
    $(clonedDom).find('.Child').each(function() {
      $(this).nextUntil('.Child', '.GrandChild').appendTo(this);
    });

    // log both doms (to see how different they are, you can remove this later)
    console.log(clonedDom.children());
    console.log($("#left").children());
  });

  //now it's nested... run json generating code here on the clonedDom
});
.GrandChild {
  color: blue;
}
.Child .GrandChild {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="left">
  <div class="Parent">P</div>
  <div class="Child">C1</div>
  <div class="GrandChild">GC1a</div>
  <div class="GrandChild">GC1b</div>
  <div class="GrandChild">GC1c</div>
  <div class="Child">C2</div>
  <div class="GrandChild">GC2a</div>
  <div class="Child">C3</div>
  <div class="GrandChild">GC3a</div>
  <div class="GrandChild">GC3b</div>
</div>

<button id='save'>save</button>

Comments

Your Answer

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