4
\$\begingroup\$

This function is meant to take an object, loop through the key-values and generate/build a HTML table at a particular ID:

function insertBasicTable(basic_data, insert_id) { /* Insert the key/value pairs into a table element on the DOM. basic_data = object containing key/value pairs insert_id = the id on the DOM to insert the table into Intentionally not including closing tags in the jquery requests; http://stackoverflow.com/a/14737115/2355035 */ table_id = '#' + insert_id; var array_length = Object.keys(basic_data).length; var array_obj_names = Object.keys(basic_data); // create the table header $(table_id).empty(); $(table_id).append('<thead>'); $(table_id).find('thead:last').append('<th>Tag'); $(table_id).find('thead:last').append('<th>Data'); // begin the table body and iterate through key/value pairs $(table_id).append('<tbody>'); for (var i = 0; i < array_length; i++) { var attr_name = array_obj_names[i]; var tag = '<td>' + array_obj_names[i]; var data = '<td>' + basic_data[attr_name]; $(table_id).find('tbody:last').append('<tr>' + tag + data); } } 

This function is then used, along with a number of D3 scripts, to populate elements on the DOM:

linePlot.render(someObject.modules.qual.quintiles); boxPlot.render(someObject.modules.qual.quintiles); insertBasicTable(someObject.modules.basic, 'basic-stats-table'); // etc, etc... 

Any comments about how this is being achieved? Am I overlooking either a basic tenant of how JS "should" be used (this is a huge side-effect for instance, should I be returning a formatted string then placing that string into the DOM for instance) or over-complicating things by jQuery'ing a bunch of times?

\$\endgroup\$

    3 Answers 3

    7
    \$\begingroup\$

    Let's start with your version:

    1) Unnecessary optimization.

    var array_length = Object.keys(basic_data).length; var array_obj_names = Object.keys(basic_data); 

    This gives you nothing in terms of performance. It would be optimized away by the browser.

    2) Chain-calling

    $(table_id).empty(); $(table_id).append('<thead>'); 

    It is possible to do chain-calls like: $('#elem').doA().doB().doC()

    3) Misunderstanding calls

    $(table_id).find('thead:last').append('<th>Tag'); 

    .append() does exactly that: appending after the last element.

    4) NuStyleLoopz

     for (var i = 0; i < array_length; i++) { var attr_name = array_obj_names[i]; var tag = '<td>' + array_obj_names[i]; var data = '<td>' + basic_data[attr_name]; 

    You could iterate over the keys directly via Object.keys() with

    Here a slighty pimped version:

    makeTag=function(openTag, closeTag){ return function(content){ return openTag+content+closeTag; }; }; tHead=makeTag("<thead>","</thead>"); tBody=makeTag("<tbody>","</tbody>"); td=makeTag("<td>","</td>"); tr=makeTag("<tr>","</tr>"); function insertBasicTable(data,id){ $('#'+id).html( tHead( tr( td("Tag")+ td("Data") ) )+ tBody( Object.keys(data).reduce(function(o,n){ return o+tr( td(n)+""+ td(data[n]+"") ); },"") ) ); }; insertBasicTable({"key1":"value1","key2":"value2"},"mytable"); 

    Here is the fiddle to play with.

    To make HTML-generation less painfull and a bit more JS-stylish I define what is called a higher order functionmakeTag: simply a function returning a function. A call to var tHead=makeTag("<thead>","</thead>"); generates an anonymous function (a function without name), which returns every time it's called "<thead>"+ parameter +"</thead>". The same goes for the other tags. This allows me to do something like a DSL:

     tHead( tr( td("Tag")+ td("Data") ) ) 

    That is not only handy, but cool B-) Besides it is nearly as readable as html and not so noisy like the typical string concatenation and the risk of typos is really low.

    \$\endgroup\$
      1
      \$\begingroup\$

      You should cache $table and $tbody, instead of re-instantiating them every time you need them.

      \$\endgroup\$
        1
        \$\begingroup\$

        Well, you've avoided the biggest potential issue by separating your data composition from your markup creation and manipulation.

        Your situation could be improved by changing your method to a "factory" method that is responsible for creating a table and then returning it.

        Then, it would be up to the caller of the table creation method to do what it needs to with the table. Whether the table is returned as a string, DOM element, or jQuery object is up to the needs of the consuming code.

        \$\endgroup\$

          Start asking to get answers

          Find the answer to your question by asking.

          Ask question

          Explore related questions

          See similar questions with these tags.