How to make an auto-fill in TextBoxes?

How can I make an auto fill in text box like this

image

1 Like

You could use string.find() to filter through the playerlist.
This is similar to what you might need:

function autofill(text)
	for i,v in pairs(game.Players:GetPlayers()) do
		if string.find(v.Name, text) then
			return v.Name
		end
	end
end
6 Likes

Make sure to use ipairs because it’s faster than pairs.

This is funny, because I’ve actually been learning about finding string similarity fairly recently. Here’s two functions:

local function LevenshteinDistance(original: string, target: string) : number
	if original == target then return 0 end
	if original:len() < target:len() then return self:LevenshteinDistance(target, original) end

	if target:len() == 0 then return original:len() end -- original:len() >= target:len()
	
	local previous_row = generateRange(target:len()+1)
	for i, c1 in ipairs(original:split("")) do
		local current_row = {i}
		for j, c2 in ipairs(target:split("")) do
			local insertions = previous_row[j+1] + 1 -- j+1 instead of j since previous_row and current_row are one character longer
			local deletions = current_row[j] + 1   -- than target
			local substitutions = previous_row[j] + if c1~=c2 then 1 else 0
			insert(current_row, min(insertions, deletions, substitutions))
		end
		previous_row = current_row
	end
	
	return previous_row[#previous_row]
end

local function LevenshteinSimilarity(original: string, target: string) : number
	return (max(original:len(), target:len())-self:LevenshteinDistance(original, target))/max(original:len(), target:len())
end

The LevenshtienDistance function returns the amount of single-character edits that need to be made to the target string to transform it into the original string. The LevenshteinSimilarity function will return a number from 0 to 1 that will be a percentage of how much the two strings match.

Given this, you can loop through each player and compare their name the the current entered-in text in the textbox.

Edit:
You can also use these two functions for getting Jaro Distance. This is most likely preffered over levenshtien distance.

local function JaroSimilarity(original: string, target: string): number
	local original_len = original:len()
	local target_len = target:len()

	if (original_len == 0 and target_len == 0) or (original == target) then return 1 end

	local match_distance = (math.floor(math.max(original_len, target_len) / 2)) - 1
	local original_matches = table.create(original_len, false)
	local target_matches = table.create(target_len, false)

	local matches = 0
	local transpositions = 0
	
	local min = math.min
	local max = math.max
	for i = 1, original_len do
		local _start = max(1, i - match_distance)
		local _end = min(i + match_distance + 1, target_len)

		for j = _start, _end do
			if target_matches[j] then
				continue end
			if original:sub(i, i) ~= target:sub(j, j)  then
				continue end
			original_matches[i] = true
			target_matches[j] = true
			matches += 1
			break
		end
	end

	if matches == 0 then
		return 0
	end

	local k = 1
	for i = 1, original_len do
		if not original_matches[i] then continue end

		while target_matches[k] == false do
			k += 1
		end

		if original:sub(i, i) ~= target:sub(k, k) then
			transpositions += 1
		end
		k += 1
	end

	local similarity = ((matches / original_len) + (matches / target_len) + ((matches - transpositions / 2) / matches)) / 3

	return similarity
end

local function JaroDistance(original: string, target: string): number
	return 1 - JaroSimilarity(original, target)
end

I’d be willing to bet that unless you’re working with tables with thousands of entries the difference is negligible but it’s still a good habit to get into, yes.

local textbox = script.Parent

function autofill(text)
	local matches = {}
	local players = game.Players:GetPlayers()
	for i, player in ipairs(players) do
		if string.match(player.Name, "^"..textbox.Text) then
			table.insert(matches, string.match(player.Name, "^"..textbox.Text))
		end
		if i == #players then
			if #matches == 1 then
				return matches[1]
			end
		end
	end
end

Slight extension with string.match() & only providing 1 match, if multiple players are found then nothing is returned.

Thank you, how can I add like the gray text behind? like this image

Also I noticed that when I press Enter it doesn’t auto fill it
image

This happened because you had 12 matches as opposed to the expected 1 so nil was returned which you then attempted to assign to the “Text” property of the “InviteToParty” instance.

local textbox = script.Parent

function autofill(text)
	local matches = {}
	local players = game.Players:GetPlayers()
	for i, player in ipairs(players) do
		if string.match(player.Name, "^"..textbox.Text) then
			table.insert(matches, string.match(player.Name, "^"..textbox.Text))
		end
	end
	return matches[1]
end

This will return the first match found.

local textbox = script.Parent

function autofill(text)
	local matches = {}
	local players = game.Players:GetPlayers()
	for i, player in ipairs(players) do
		if string.match(player.Name, "^"..textbox.Text) then
			table.insert(matches, string.match(player.Name, "^"..textbox.Text))
		end
	end
	return table.concat(matches, ", ")
end

This will return all matches found concatenated into a single string separated by a comma followed by a whitespace.

Thank you, which method would be better to use? especially if a scenario appears where there’s two players with similar names e.g. “Player32132” and "Player3552