3

I want to generate a huge table generated by a Java servlet and sent to client as ajax response. My table cells are

<td style="background-color:blue;border-color:yellow;" onClick=tableClick(this)>value1</td>
<td style="background-color:red;border-color:cyan" onClick=tableClick(this)>value2</td>

suppose we have a table with 30 rows and 40 cols makes totally ca. 1000 cels. When I send this string from java to browser, i will be using to much network resources and the clients have poor connection capabilitiy, so have to minimize the content sent from java. First i cache the color names with c1:blue, c2:yellow, c3:red, c4:cyan

On the receiving side, the devices are mobile or ipads or tablets, so cpu workload is also important. What is the best way for performance to generate the table dynamically? How should be actions registered? How should be colors set?

Option1: use a json-notation such as

 { {'c1','c2','value1'},{'c3','c4','value2'}..

Populate a big string containing all cells and set to the table only once with append.

 // iterate in the json array and fetch the corresponding background color
 var bgcolor = extractFromJson(row,col);
 tablestring += "<td onclick=tableClick(this) style='background-color:' + bgcolor + ';border-color:' + brcolor + '>cellvalue</td>";

 // once we have all the cells, then set to the table
 $('#mytable').append(tablestring);

Option:2 Send a empty template to be filled on the receiver

Java: String tableString; bg is attribute for background color, br is attribute for the border color

tableString += '<td bg=c1 br=c4>cellvalue</td>';

on the browser side, set this table string to the table container

$('#mytable').append(tablestring);
// register actions and set colors
$('#mytable').find('td').each(funtction() {
     $(this).on('click', function () { tableClick($(this)[0]); });
     $(this).style('background-color', getColor($(this).attr("bg")));
     $(this).style('border-color', getColor($(this).attr("br")));
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
benchpresser
  • 2,171
  • 2
  • 23
  • 41
  • 1
    might be worth looping through the json and using `createElement` and `attr` to style it as you wish rather than creating a string for jquery to then read and do the same thing, see here http://stackoverflow.com/questions/327047/what-is-the-most-efficient-way-to-create-html-elements-using-jquery – rorypicko Feb 25 '15 at 14:35

3 Answers3

2

Option 1 would be a better approach.DOM operations are generally very slow. In first option you are creating a string and then finally appending once. On the other hand in Option 2, you are doing DOM operation for each row, which makes it inefficient. I believe option 1 is better.

Vaibhav
  • 1,479
  • 8
  • 13
  • what about events? setting with string – benchpresser Feb 25 '15 at 17:02
  • 1
    Putting the event listener on full table is better, that is the main feature of event delegation. Rather than adding event listener on each td, go for only one event listener on table. – Vaibhav Feb 25 '15 at 17:09
  • final design: i will put event listener on full table.for the styles and values, will sent json array, decode for example background-color:#001122 by c1,(in order to minimize network usage,i wll have 1000 cells but only 5 different background and foreground colors)send the properties through json.on the receiver side, i generate a huge string containing all cells created by concat(searched a lot and += string operations are fast enough).Then finally set the huge string to table with document.getElementById('id').innerHTML=hugeString (there is performance loss when used $('#id).html(hugeString) – benchpresser Feb 25 '15 at 22:49
  • 1
    Thats nice, JQuery selector will be little slower than native one, so getElementById is better. – Vaibhav Feb 26 '15 at 03:16
1

Regarding your event handling, you should use event delegation. Instead of an handler per row, you should have a single handler. In jQuery:

 $('#mytable').parent().on('click', 'td', function(ev) {
     tableClick($(this)[0]);
 });

Mixing scripting with document structure (DOM creation) is bad for many reasons (bad for web designers, difficult to maintain, mixture of concerns, much weight on client, etc.)

Therefore, DOM creation should be prepared on the server. Since you're using Java, I don't see a reason to not using some server side tech. to generate HTML (manually, JSP, Facelets, Velocity, ...). That would make the client job much lighter as you wanted.

If not possible, at least use DOM API (as stated in the other answer). You should avoid string-based creation..

Community
  • 1
  • 1
Luís Soares
  • 5,726
  • 4
  • 39
  • 66
  • ok, dom manipulation causes poor performance. but why should we avoid string based creation? if we generate the full table on the server, it is a huge string and network is a issue. what do you think about option1, where we append to string and finally set to the container? – benchpresser Feb 25 '15 at 15:05
  • 1
    what's wrong with injecting html strings? Far less function calls involved – charlietfl Feb 25 '15 at 15:10
  • string based creation is bad because: error prone, hard to handle (e.g. add vars), mantain (hard to read), hard do manipulate by designer, among other reasons. – Luís Soares Feb 25 '15 at 15:22
  • if we think only and only for performance? what is the best way? – benchpresser Feb 25 '15 at 15:25
  • 1
    Option 1 is OK as long as you avoid string-based DOM creation (you can apply @rorypicko approach to avoid it). Anyway, it's still JS based. I never tested it, but a full HTML (server generated) is probably faster and puts less strain on the client (it can even be cached server-side!). Of course the event handling part is of JS nature. – Luís Soares Feb 25 '15 at 15:25
  • "if we think only and only for performance" > server side cached solution. because the HTML markup is always the same it can be cached. the client just has to draw it as a static page. – Luís Soares Feb 25 '15 at 15:30
  • yes but the total html is too large to be handled on network, clients have poor connection. my current structure is already generating the full html and setting directly using $('#container').html(content). I need a hybrid solution, where network traffic is minimised and also performane is kept.my idea in option1 was totally string addition (no dom operation) and then with only step setting it to the container. i will have a big string containing all cells. and lastly invoking $('#table').html(hugestring). what is wrong with this approach? – benchpresser Feb 25 '15 at 15:33
  • 1
    In that case, JSON is lighter than XML. Send some JSON to be processed by the client. Here you could consider a declarative approach (for the structure part) like AngularJS instead of a jQuery imperative one. I never tested it, but it seems reasonable to consider it in this case. – Luís Soares Feb 25 '15 at 15:35
  • anyway, do not forget the event delegation. it can make a difference. – Luís Soares Feb 25 '15 at 15:38
  • the fastest is creating the huge table on server and sending to client and setting to container. But it consumes too much network resource. Opt1 means, i generate the content on the client where i append cell styles etc from json array. Finally i have a big string containing all cells. No dom operation until now. Lastly i set it to container. Doesn't has it better performance compared to rorypicko appoach? Event delegation is ok, because all cells have same action, but what about styles? – benchpresser Feb 25 '15 at 15:45
  • 1
    Regarding your DOM question, and since performance is very important there, I recommend you to make experiments with http://jsperf.com/ (e.g. http://jsperf.com/jquery-vs-createelement) Regarding styles, yes you have to do one by one but that's not an issue. It just needs to be done; you just need to benchmark now. – Luís Soares Feb 25 '15 at 15:54
  • 1
    if **only** performance and network latency matters..... string based is the way, despite all its disadvantages... check here: http://jsperf.com/dom-insertion-jquery-string-or-createelement/2 – Luís Soares Feb 25 '15 at 15:58
  • 1
    but for a small sample, it looses.... http://jsperf.com/creating-dom-elements2/4 in conclusion... do your own jsperf experiment with your real example code :) – Luís Soares Feb 25 '15 at 16:02
1

you should loop through your json like this

for(var i = 0; i < json.length; i++){
    $('<td/>').style({
        backgroundColor: getColor(json[i][0]),
        border: getColor(json[i][1])
    })
    .html(json[i][2])
    .click(function(){
        tableClick($(this)[0]);
    }).appendTo("#mytable");
}
rorypicko
  • 4,194
  • 3
  • 26
  • 43