0

I have the following code to display list with words for autocompleting:

var words = ['foo', 'bar', 'barz', 'ba'];
var possibleWords = [];
  
document.getElementsByTagName('div')[0].addEventListener('keyup', function(){
      
  var textWords = this.innerText.split(' ');
  var lastWord = textWords[textWords.length-1];
  for(var k = 0; k < words.length; k++){
      
    for(n = 0; n < 20; n++){
          
      if(lastWord.length == n+1 && words[k].charAt(n) == lastWord.charAt(n)){
        possibleWords.push(words[k]);
            
        var counts = possibleWords.reduce((a, c) => {
          a[c] = (a[c] || 0) + 1;
          return a;
        }, {});
        var maxCount = Math.max(...Object.values(counts));
        var mostFrequent = Object.keys(counts).filter(k => counts[k] === maxCount);
      }
    }
  }
      
  console.log(mostFrequent);
      
  var list = this.getElementsByTagName('ul')[0];
  if(mostFrequent == undefined) {
    list.removeAttribute('style');
  } else {
      
    list.style.display = 'inline';
    list.innerHTML = '';
    list.innerHTML = '<li>'+mostFrequent.join('</li><li>')+'</li>';
  }
});
div{
width:300px;
height:100px;
outline:1px solid #ccc;
position:relative;
}
ul{
display:none;
position:absolute;
left:0;
top:100px;
}
<div contenteditable="true"><ul></ul></div>

When I comment the bottom code from var list = ... to list.innerHTML = '<li>'+... and try to type b, then ba, then bar and then barz I see correct result in the console. But if I don't comment the bottom code, I receive undefined half the time and the list is also hidden half the time.

How to resolve the issue?

1 Answer 1

1

You're seeing this odd behavior because your <ul> tag that you dynamically update is nested within the same div that receives input to feed the contents of the list. Consider what the value of this.innerText is on your div keyup listener after you dynamically modify the list that the div contains.

Try console.log(textWords) at the top of your keyUp listener to see.

Simply making your div this instead:

<div contenteditable="true"></div><ul></ul>

and changing the listener near the end of your snippet to

var list = document.getElementsByTagName('ul')[0];

Solved the issue for me.

As an aside -- there are more performant ways to implement autocomplete. Look into "autocomplete trie" for just one way.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.