Page hangs up, too much to search - javascript

I used PHP to create an HTML page, which compiles a list of data points and pushes them into an array, declares the array in the header, and also echo's a huge list of form input objects into the body.
The list I'm working with is just under 15,000 lines which are put into 1 array.
I more or less created a search box that when I blur() an action is supposed to occur, Javascript function is supposed to search through the array and hide unmatched form options and display matches. This seems to work fine up to 5000 but if I have it run through all 15000 array items it hangs up and freezes.
I'm currently hosting it on a free site while I test... here is the link to the actual page TEST PAGE that hangs up
I'm including a snippet of the JS code with a truncated array so you don't have to scroll for thousands of lines.
<script type="text/javascript" >
var array_ICDDx = new Array('[ICD Code] Diagnosis','[001.0] Cholera due to vibrio cholerae','[001.1] Cholera due to vibrio cholerae el tor','[001.9] Cholera, unspecified','[002.0] Typhoid fever','[002.1] Paratyphoid fever A','[002.2] Paratyphoid fever B','[002.3] Paratyphoid fever C','[002.9] Paratyphoid fever, unspecified','[003.0] Salmonella gastroenteritis','[003.1] Salmonella septicemia','[003.20] Localized salmonella infection, unspecified','[003.21] Salmonella meningitis','[003.22] Salmonella pneumonia','[003.23] Salmonella arthritis','[003.24] Salmonella osteomyelitis',[...GOES ON FOREVER ~15000 ARRAY VALUES...]);
function searchICDDx(ICDDx,line_start,line_end) {
for (var a = line_start; a < line_end; a++) {
var ICDDx_check = array_ICDDx[a].toLowerCase();
var Row = "R" + a;
if (ICDDx_check.search(ICDDx) >= 0) {
document.getElementById(Row).style.display = "block";
}
else {
document.getElementById(Row).style.display = "none";
}
}
if (line_end < array_ICDDx.length) {
line_end += 1000;
if (line_end > array_ICDDx.length) { line_end = array_ICDDx.length; }
var timer = setTimeout(searchICDDx(ICDDx,a,line_end),100);
// searchICDDx(ICDDx,a,line_end);
}
// else if (line_end >= array_ICDDx.length) {
// clearTimeout(timer);
return;
// }
}
function searchICD() {
var find_ICD = Coder.elements['ICD'].value;
if (find_ICD != "") {
document.Coder.Dx.value = "";
find_ICD = find_ICD.toLowerCase();
searchICDDx(find_ICD,1,1000);
}
}
function searchDx() {
var find_Dx = Coder.elements['Dx'].value;
if (find_Dx != "") {
document.Coder.ICD.value = "";
find_Dx = find_Dx.toLowerCase();
searchICDDx(find_Dx,1,1000);
}
}
</script>
It doesn't appear to be an issue with the code not functioning. As I mentioned, if I limit the search to just 1000 array values it seems to work, its the massive amount of array values that is killing the page.
Any suggestions?
Thank you in advance!

With this many data points, you should probably do this on the server. However, you can try the following:
instead of using a for loop (which completely freezes the browser until it is done), use a setInterval that checks a new result every 5 ms or so. Periodically, check if all the results have been searched, and clear the interval if so. It will still take a bit to search, but won't freeze the browser.
search only until you have a set number of results (40 or so), and store the last index of the array that was searched. Wait to load more searches until the user scrolls down the page.
Also, you should probably implement an infinite scroll for displaying results. My browser froze and had to be restarted just opening the link you attached.
Update: if you don't want the items displayed until after you search, you should have no items on the page initially and add them when they match the search. This prevents the initial lag, prevents you from having to change the visibility of every element, and reduces the number of elements on the page (which causes issues).

Thank you for all your input and suggestions.
I went back and took out all of entries when listed in the form. Then I had JS create a list of checkbox inputs based on all the positive results and element.innerHTML the results. The array is still a huge list on client side through which the JS searches for matches. I updated the code in the link from my original post to show the faster and working result.
<script type="text/javascript" >
var array_ICDDx = new Array('[icd code] diagnosis','[001.0] cholera due to vibrio cholerae','[001.1] cholera due to vibrio cholerae el tor','[001.9] cholera, unspecified','[002.0] typhoid fever','[002.1] paratyphoid fever a',[...etc...]);
function searchICDDx(array_Results,ICDDx,line_start,line_end) {
for (var a = line_start; a < line_end; a++) {
if (array_ICDDx[a].indexOf(ICDDx) >= 0) {
array_Results.push("<span style='display:block' ><input type='checkbox' value='"+array_ICDDx[a]+"' >"+array_ICDDx[a]+"</span>");
}
}
if (line_end < array_ICDDx.length) {
line_end += 1000;
if (line_end > array_ICDDx.length) { line_end = array_ICDDx.length; }
searchICDDx(array_Results,ICDDx,a,line_end);
}
else if (line_end >= array_ICDDx.length) {
var string_Results = array_Results.join("\n");
document.getElementById("Results_here").innerHTML = string_Results;
return;
}
}
function searchICD() {
var array_Results = new Array();
var find_ICD = Coder.elements['ICD'].value;
if (find_ICD != "") {
document.Coder.Dx.value = "";
find_ICD = find_ICD.toLowerCase();
searchICDDx(array_Results,find_ICD,1,1000);
}
}
function searchDx() {
var array_Results = new Array();
var find_Dx = Coder.elements['Dx'].value;
if (find_Dx != "") {
document.Coder.ICD.value = "";
find_Dx = find_Dx.toLowerCase();
searchICDDx(array_Results,find_Dx,1,1000);
}
}
</script>
In the past I've had poor results with forms and innerHTML added options, which I'll tackle another time when I try to move this code into the larger project.
Thank you again

Related

How to populate jqGrid filter toolbar and search when the page loads (ASP.net webforms)

Currently, I'm trying to populate the filterToolbar with values taken in from a cookie. If there is cookie data for the filters, I want it to fill the respective textboxes and filter the jqGrid for that data.
I'm using ASP.net webforms, so most of my data is initialized already. How/where could I add javascript in order to get this going?
I actually figured out what I was doing.
So what I ended up doing as a solution was adding a timeout function in the document.ready function
$(document).ready(function () {
// some code
setTimeout(function () {
$('#Jqgrid1')[0].triggerToolbar();
}, 500)
//some code
}
My guess is that I couldn't use the $('#grid')[0].toggleToolbar() to force it because whenever I tried to use it, it was before the whole grid was finish setting up.
In the ASP webform, I had several functions registered.
<cc1:JQGrid ID="Jqgrid1" runat="server"
Height="630"
SearchDialogSettings-Draggable="true"
EnableViewState="false"
AutoWidth="True" >
<ClientSideEvents
LoadComplete="Jqgrid1_LoadComplete"
GridInitialized="initGrid"
/>
<%-- grid code --%>
</cc1:JQGrid>
The LoadComplete is executed after the grid is loaded. I tried doing triggering my toolbar there, but didn't work. My guess is, again, it was too early in the grid execution to use the triggerToolbar() function.
The same went for the GridInitialized events (even though both events would seem to imply to me that the grid is done doing its thing... but whatever...)
The way that I read my cookies in was actually in the GridInitialized event handler.
function initGrid() {
var myJqGrid = $(this);
var valueName = 'GridFilters';
var myCookie = document.cookie;
var gridFilterString;
var gridFilterArray;
var currentFilter;
var myCookie_arr;
var myDic = {};
if (myCookie.indexOf(valueName) > -1) { // don't even bother if the cookie isn't there...
myCookie_arr = myCookie.split("; "); // looking for the cookie I need
// read cookies into an array
for (var i = 0; i < myCookie_arr.length; i++)
{
parts = myCookie_arr[i].split("=");
first = parts.shift(); // remove cookie name
myDic[first.trim()] = parts.join("=").trim(); // handles multiple equality expressions in one cookie
}
if (myDic.hasOwnProperty("GridFilters"))
gridFilterString = myDic["GridFilters"];
if (gridFilterString != "NONE") {
myFiltersDic = {}
myFiltersArr = gridFilterString.split("&")
for (var i = 0; i < myFiltersArr.length; i++) {
parts = myFiltersArr[i].split("=");
myFiltersDic[parts[0].trim()] = parts[1].trim();
}
myParams = $(this).jqGrid("getGridParam", "postData");
var filters = []
for (keys in myFiltersDic) {
$('#gs_' + keys.trim()).val(myFiltersDic[keys].trim());
}
$.cookie('m_blnSearchIsHidden', "0", "/");
if (!isLoaded)
{
$(this)[0].toggleToolbar();
}
isLoaded = true;
}
}
}

Reload a content almost invisibly and no blinking effect using JAVASCRIPT

I'm writing a small progam wherein I'm getting data using $.get then display the data so far so good and then there's this part then when I click a certain link it refresh the page but it has this blinking effect. Is there a way on how to reload the content get the new updated content then replace the previously loaded data.
NOTE: I didn't use setInterval or setTimeout function because it slows down the process of my website. any answer that does not include those functions are really appreciated.
Here's the code
function EmployeeIssues(){
$('#initial_left').css({'display' : 'none'});
var table = $('#table_er');
$.get('admin/emp_with_issues', function(result){
var record = $.parseJSON(result);
var data = record.data,
employees = data.employees,
pages = data.pages;
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
for (var i = 0; i < employees.length; i++) {
$('#table_er').fadeIn('slow');
table.append(write_link(employees[i])); // function that displays the data
}
if(pages){
$('#pagination').html(pages);
}
}else{
$('#er_tab_label').html('<b>No employees with issues yet.</b>');
}
});
table.html('');
}
then this part calls the function and display another updated content
$('#refresh_btn').on('click', function(e){
e.preventDefault();
var tab = $('#tab').val();
if(tab == 'er'){
EmployeeIssues();
}
});
What should I do to display the content without any blinking effect?
thanks :-)
This section might be the issue :
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
for (var i = 0; i < employees.length; i++) {
$('#table_er').fadeIn('slow');
table.append(write_link(employees[i])); // function that displays the data
}
if(pages){
$('#pagination').html(pages);
}
} else ...
It seems you're asking table_er to fade in once per run of the loop whereas s there can only be one such table, you only need to do it once ?
first try re-arringing it like this:
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
$('#table_er').hide(); // hide it while we add the html
for (var i = 0; i < employees.length; i++) {
table.append(write_link(employees[i])); // function that displays the data
}
$('#table_er').fadeIn('slow'); // only do this after the table has all its html
if(pages){
$('#pagination').html(pages);
}
} else ....
Another possibility is that you're running through a loop and asking jquery to do stuff while the loop is running. It might be better to work out the whole HTML for the new page data in a string and then get the screen to render it in one line. I cna't do this for you as I don't know what's in write_link etc but something like this ..
if(employees){
$('#er_tab_label').html('<b>Employees with Issues</b>');
var sHTML ="";
$('#table_er').hide(); // hide it while we add the html
for (var i = 0; i < employees.length; i++) {
sHTML+=write_link(employees[i]); // maybe this is right ? if write_link returns an HTML string ?
}
table.append(sHTML); // add the HTML from the string in one go - stops the page rendering while the code is running
$('#table_er').fadeIn('slow'); // now show the table.
if(pages){
$('#pagination').html(pages);
}
} else ...

How is it possible, that ajaxing is much more slower in Chrome and IE than Mozilla?

I would like to ask you to find the point, why the site -I'm working on- is slow.
the conditions of the problem:
large row count (so I think maybe the problem is related to this.)
there is ajaxing event (I have tired to comment it out and the problem disappeared)
using not Mozilla (this freeze effect appear in IE and Chrome)
description of the problem (see the image):
I change the value of input
after there is an ajax call (in order to calculate prize) and it takes in FF about 30 ms otherwise more than 1 s
there is a freeze until the ajax finished (but ajax is not set to async:false)
only after that can I change the next input
I have tired to reproduce the error, but I could't. So see the original site:
site: foto/fotokidolgozas/elohivas-beallitasok.php
Log in and pass: d838292#rtrtr.com
Update: It works now fine, the trick is the following:
I use hidden input fields, their values are json_encode-d strings. I can process them anytime with js.
Thank you for any help!
Code:
$('#cikkek,#magic_bar').on("change","select,textarea,input[type!=hidden]",function(event_object){
if( $(this).attr('name') == "kijelolve" && !$(this).parents('#magic_bar').length)return true;
var cikk_id = $(this).parents('.cikk').attr('id');
var cikk_tipus = $("input[name=cikk_tipus]").val();
var tulajdonsag = $(this).attr('name');
var ertek = $(this).val();
if(ertek == "-1")return false;
if($(this).is('[type=checkbox]'))ertek = $(this).prop("checked")?'1':'0';
if(cikk_tipus=='fotokidolgozas' && (tulajdonsag=='meret'||tulajdonsag=='vagas'))
{
var sor = $(event_object.target).parents('.cikk');
var act_meret = sor.find('select[name=meret]').val();
var act_fill = sor.find('select[name=vagas]').val();
var act_zold_class = sor.find("input[name=zold_"+act_meret+"]").val()=="1" ?"zold":"feher" ;
var name = "src_"+act_meret+"_"+act_fill;
var name2 = "szoveges_uzenet_"+act_meret+"_"+act_fill;
sor.find(".img_cont").find("img").attr("src",sor.find("input[name="+name+"]").val());
sor.find(".szoveges_uzenet").text(sor.find("input[name="+name2+"]").val());
sor.find(".dpi_megfelel").text(sor.find("input[name=minoseg_"+act_meret+"]").val()+" ("+sor.find("input[name=dpi_"+act_meret+"]").val()+" dpi)");
sor.find("select[name=meret]").removeClass("feher zold").addClass(act_zold_class);
}
var before = now();
//this is the ajax part
if(ajax_modositaskor)
$.post('/_fn/cikk/mod.php',{
'cikk_tipus':cikk_tipus,
'cikk_id':cikk_id,
'tulajdonsag':tulajdonsag,
'ertek':ertek
},function(a){
var elapsed = now() - before;
if(a[0]!="1")
{
//error
alert(a[0]);
return;
}
if(a[1]!="-1")
{
//there is new price
$(event_object.target).parents('.cikk').find('.ar').text(a[1]);
}
if(a[2]!="-1")$('#cikkek_ara').text(a[2]);
osszegzest_frissit(a[3]);
var php_time = Math.round(a[4])
a_min = Math.min(a_min,elapsed);
p_min = Math.min(p_min,parseFloat(php_time));
a_max = Math.max(a_max,elapsed);
p_max = Math.max(p_max,parseFloat(php_time));
if(!a_avg)a_avg = elapsed;else a_avg= Math.round((a_avg+elapsed)/2);
if(!p_avg)p_avg = php_time;else p_avg = Math.round((p_avg+php_time)/2);
trace("ajax="+elapsed+"\tphp="+php_time+"\tajax_min="+a_min+"\tphp_min="+p_min+"\tajax_max="+a_max+" \tphp_max="+p_max+"\tajax_avg="+a_avg+" \tphp_avg="+p_avg);
},"json").error(function() { postHiba() });
});
The problem was that the hidden data was too large (see my other question), and it decreased the processing time. (Firefox seems to be well coded, because this does not mattered)
Now the problem is fixed.

Disappearing Menu Commands After User Input in Tampermonkey

Tampermonkey is an extension for Google Chrome that attempts to emulate the functionality of Greasemonkey. To be clear, I got my script to work in Chrome and the default JavaScript changes to show up. I wanted to test the menu commands, however, and entered a 6-digit hex color code after clicking on the command in the Tampermonkey menu. I reloaded the page, and the commands disappeared from the menu! My script was still there (and the checkbox was ticked).
No matter what I did or what code I changed, I could never emulate this initial functionality after that user-defined input was set. This leads me to believe that there's some persistent data that I can't delete that's causing my script to fail prematurely. NOTE: This exact script works perfectly and without errors in Firefox.
This is obviously not a Tampermonkey forum, but people here seem very knowledgeable about cross-platform compatility. I didn't hear a single peep from the Chrome console after all of the changes below, and I'm really just out of ideas at this point. Here are some things I've tried (with no success). Any console errors are listed:
Changing jQuery version from 1.5.1 to 1.3.2
Calling localStorage.getItem('prevoColor') from console after page load (both values null)
Changing client-side storage from localStorage to get/setValue
Calling GM_getValue from the console = ReferenceError: GM_getValue is not defined
Deleting localStorage entries for veekun.com in Chrome options
Refreshing, Re-installing the script, and restarting the browser more times than I can count
Repeating all of the above commands using Firebug Lite (bookmarklet)
Here's the code I was using:
// ==UserScript==
// #name Veekun Comparison Highlighter
// #namespace tag://veekun
// #description Highlights moves exclusive to pre-evolutions on veekun.com's family comparison pages (user-defined colors available)
// #include http://veekun.com/dex/gadgets/*
// #author Matthew Ammann
// #version 1.0.3
// #date 3/11/11
// #require http://sizzlemctwizzle.com/updater.php?id=98824
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
// ==/UserScript==
/*
Goal: Change checkmark color & move name to user-specified color on family comparison pages if
[DONE] Baby poke has a LEVEL-UP move unlearned by any evolutions
[DONE] a) Make sure move is not a TM or tutor move
[DONE] Any other mid-evolution has a move unlearnable by a final evo (Caterpie, Weedle families)
[DONE] a) Make sure move is not a TM or tutor move
[DONE] Any pre-evo has a TUTOR move unlearned by any evo (Murkrow in HG/SS)
[] Implement auto-update after uploading to userscripts.org
Credits: Brock Adams, for helping with Chrome compatibility
Metalkid, for the jQuery consult
*/
var isLevelupMove = false;
var isTutorMove = false;
var isTM = false;
var TMhead = $('#moves\\:machine');
var hasSecondEvo = false;
var hasFinalEvo1 = false;
var hasFinalEvo2 = false;
var header = $('.header-row').eq(1);
var TMmoves = new Array();
//This section deals with the user-defined colors
GM_registerMenuCommand("Color for pre-evolutionary-only moves", prevoColorPrompt)
GM_registerMenuCommand("Color for first evolution-only moves", evoColorPrompt)
var prevoColor = GM_getValue('prevoColor', '#FF0000');
var evoColor = GM_getValue('evoColor', '#339900');
function prevoColorPrompt()
{
var input = prompt("Please enter a desired 6-digit hex color-code for pre-evolutionary pokemon:")
GM_setValue('prevoColor', '#'+input);
}
function evoColorPrompt()
{
var input = prompt("Please enter the desired 6-digit hex color-code for first-evolution pokemon:")
GM_setValue('evoColor', '#'+input);
}
//This loop tests each 'th' element in a sample header row, determining how many Evos are currently present in the chart.
$('.header-row').eq(1).find('th').each(function(index)
{
if($(this).find('a').length != 0)
{
switch(index)
{
case 2:
hasSecondEvo = true;
break;
case 3:
hasFinalEvo1 = true;
break;
case 4:
hasFinalEvo2 = true;
break;
}
}
});
//All 'tr' siblings are TM moves, since it's the last section on the page
//This array puts only the names of the available TMs into the TMmoves array
TMhead.nextAll().each(function(index)
{
TMmoves.push($(this).children(":first").find('a').eq(0).html());
});
$('tr').each(function(index)
{
var moveName = $(this).children(":first").find('a').eq(0).html();
moveName = $.trim(moveName);
switch($(this).attr('id'))
{
case 'moves:level-up':
isLevelupMove = true;
break;
case 'moves:egg':
isLevelupMove = false;
break;
case 'moves:tutor':
isTutorMove = true;
case 'moves:machine':
isTM = true;
}
if(isLevelupMove || isTutorMove)
{
var babyMoveCell = $(this).find('td').eq(0);
babyMoveText = $.trim(babyMoveCell.html());
secondEvoCell = babyMoveCell.next();
secondEvoText = $.trim(secondEvoCell.html());
finalEvo1Cell = secondEvoCell.next();
finalEvo1Text = $.trim(finalEvo1Cell.html());
finalEvo2Cell = finalEvo1Cell.next();
finalEvo2Text = $.trim(finalEvo2Cell.html());
//This checks if evolutions have checkmarks
if(babyMoveText.length > 0)
{
if(hasSecondEvo && secondEvoText.length == 0 || hasFinalEvo1 && finalEvo1Text.length == 0 ||
hasFinalEvo2 && finalEvo2Text.length == 0)
{
//See if the move is a TM before proceeding
var tm = tmCheck(moveName);
if(!tm)
{
if(secondEvoText.length > 0)
{
babyMoveCell.css("color", evoColor);
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor); //highlights move name
}
else
{
babyMoveCell.css("color", prevoColor);
babyMoveCell.prev().find('a').eq(0).css("color", prevoColor);
}
}
}
}
else if(secondEvoText.length > 0)
{
if(hasFinalEvo1 && finalEvo1Text.length == 0 || hasFinalEvo2 && finalEvo2Text.length == 0)
{
var tm = tmCheck(moveName);
if(!tm)
{
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor);
}
}
}
}
});
function tmCheck(input)
{
var isTM = false;
//Iterate through TMmoves array to see if the input matches any entries
for(var i = 0; i < TMmoves.length; i++)
{
if(input == TMmoves[i])
{
isTM = true;
break;
}
}
if(isTM == true)
return true;
else
return false;
}
//alert("evoColor: " + localStorage.getItem('evoColor') + ". prevoColor: " + localStorage.getItem('prevoColor'));
Any ideas as to why this is happening?
EDIT: I messaged sizzlemctwizzle about this problem, and this was his reply: "Tampermonkey’s #require implementation is incorrect. It downloads my updater far too often so I have banned it from using my updater via browser sniffing. My server just can’t handle the traffic it brings. The script it is downloading from my server shouldn’t have any actual code in it. Since it is causing errors with in your script I would guess Tampermonkey isn’t passing the User Agent header when it does these requests. I’m never tested my updater in Chrome so I have no idea why it breaks. Perhaps you could try and install NinjaKit instead."
What URL are you testing this on? I tested on http://veekun.com/dex/gadgets/stat_calculator.
Anyway, the script behavior, vis à vis the menu commands did seem erratic with Tampermonkey. I couldn't really tell / didn't really check if the rest of the script was working as it should.
The culprit seems to be the sizzlemctwizzle.com update check. Removing its // #require made the menu stable. Putting that directive back, broke the script again.
I've never been a fan of that update checker, so I'm not going to dive into why it appears to be breaking the Tampermonkey instance of this script. (That would be another question -- and one probably best directed at the 2 responsible developers.)
For now, suggest you just delete it. Your users will check for updates as needed :) .

What is the fastest JSON parser for JavaScript?

I want to show a list with 1000 rows using Json that's support by Struts2 like pug-in. I use flexigrid (jquery) to parse 1000 rows to display. But it's so slow, and sometimes my browser crashes. (Firefox & IE).
So, what is the fastest Javascript framework to parse about 1000 rows?
What is the fastest JSON parser for JavaScript?
eval or when available, native JSON parser, at least in Chrome, Safari, Firefox 3.something, Opera 10.50, and even IE8 (only in IE8-mode)
Show the user what they want to see.
Show 50 rows, add a filter or a search.
If you really think that data should be reachable in a single page, maybe what you want is to fetch data while the user scrolls (and thus pick up smaller portions at a time).
I don't think you'll get acceptable performance from just about any grid component showing 1,000 at the same time, especially not on IE (even IE8). But most grids should be able to support having 1,000 in memory (well, depending on how big they are) and displaying a window into them (say, 20 rows, 40 rows, etc.) with paging and filtering options, without a significant performance problem. That would be a better user experience as well, I would think.
Edit
I got curious enough to check, and yeah, JSON parse time is not the problem; it'll be the rendering. Below is an example of very, very simple (not production) paging entirely client-side. On my netbook, IE7 parses the 1,000 rows of simple JSON objects in 36ms, so even complex objects shouldn't be an issue. That's using Prototype's evalJSON, which (even now) just defers to eval and puts the data in parentheses (they'll be changing that).
1000rows.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>1,000 Row Test Page</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
#log p {
margin: 0;
padding: 0;
}
</style>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js'></script>
<script type='text/javascript' src='1000rows.js'></script>
</head>
<body><div>
<input type='button' id='btnLoadData' value='Load Data'>
<input type='button' id='btnNext' value='Next'>
<input type='button' id='btnPrevious' value='Previous'>
<table>
<thead>
<tr><th>Name</th><th>Description</th><th>Count</th></tr>
</thead>
<tfoot>
<tr><th colspan='3' id='theLabel'></th></tr>
</tfoot>
<tbody id='theData'>
<tr><td colspan='3'></td></tr>
</tbody>
</table>
<hr>
<div id='log'></div>
</div></body>
</html>
1000rows.js (using Prototype; jQuery would be different but similar)
(function() {
var data, windowTop, WINDOW_SIZE;
// "Constant" for the size of our window into the data
WINDOW_SIZE = 20; // Rows
// No data yet
clearData();
// Hook up our observers when we can
document.observe('dom:loaded', function() {
$('btnLoadData').observe('click', loadData);
$('btnNext').observe('click', function(event) {
event.stop();
updateWindow(WINDOW_SIZE);
});
$('btnPrevious').observe('click', function(event) {
event.stop();
updateWindow(-WINDOW_SIZE);
});
});
// Clear our data to a known state
function clearData() {
data = [];
windowTop = 0;
}
// Click handler for the load data button
function loadData() {
var success;
log("Loading data..");
clearData();
updateWindow();
success = false;
// Note: Using text/plain rather than application/json so
// Prototype doesn't parse the data for me, so I can measure
// how long it takes to do it.
new Ajax.Request("data.txt", {
onSuccess: function(response) {
var start, duration;
success = true;
log("Got data, parsing");
start = new Date().getTime();
data = response.responseText.evalJSON();
duration = new Date().getTime() - start;
log("Data parsed in " + duration + "ms");
updateWindow.defer();
}
});
}
function updateWindow(offset) {
var dataElement, labelElement, markup, index, template;
// Get the target element
dataElement = $('theData');
labelElement = $('theLabel');
if (!dataElement || !labelElement) {
return;
}
// If no data, simply say that
if (!data || data.length <= 0) {
dataElement.update("");
labelElement.update("No information");
return;
}
// Ensure that windowTop is rational
if (WINDOW_SIZE > data.length) {
windowTop = 0;
}
else {
if (typeof offset == 'number') {
windowTop += offset;
}
if (windowTop + WINDOW_SIZE > data.length) {
windowTop = data.length - WINDOW_SIZE;
}
if (windowTop < 0) {
windowTop = 0;
}
}
template = new Template(
"<tr><td>#{name}</td><td>#{description}</td><td>#{count}</td></tr>"
);
markup = "";
index = windowTop + WINDOW_SIZE - 1;
if (index >= data.length) {
index = data.length - 1;
}
$('theLabel').update('Showing rows ' + windowTop + ' through ' + index);
while (index >= windowTop) {
markup = template.evaluate(data[index]) + markup;
--index;
}
dataElement.update(markup);
}
// Log a message
function log(msg) {
$('log').appendChild(new Element('p').update(msg));
}
})();
data.txt (quite boring, of course)
[
{"name": "Name #0001", "description": "Description #0001", "count": 1},
{"name": "Name #0002", "description": "Description #0002", "count": 2},
{"name": "Name #0003", "description": "Description #0003", "count": 3},
...
{"name": "Name #1000", "description": "Description #1000", "count": 1000}
]
...a full copy of data.txt can be found here.
1,000 rows of what? jQuery is actually pretty quick, especially since performance upgrades in version 1.4 (released just days ago). If you're experiencing problems showing 1,000 rows, I would first ask you why you're showing that many - no human ought to have to scroll that much. And second, is all of the information crucial, and are you only passing crucial information into the JSON value. And lastly, are you making your DOM unnecessarily-complicated with the way you're adding the data?
Again, if you're querying only what you need to show, and you're showing a reasonable about of data (posting 1,000 rows on the screen isn't reasonable), jQuery will be more than sufficient for your needs.
If you really want speed, the javascript eval("..."); function is the fastest. Unfortunately it's not safe as it can execute malicious javascript.
There's also the javascript JSON Parser (found here) from JSON.org. They've written the javascript to parse JSON strings to create a JSON object (I've heard that debugging using Firebug, a Firefox add-ons, creates an array of JSON objects but I've never tried it).

Categories

Resources