views:

36

answers:

1

I have a problem building a HTML table from the following JSON

[ 
  { 
    "size" : 167, 
    "price" : 453400, 
    "type" : "Neubau", 
    "children" : false
  }, 
  { 
    "size" : 167, 
    "price" : 453400, 
    "type" : "Neubau", 
    "children" : false
  }, 
  { 
    "size" : 167, 
    "price" : 453400, 
    "type" : "Neubau", 
    "children":[
      { 
        "size" : 167, 
        "price" : 453400, 
        "type" : "Neubau", 
        "children" : false
      },
      { 
        "size" : 167, 
        "price" : 453400, 
        "type" : "Neubau",
        "children" : false
      }  
    ]
  }, 
  { 
    "size" : 167, 
    "price" : 453400, 
    "type" : "Neubau", 
    "children" : false
  }
]

when fed into these functions

function getRowHTML(dataObject, type) {
  cycles = dataObject.length;
  var markup = '';
  for (var i=0; i < cycles; i++) {
    // different markup for each line
    switch (type) {
      case 'size':
        markup += ' <td>' + dataObject[i].size + '</td>';
        break;
      case 'price':
        markup += ' <td>' + addDots(dataObject[i].price) + '&euro; </td>';
        break;
      case 'type':
        markup += ' <td>' + dataObject[i].type + '</td>';
        break; 
    }

    // Check if an object has children and insert children HTML as well
    if (dataObject[i].children) {
      markup += getRowHTML(dataObject[i].children,type);
    }
  }
  return markup;
}

function getHTML(data) {
  var markup = '<table>';

  markup += '<tr class="odd">' + getRowHTML(data,'size') + '</tr>';
  markup += '<tr class="even">' + getRowHTML(data,'price') + '</tr>';
  markup += '<tr class="odd">' + getRowHTML(data,'type') + '</tr>';


  markup += '</table>';

  return markup;
}

Everything works fine until I add the check for children and the corresponding recursive function call.

Then the result are the first two objects and the children but the last one won't be in the table. Any ideas?

+1  A: 

You have forgotten the var on the cycles variable, making it an accidental global. The inner call to getRowHTML overwrites the value of the global cycles in the outer call, making the outer loop end early.

Note you also have HTML-injection problems if any of the properties can contain HTML-special characters. You should HTML-escape any content being inserted into an HTML string. Or, to avoid having to think about that, use DOM methods to create the table instead. eg.

function fillRow(row, items, property) {
    for (var i= 0, n= items.length; i<n; i++) {
        var item= items[i];
        var s= item[property];
        if (property==='price')
            s= addDots(s)+'\u20Ac'; // €
        row.insertCell(-1).appendChild(document.createTextNode(s));
        if (item.children)
            fillRow(row, item.children, property);
    }
}

function makeTable(data) {
    var table= document.createElement('table');
    var properties= ['size', 'price', 'type'];
    for (var i= 0, n= properties.length; i<n; i++) {
        var row= table.insertRow(-1);
        row.className= i%2===0? 'odd' : 'even';
        fillRow(row, data, properties[i]);
    }
    return table;
}
bobince
Thanks, I've missed the global. The actual code is a lot more complex and the JSON will come from a secure source. But thanks for the hint as well.
dantz