1
\$\begingroup\$

Previous topic: Large table updates using AJAX in Internet Explorer 11

For the functions included here, I have taken the advice of the previous answer and incorporated it in the restructure, but am still experiencing huge latency of about 2 seconds per computer record.

I am lead to believe that this is more an issue with the structure of the DOM. I have added the HTML to this post. Could anyone advise if there may be a more appropriate table structure / access method that might better suit my needs?

function writeTableLines(tempRows){
    /* This Function takes care of updating the text and coloring of
    network name
    Boot time
    chck in time
    workgroup
    utilization
    All other values are not dynamically written.
    */
    for( i in tempRows){
        var tempValues = tempRows[i];
        // For Row
        var selector = $(document.getElementById(i.toString()));
        var name_selector = selector.find(".name");
        var network_selector = $(document.getElementById(i.toString()+'_network'));  //"[id='"+i+"_network']";
        var boot_selector =  $(document.getElementById(i.toString()+'_boot'));                //"[id='"+i+"_boot']";
        var check_in_selector =   $(document.getElementById(i.toString()+'_checked_in'));//"[id='"+i+"_checked_in']";
        var util_selector = selector.find('.util').find('a');
        var workgroup_selector = selector.find('.workgroup').find('a');

		network_selector.text(tempValues['network']);

		if (tempValues['network_color']){
		    network_selector.addClass(tempValues['network_color']);
		    name_selector.addClass(tempValues['network_color']);
		}else{
		    network_selector.removeClass('warning');
		     name_selector.removeClass('warning');
		}

        // Boot Time

		boot_selector.text(tempValues['boot']);
		if (tempValues['boot_color']){
		    boot_selector.addClass(tempValues['boot_color']);
		   name_selector.addClass(tempValues['boot_color'])
		}else{
		    boot_selector.removeClass('issue');
		    name_selector.removeClass('issue');
		}

		// Last Checked In Timestamp

		check_in_selector.text(tempValues['checked_in']);
		if (tempValues['service_unresponsive']){
		    check_in_selector.addClass('redline');
		    name_selector.addClass('redline');
		}else{
		    check_in_selector.removeClass('redline');
		    name_selector.removeClass('redline');
		}


		util_selector.text(tempValues['util'])
		 if (tempValues['util_class']){
            util_selector.addClass(tempValues['util_class']);
        }else{
            util_selector.removeClass('redline warning');
        }



        if (($.trim(tempValues['workgroup'])) != $.trim(workgroup_selector.text())){
            if ((tempValues['workgroup'] != selected) && (selected != 'All')){
			    workgroup_selector.addClass('warning');
    		}else{
	    		workgroup_selector.removeClass('warning');
		    }
		}
        workgroup_selector.text(tempValues['workgroup'])
		toggle_links(i, tempRows[i]);
		$('#connectionGrid').trigger('updateAll', [false]);
  	}
}
function disable_links(computer){
	var links = document.getElementsByClassName("pclinks_"+computer);
	var myLength = links.length;
	for(var i = 0; i < myLength ;i++){
		links[i].removeAttribute("href");
		$(links[i]).addClass('disabled_link').removeClass('enabled_link');
		if (links[i].id == 'refresh'){
			continue;
		}
		links[i].onclick = function(){
			alert("Currently Offline");
		}
   	}
}

function enable_links(computer, network){
	var links = document.getElementsByClassName("pclinks_"+computer);
	var myLength = links.length;
	for(var i = 0 ; i < myLength ; i++){
			if (links[i].id == 'refresh'){
				links[i].onclick = function(){ refresh(this)};
				continue;
			}
			links[i].href = "file://///"+network+"/MM"+links[i].id;
			$(links[i]).removeClass('disabled_link').addClass('enabled_link');
		    $(links[i]).prop("onclick", null);
		}
}


function toggle_links(computer, row){
	if(row['online'] == false){
		disable_links(computer);
	}else{
		enable_links(computer, row['network']);
	}
}
{% extends 'directory/base.html' %} 
{% block content %}

<div id="tabs">
    <ul id="gaugeList">
        {% for workgroup in context['workgroup_list'] %}
        <li><h3>
        <a class="gaugeCell" id="{{ workgroup.shorthand }}" href="#tabs-{{ workgroup.shorthand }}"></a>
        </h3></li>
        {% endfor %}
    </ul>
    <div id="gridBox" class="scrollable">
        <table id="connectionGrid" class="tablesorter">
            <thead>
                <tr>
                    <th>Type</th>
                    <th>Computer</th>
                    <th>Workgroup</th>
                    <th>C:\ Drive %</th>
                    <th></th>
                    <th></th>
                    <th></th>
                    <th class="clearall button" onclick="hideRows()">Clear All</th>
                    <th onclick="collapseListener()" id="collapserows" class="collapseall button">Collapse All</th>
                </tr>
            </thead>
            <tbody id="connectionBody">
                {% for computer in context['computer_list'] %} 
                {% if (computer.visible == True or current_user.is_admin) and computer.active_drive is not none %}
                <tr id="{{computer.name}}" class="parent">
                    <td rowspan="1" class="type">
                        <a href="#" class="toggle">{{ computer.station_type if computer.station_type else 'Enter Data'}}</a>
                    </td>
                    <td class="name">
                        <a href="#" id="name" class="toggle">{{computer.name}}</a>
                    </td>
                    <td class="workgroup">
                        <a href="#" id="{{computer.name}}_workgroup" class="innerworkgroup toggle">{{computer.active_drive.workgroup.shorthand}}</a>
                    </td>
                    <td class="util">
                        <a href="#" class="toggle" id="{{computer.name}}_util">{{ computer.active_drive.percentage_full if computer.active_drive.percentage_full else 'Check Service'}}</a>
                    </td>
                    <td>
                        <a id="{{computer.name}}_Users" class="enabled_link pclinks_{{computer.name}}" href="file://///{{ computer.active_drive.name }}/MMUsers" target="_blank">Users</a>
                    </td>
                    <td>
                        <a id="{{computer.name}}_Projects" class="enabled_link pclinks_{{computer.name}}" href="file://///{{ computer.active_drive.name }}/MMProjects" target="_blank">Projects</a>
                    </td>
                    <td>
                        <a id="{{computer.name}}_attic" class="enabled_link pclinks_{{computer.name}}" href="file://///{{ computer.active_drive.name}}/MMAttic" target="_blank">Attic</a>
                    </td>
                    <td>
                        <a id="{{computer.name}}_pcusers" class="enabled_link pclinks_{{computer.name}}" href="file://///{{ computer.active_drive.name }}/MMPCUsers" target="_blank">Desktops</a>
                    </td>
                    <td>
                        <img src="{{url_for('static',filename='images/refresh.png')}}" title="Service restart may take up to a minute" id="{{computer.name}}_refresh" class="pclinks_{{computer.name}}" onclick="refresh(this)" target="_blank">
                        </img>
                    </td>
                    <tr class="tablesorter-childRow">
                        <td class="label dualboot topitem" colspan="1">Dual Boot</td>
                        <td class="info dualboot topitem" colspan="1" >
                            {{ 'Yes' if computer.dual_boot == True else 'No' }}
                        </td>

                        <td class="label topitem" colspan="3" style="text-align:center;">{{computer.active_drive.image_version}}</td>

                        <td class="label topitem" colspan="2">Media Composer</td>
                        <td class="info topitem" colspan="2">{{computer.active_drive.media_composer_version}}</td>
                    </tr>
                    <tr class="tablesorter-childRow">
                        <td class="label" colspan="1">Network Name</td>
                        <td class="info" colspan="1" id="{{computer.name}}_network">{{ computer.active_drive.name }}</td>

                        <td class="label">Model</td>
                        <td class="info" colspan="2">
                            {{ computer.model if computer.model else 'Check Service' }}</td>
                        <td class="label" colspan="2">Interplay Access</td>
                        <td class="info" colspan="2">{{computer.active_drive.access_version}}</td>
                    </tr>
                    <tr class="tablesorter-childRow">
                        <td class="label">Room</td>
                        <td class="info" colspan="1">
                            {% if computer.room %} {{ computer.room }} ({{computer.room.description}}) {% else %} Enter Data {% endif %}
                        </td>

                        <td class="label" colspan="1">Edit Service</td>
                        <td class="info" colspan="2">{{computer.active_drive.edit_service_version}}</td>
                        <td class="label" colspan="2">Media Indexer</td>
                        <td class="info " colspan="2">{{computer.active_drive.indexer_version}}</td>
                    </tr>
                    <tr class="tablesorter-childRow">
                        <td class="label" colspan="1">Phone</td>
                        <td class="info" colspan="1">
                            {{ computer.room.phone_numbers if computer.room.phone_numbers else 'Enter Data'}}</td>

                        <td class="label ">Boot Time</td>
                        <td class="info " colspan="2" id="{{computer.name}}_boot">
                            {% if computer.online == false %} Offline {% else %} {{ computer.active_drive.boot_time if computer.active_drive.boot_time else 'Check Service' }} {% endif %}
                        </td>

                        <td class="label" colspan="2">Transfer Client</td>
                        <td class="info" colspan="2">{{computer.active_drive.transfer_client_version}}</td>
                    </tr>
                    <tr class="tablesorter-childRow">
                        <td class="label" id="intercomlabel" colspan="1">Intercom</td>
                        <td class="info" colspan="1">
                            {{ computer.room.intercom_numbers if computer.room.intercom_numbers else 'Enter Data' }}
                        </td>
                        <td class="label" colspan="1">Checked-In</td>
                        <td class="info checkin" colspan="2" id="{{computer.name}}_checked_in">
                            {{ computer.active_drive.last_checked_in if computer.active_drive.last_checked_in else 'Check Service' }}
                        </td>
                        <td class="label" colspan="2">Avid ISIS Client</td>
                        <td class="info" colspan="2">{{computer.active_drive.isis_client_version}}</td>
                    </tr>
                    <tr class="tablesorter-childRow">
                        <td class="label">Notes</td>
                        <td class="info" colspan="1">{{ computer.notes if computer.notes else ''}}</td>
                        <td class="label">Swing Date</td>

                        <td class="info" colspan="2">{{ computer.active_drive.last_changed_workgroup }}</td>

                        <td class="label" colspan="2">Nvidia Driver</td>
                        <td class="info " colspan="2">{{computer.active_drive.graphics_driver_version}}</td>
                   </tr>

                {% endif %} 
                {% endfor %}
            </tbody>
        </table>

    </div>

    <div id="bottom" class="bottom">
        {% for workgroup in context['workgroup_list'] %}
        <a href="#" id="{{workgroup.shorthand}}" class="show_{{workgroup}}">
{{ workgroup.shorthand }}
</a> {% endfor %}
    </div>
</div>
{% endblock %}

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

I know it has been quite some time since the question was posted and maybe you have found optimizations already but hopefully the review below will be helpful.

Selecting elements

In the previous review, the answer by @Roamer-1888 stated the following:

Searching a whole, large DOM for elements is a real performance killer. When possible, always try to search a fragment, or traverse the DOM relative to a known element.

Yet, it appears that the writeTableLines() function still has many calls to document.getElementById(). For example, selector could be found by utilizing the <tbody> element. It would be best to store a reference to that element outside the for loop -

var tbody = $('#connectionBody');

Then selector can be found using selector.find():

var selector = tbody.find('#' + i.toString());

Once selector has been found, the other child elements (e.g network_selector, boot_selector, etc.) can be found using selector.find() as well...

Unique id attributes

Inside the functions disable_links() and enable_links() I see conditional logic like this:

if (links[i].id == 'refresh'){

But looking at the HTML I don't see any element with that id attribute. Inside each row I see an element with

<img src="{{url_for('static',filename='images/refresh.png')}}" title="Service restart may take up to a minute" id="{{computer.name}}_refresh" class="pclinks_{{computer.name}}" onclick="refresh(this)" target="_blank">

So unless there is another HTML element that wasn't included in the original post, that conditional code mentioned above would never evaluate to true.

Similarly, I noticed in the HTML for the table rows:

<td class="name">
      <a href="#" id="name" class="toggle">{{computer.name}}</a>

This means that each row has an anchor element with the id attribute value name. Remember that "The id global attribute defines a unique identifier (ID) which must be unique in the whole document."1

1https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.