0

I've created my own autocomplete feature and I've come across a bug I'd like to fix. Here's an example of an incomplete sentence I might want to autocomplete the final word for:

let text = 'Hello there, I am her'

In my functionality the user clicks ctrl + enter and it autcompletes the word with a suggestion displayed on the page. In this case let's say the suggestion is 'here'. Also my controller knows where the user is based on the insertion cursor (so I have the index).

If I use replace like so:

text.replace(word, suggestion);

(Where word is 'her' and suggestion is 'here') it will replace the first occurrence. Obviously there are endless combinations of where this word might be in the text, how do I replace one at a certain index in text string? I know I can do it through some messy if conditions, but is there an elegant way to do this?

(If it is relevant I am using angular keydown/keyup for this)

EDIT>>>>> This is not a duplicate on the question linked as in that case they are always replacing the last occurrence. If I did that then my program wouldn't support a user going back in their sentence and attempting to autocomplete a new word there

DeejC
  • 117
  • 13
  • to OP: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split let frags = text.split(' '); – simon Jan 05 '18 at 12:00

2 Answers2

0

So, you have a position in a string and a number of characters to replace (=length of an incomplete word). In this case, would this work?

let text = 'appl and appl and appl'

function replaceAt(str, pos, len, replace) {
    return str.slice(0, pos) + replace + str.slice(pos + len);
}

console.log(replaceAt(text, 0, 4, 'apple'))
console.log(replaceAt(text, 9, 4, 'apple'))
georg
  • 211,518
  • 52
  • 313
  • 390
  • This works great thanks! What I actually had was the index of the end of the word, but that's a quick fix. For some reason now if I replace one of the earlier occurrences it moves my insertion cursor to the end of the string, but that's a different (less important) issue... – DeejC Jan 05 '18 at 12:21
  • DeejC while this answer is a good alternative, look @ split() and join() functions, they are extremely nice for string manipulations. – simon Jan 05 '18 at 12:22
0

Gonna point you in a direction that should get you started.

let sentence = 'Hello lets replace all words like hello with Hi';
let fragments = sentence.split(' ');
for (let i=0; i<fragments.length; i++){
 if(fragments[i].toLowerCase() == 'hello')
   fragments[i] = 'Hi'
}
let formattedsentence = fragments.join(' ');
console.log(formattedsentence); //"Hi lets replace all words like Hi with Hi"
simon
  • 854
  • 1
  • 9
  • 23
  • Think you would struggle to find the index of the fragments array you want if the array contains duplicate values? Would get a bit messy I think – DeejC Jan 05 '18 at 12:22
  • Fragments will contain any index you want, its up to you to figure out which index to change. In this above case, I threw in a .toLowerCase() to also match against those as well. This is the additional logic you'd have to throw in the loop to extract what you want to modify, and what you dont. – simon Jan 05 '18 at 12:24
  • In my case, it found 2 matches. If I didn't use .toLowerCase(), it would have only found 1. – simon Jan 05 '18 at 12:25
  • If there were 2 instances of 'hello' and then you find 2 matches, how do you know which match to pick based off the index of the original `sentence`? – DeejC Jan 05 '18 at 12:36
  • In my example, its going to pick whatever you specify. In that case it is 'hello' and any instance of 'hello', regardless if its uppercase or lower. – simon Jan 05 '18 at 12:47
  • Okay, not quite what I'm looking for in this case but thanks for the ideas – DeejC Jan 05 '18 at 13:51