function autocomplete(inp, obj) {
  /*the autocomplete function takes two arguments,
  the text field element and an objay of possible autocompleted values:*/
  var currentFocus;
  /*execute a function when someone writes in the text field:*/
  inp.addEventListener("input", function(e) {
      var a, b, i, val = this.value;
      /*close any already open lists of autocompleted values*/
      closeAllLists();
      if (!val || val.length < 3) return false;
      currentFocus = -1;
	  
      /*create a DIV element that will contain the items (values):*/
      a = document.createElement("DIV");
      a.setAttribute("id", this.id + "autocomplete-list");
      a.setAttribute("class", "autocomplete-items");
      /*append the DIV element as a child of the autocomplete container:*/
      this.parentNode.appendChild(a);
	  
      /*for each item in the object...*/
      for (node in obj) {
		var nomNode = obj[node].name;
				
		if (nomNode.toUpperCase().includes(val.toUpperCase())) {
			var parts = nomNode.toUpperCase().split(val.toUpperCase());
			
			  /*create a DIV element for each matching element:*/
			  b = document.createElement("DIV");
			  
			  /*make the matching letters bold:*/
			  if (parts[0].length == 0) b.innerHTML = "";
			  else b.innerHTML = nomNode.substr(0, parts[0].length);
			  b.innerHTML += "<strong>" + nomNode.substr(parts[0].length, val.length) + "</strong>";
			  b.innerHTML += nomNode.substr(parts[0].length + val.length);
			  b.innerHTML += " - <span class='autocomplete-year'>" + obj[node].year + "</span>";
			  /*insert a input field that will hold the current object item's value:*/
			  b.innerHTML += "<input type='hidden' value='" + node + "'>";
			 
			 /*execute a function when someone clicks on the item value (DIV element):*/
			  b.addEventListener("click", function(e) {
				  /*insert the value for the autocomplete text field:*/
				  var n = this.getElementsByTagName("input")[0].value;
				  inp.value = obj[n].name;
				  
				  // Move camera to desired node
					sigma.misc.animation.camera( s.camera,
					  { x: obj[n].x, y: obj[n].y, ratio: 0.5 },
					  { duration: s.settings('animationsTime') || 300 }
					);
			  
				  // Close the search box
				  var searchBox = document.getElementById('searchBox');
				  searchBox.style.display = "none";
				  
				  // Empty the input bar
				  var searchInput = document.getElementById('searchInput');
				  searchInput.value = "";
				  
				  /*close the list of autocompleted values,
				  (or any other open lists of autocompleted values:*/
				  closeAllLists();
			  });
			  
			  // Set "data-edges" attribute and compare with others
			  var nEdges = Object.keys(s.graph.neighbors(node)).length;
			  b.dataset.edges = nEdges;
			  var inserted = false;
			  
			  // Sort nodes by degree
			  for (i in a.childNodes) {
				  var child = a.childNodes[i];
				  if (!child.dataset) break;
				  if (nEdges > child.dataset.edges) {
					  a.insertBefore(b, child);
					  inserted = true;
					  break;
				  }
			  }
			  
			  if (!inserted) {
				  a.appendChild(b);
				  console.log("inserted");
			  }
		  }
        }
  });
  /*execute a function presses a key on the keyboard:*/
  inp.addEventListener("keydown", function(e) {
      var x = document.getElementById(this.id + "autocomplete-list");
      if (x) x = x.getElementsByTagName("div");
      if (e.keyCode == 40) {
        /*If the objow DOWN key is pressed,
        increase the currentFocus variable:*/
        currentFocus++;
        /*and and make the current item more visible:*/
        addActive(x);
      } else if (e.keyCode == 38) { //up
        /*If the objow UP key is pressed,
        decrease the currentFocus variable:*/
        currentFocus--;
        /*and and make the current item more visible:*/
        addActive(x);
      } else if (e.keyCode == 13) {
        /*If the ENTER key is pressed, prevent the form from being submitted,*/
        e.preventDefault();
        if (currentFocus > -1) {
          /*and simulate a click on the "active" item:*/
          if (x) x[currentFocus].click();
        }
      }
  });
  function addActive(x) {
    /*a function to classify an item as "active":*/
    if (!x) return false;
    /*start by removing the "active" class on all items:*/
    removeActive(x);
    if (currentFocus >= x.length) currentFocus = 0;
    if (currentFocus < 0) currentFocus = (x.length - 1);
    /*add class "autocomplete-active":*/
    x[currentFocus].classList.add("autocomplete-active");
  }
  function removeActive(x) {
    /*a function to remove the "active" class from all autocomplete items:*/
    for (var i = 0; i < x.length; i++) {
      x[i].classList.remove("autocomplete-active");
    }
  }
  function closeAllLists(elmnt) {
    /*close all autocomplete lists in the document,
    except the one passed as an argument:*/
    var x = document.getElementsByClassName("autocomplete-items");
    for (var i = 0; i < x.length; i++) {
      if (elmnt != x[i] && elmnt != inp) {
        x[i].parentNode.removeChild(x[i]);
      }
    }
  }
  /*execute a function when someone clicks in the document:*/
  document.addEventListener("click", function (e) {	  
      closeAllLists(e.target);
  });
}
