Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to populate a large datalist (~2000 items) from a dictionary

Right now I'm using the following code but it takes ~10 seconds on Chrome and ~2 minutes on IE11, which is where its mostly going to end up being used.

for (var key in dict) {
    if (dict.hasOwnProperty(key)) {
        combo.innerHTML += "<option value=\"" + dict[key] + "\">" + key + "</option>";
    }
}

I was reading this tutorial: http://blog.teamtreehouse.com/creating-autocomplete-dropdowns-datalist-element which suggested using ajax like so when dealing with larger quantities, though I'm not sure if large refers to 100 items or 100,000 items.

var request = new XMLHttpRequest();

request.onreadystatechange = function(response) {
  if (request.readyState === 4) {
    if (request.status === 200) {

      var jsonOptions = JSON.parse(request.responseText);

      jsonOptions.forEach(function(item) {

        var option = document.createElement('option');
        option.value = item;
        dataList.appendChild(option);

      });

    } else {
      console.log("Failed to load datalist options");
    }
  }
};

request.open('GET', 'html-elements.json', true);
request.send();

I've been trying to get this to work for a dictionary by replacing request.responseText with JSON.parse(JSON.stringify(dict)); but I'm running into problems getting it to make the request to begin with because it's not in a file.

How should I do this? And if I shouldn't be using a DataList for this, what alternative do you recommend?

Thanks in advance.

like image 491
Charles Clayton Avatar asked May 19 '15 21:05

Charles Clayton


2 Answers

One area in which you could speed up performance is with a document fragment as writing to the DOM is slow.

var frag = document.createDocumentFragment();

for (var key in dict) {
    if (dict.hasOwnProperty(key)) {
        var option = document.createElement("OPTION");
        option.textContent = key;
        option.value = dict[key];
        frag.appendChild(option);
    }
}

combo.appendChild(frag);
like image 64
znap026 Avatar answered Oct 17 '22 13:10

znap026


On instant way to get better performance is to build the HTML string up first, then assign it to the innerHTML.

var htmlStr = '';
for (var key in dict) {
    if (dict.hasOwnProperty(key)) {
        htmlStr += "<option value=\"" + dict[key] + "\">" + key + "</option>";
    }
}
combo.innerHTML = htmlStr;

The difference is huge: http://jsperf.com/string-append-vs-dom

like image 41
garryp Avatar answered Oct 17 '22 13:10

garryp