2013-06-19 2 views
4

У меня есть объект, как показано ниже:Генерировать таблицу из данных объекта

var obj = { 
    a : { 
     x : 1, 
     y : 2, 
     z : 3 
    }, 
    b : { 
     x : 1, 
     y : 2, 
     z : 3 
    } 
} 

с ним, я хотел бы генерировать следующую таблицу. Формат предъявляется ниже

http://jsfiddle.net/gD87t/

Я пытаюсь получить элементы из объекта и и пытаюсь добавить, но путаюсь со значением RowSpan

var tr = document.createElement('tr'); 
for(var i in obj){ 
    var td = document.createElement('td'); 
    td.rowSpan = ? // Here I am getting confused. 
} 

Может шаблонный движок решить мою проблему? Каков наилучший способ сделать это?

+2

FYI, это не JSON, это просто объектный литерал. JSON - это формат обмена данными, такой как XML или CSV. –

+0

вам нужно использовать стол. Просто используйте встроенные блоки div и установите правильный css. –

+0

@OnurTOPAL Мой текущий фокус заключается в том, чтобы сделать это, тогда я сосредоточусь на том, чтобы сделать это без таблиц – Exception

ответ

4

Вот один из способов сделать это с помощью рекурсивной функции в чистых ЯШАХ:

function addObjectToTable(table, obj, tr) { 
    var rows = 0; 
    for (key in obj) { 
    if (tr == null) { 
     tr = document.createElement('tr'); 
     table.appendChild(tr); 
    } 

    var td = document.createElement('td'); 
    td.textContent = key; 
    tr.appendChild(td); 

    var value = obj[key]; 
    if (typeof value != 'object') { 
     var td = document.createElement('td'); 
     td.textContent = value; 
     tr.appendChild(td); 
     rows += 1; 
    } 
    else { 
     var subrows = addObjectToTable(table, value, tr); 
     td.setAttribute('rowspan',subrows); 
     rows += subrows; 
    } 

    tr = null; 
    } 
    return rows; 
} 

Какого будет называться так:

var table = document.createElement('table'); 
addObjectToTable(table,obj); 
document.body.appendChild(table); 

Обратите внимание, что при первом вызове параметр тр является null, так как нам всегда нужно создать новую строку на верхнем уровне. Когда функция вызывается рекурсивно, параметр tr передается с верхнего уровня, так как нижние уровни будут в основном добавлять к строке их родительского объекта.

Функция возвращает количество добавленных строк, поэтому, когда она называется возвратно, вызывающий абонент будет знать, что нужно установить для значения rowspan.

Fiddle link

+0

Он отлично работает .. Отлично ... – Exception

1

Значение для rowspan - это количество свойств во внутреннем объекте. Вы можете использовать функцию Object.keys, чтобы получить список ключей на объекте, а затем использовать его свойство length, чтобы определить, сколько свойства есть:

for(var i in obj){ 
    var td = document.createElement('td'); 
    td.rowSpan = Object.keys(obj[i]).length; 
} 
+0

Что делать, если объект имеет вложенный объект ..? – Exception

+1

@Exception Затем вы обрабатываете это в своем коде любым способом, которым хотите его обрабатывать? Без более явного примера того, как это будет выглядеть, и как оно изменит желаемый результат таблицы, я не уверен, как вы ожидаете, что я отвечу на это. –

1
var table = document.createElement('table'); 
var i, j; 
var row, cell; 
for(i in obj) { 
    if(obj.hasOwnProperty(i)) { 
     var row = document.createElement('tr'); 
     var cell = document.createElement('td'); 
     cell.rowSpan = Object.keys(obj[i]).length; 
     cell.innerText = i; 
     row.appendChild(cell); 
     for(j in obj[i]) { 
      if(obj[i].hasOwnProperty(j)) { 
       cell = document.createElement('td'); 
       cell.innerText = j; 
       row.appendChild(cell); 
       cell = document.createElement('td'); 
       cell.innerText = obj[i][j]; 
       row.appendChild(cell); 
       table.appendChild(row); 
       row = document.createElement('tr'); 
      } 
     } 
    } 
} 
document.body.appendChild(table); 

Конечно, это будет выглядеть компактнее в JQuery , Но похоже, что вы хотели сделать это в простом DOM.

See it woking

+0

Спасибо за ответ, но он потерпит неудачу, если иерархия здесь более двух уровней. Http://jsfiddle.net/9dyFL/1/ – Exception

2

ОБНОВЛЕНО: если вам не нужно пустое решение клетки может быть (проверить скрипку http://jsfiddle.net/gD87t/11/)

Пример объекта:

var obj = { 
    a : { 
     x : 1, 
     y : 2, 
     z : { 
      c : 4, 
      d : 5 
     } 
    }, 
    b : { 
     x : 1, 
     y : 2, 
     z : 3 
    } 
} 

И рутина построить таблицу:

function merge(rows , inner) { 
    inner.reduce(function (i, p) { 
     rows.push(i) 
    }) 
} 

function getRows(o) { 
    var rows = [] 
    if (typeof o == 'object') { 
     for (var k in o) {       
      var innerRows = getRows(o[k]) 
      , firstCell = $('<td />') 
        .text(k) 
        .attr('rowspan',innerRows.length)   
      innerRows[0].prepend(firstCell)    
      rows = rows.concat(innerRows)   
    } 
    } else { 
     var tr = $('<tr />') 
     , td = $('<td />').text(o) 
     tr.append(td) 
     rows.push(tr) 
    } 
    return rows 
} 

function buildTable(o, $t) {  
    var rows = getRows(o)  
    $t.append(rows)  
} 

buildTable(obj, $('#table2')) 
+0

Спасибо за ответ. Но он терпит неудачу, если иерархия более двух уровней, таких как здесь http://jsfiddle.net/gD87t/7/ – Exception

+0

@Exception show example table для этого случая. – vittore

+0

Пожалуйста, посмотрите на это http://jsfiddle.net/gD87t/8/. Я закодировал пример части того, как я ожидаю от новых данных. – Exception

0

ну, это было действительно сложно, но я t hink это делается. Кстати, я все же предлагаю решение без таблиц. Вы можете проверить рабочий код here

var obj = { 
    a : { 
     x : 1, 
     y : 2, 
     z : {c:1, d:3} 
    }, 
    b : { 
     x : 1, 
     y : 2, 
     z : 3 
    } 
} 
var table = document.createElement('table'); 
function createTable (o, parentCells) { 
    for (var key in o) { 

     var row = document.createElement('tr'); 

     var cell = document.createElement('td'); 
     cell.rowSpan = 1; 
     cell.innerText = key; 
     if (typeof o[key] !== "object") { 
      var cellv = document.createElement('td'); 
      cellv.innerText = o[key]; 
      row.appendChild(cell);   
      row.appendChild(cellv); 
      table.appendChild(row); 
     } 
     else { 

      for (var i = 0; i < parentCells.length; i++) { 
       parentCells[i].rowSpan += Object.keys(o[key]).length; 
      } 

      cell.rowSpan += Object.keys(o[key]).length; 

      var newParentCells = new Array(parentCells); 
      newParentCells.push(cell); 
      row.appendChild(cell); 
      table.appendChild(row); 
      createTable(o[key], newParentCells); 
     } 


    } 
} 
createTable(obj, []); 
document.body.appendChild(table); 
3

я не мог найти ответ, который обрабатывается циркуляры, и я решил сделать это без каких-либо ненужных пишет DOM. Кроме того, я не следил за точной надписью, которую запросил ОП, потому что я чувствовал, что таблицы вложенности были более удобны для рекурсивной операции, такой как эта, и служат почти той же визуальной цели.

Итак, вот функция я создал:

function dataToTable (data) { 
    var storage = []; 
    return (function buildTable (data) { 
     var table = '<table><tbody>'; 
     var name, value; 
     // Add the object/array to storage for cirular detection. 
     storage.push(data); 
     for (name in data) { 
      value = data[name]; 
      table += '<tr><td>' + name + '</td><td>'; 
      // If the value is an object we've put in storage (circular) 
      if (storage.indexOf(value) !== -1) { 
       table += '<em>Circular</em>'; 
      } else if (typeof value === 'object') { 
       table += buildTable(value); 
      } else { 
       table += value; 
      } 
      table += '</td></tr>'; 
     } 
     return table + '</tbody></table>'; 
    }(data)); 
} 

Вот это объект, который я использовал для теста:

var obj = { 
    a : { 
     x : 1, 
     y : 2, 
     z : 3 
    }, 
    b : { 
     x : 1, 
     y : 2, 
     z : { 
      test1: 0, 
      test2: { 
       test3: 1, 
       test4: ['a','b','c'] 
      } 
     } 
    } 
}; 
obj.c = obj; 
obj.b.z.test2.test4.push(obj.a); 

функция превратит этот объект в HTML-таблицу. То, что вы делаете со столом, зависит от вас. На моей скрипке я использовал DOM, чтобы добавить таблицу в DIV (document.getElementById).

http://jsfiddle.net/5RhXF/1/

Я надеюсь, что вы найдете мое внедрение ясно.

UPDATE ::

Я решил проверить это на библиотеку JQuery, и это сработало! Кроме того, функции печатались как их значение toString без хорошего формата текста. Это имеет смысл, но не очень полезно. Итак, я думаю, что это хороший и простой способ просмотреть API-интерфейсы для фреймворков/библиотек и что-нет. Поэтому я добавил prettify для выделения синтаксиса функций, а также добавил проверку типов для функций в генераторе таблицы и быстрый класс, чтобы избавиться от границ вокруг поля prettify (так как уже есть граница на ячейке таблицы) , Если кто-то заинтересованы в версии, предназначенной для источника чтения/отладки, вот скрипка:

http://jsfiddle.net/5RhXF/7/

+1

Вложенные таблицы? * cringes * –

0

Если вы хотите использовать document.createElement, как вы делаете в вашем вопросе, самый простой способ, вероятно, так:

function generateTable(o) { 
    var table, tr, td, i, j, l, keys; 

    table = document.createElement('table') 

    for(i in o){ 
     tr = document.createElement('tr'); 
     table.appendChild(tr); 
     td = document.createElement('td'); 
     keys = Object.keys(o[i]); 
     td.rowSpan = keys.length; 
     td.textContent = i; 
     tr.appendChild(td); 
     x=0; 

     for(j=0;j<keys.length;j++) { 
      if(j) { 
       tr = document.createElement('tr'); 
       table.appendChild(tr);    
      } 
      td = document.createElement('td'); 
      td.textContent = keys[j]; 
      tr.appendChild(td); 
      td = document.createElement('td'); 
      td.textContent =o[i][keys[j]]; 
      tr.appendChild(td); 
     } 
    } 
    return table; 
} 

CAVEAT: Object.keys не доступен в старых браузерах так что вы» будет нуждаться в polyfill вроде этого:

(взятую из MOZILLA DEVELOPER NETWORK)

if (!Object.keys) { 
    Object.keys = (function() { 
    var hasOwnProperty = Object.prototype.hasOwnProperty, 
     hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), 
     dontEnums = [ 
      'toString', 
      'toLocaleString', 
      'valueOf', 
      'hasOwnProperty', 
      'isPrototypeOf', 
      'propertyIsEnumerable', 
      'constructor' 
     ], 
     dontEnumsLength = dontEnums.length; 

    return function (obj) { 
     if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object'); 

     var result = []; 

     for (var prop in obj) { 
     if (hasOwnProperty.call(obj, prop)) result.push(prop); 
     } 

     if (hasDontEnumBug) { 
     for (var i=0; i < dontEnumsLength; i++) { 
      if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]); 
     } 
     } 
     return result; 
    }; 
    })(); 
} 

В качестве альтернативы существует гораздо проще polyfill, который будет охватывать большинство случаев достаточно хорошо здесь:

(Из Token Posts)

if (!Object.keys) Object.keys = function(o) { 
    if (o !== Object(o)) 
    throw new TypeError('Object.keys called on a non-object'); 
    var k=[],p; 
    for (p in o) if (Object.prototype.hasOwnProperty.call(o,p)) k.push(p); 
    return k; 
} 

Вы можете увидеть скрипку его в действии здесь: http://jsfiddle.net/uyJv2/

+0

Спасибо за ответ. Но код, который вы предоставили, работает только на двух уровнях данных. Если два уровня данных я могу сделать это. Но мое требование - n раз, то это провалится. :( – Exception

Смежные вопросы