Clicking fires FocusLost when it should be firing MouseButton1Click

Hello all.

I am making a drop down, and it currently doesn’t work. Whenever I click on a material in the drop down, it thinks I’m clicking somewhere offscreen, and the focus is lost before the click is even finished.

Here is the barebones file:
Drop Down Not Working.rbxl (75.6 KB)

The local script should be under StarterGui → ScreenGui → Materials

Please feel free to ask any questions. I’ve been struggling all weekend with this issue, so thank you all in advance!

2 Likes

24 hours, time to bump this post. If someone is already working on it, I thank you immensely! The only thing that has worked so far is a delay, but that’s horrible practice.

1 Like

another 24 hours has passed. Since focus lost has a parameter that shows the input type, you can check if it was a click, and maybe the position of that click, and determine what button was under that click, and if it was one of the material names buttons. But this won’t work for touch screen laptops…

1 Like

just remove FocusLost connection, its completely useless and everything works fine without it

1 Like

no? if a player click a different button, I want the text inside the textbox to revert to what it was before the player cleared the text by clicking on the textbox if that makes sense. Or the player typed something in, but then wants to cancel by clicking off screen or pressing escape, that’s what the focus lost does. Also when the player presses enter after typing something in, that’s what the focus lost event is for.

1 Like

but you never even used MaterialTextBoxPreviousText variable so yes, it’s useless


*nor do you ever change MaterialTextBox.Name property

edit: nvm didnt see it

1 Like

check what happens at the top of the focused event. I think there should be a comment too, not sure though

Edit: no worries :D

Once you’ve seen it, let me explain how my code works:
MaterialTextBoxPreviousText is for the previous letter. It updates every time you type in a new letter. So if the player entered the wrong character (such as a number), you can quickly revert back.

I save what was inside the text box right as you clicked into MaterialTextBox.Name. Then I clear the text. Because MaterialTextBoxPreviousText doesn’t save the previous full text of the material that was there.

1 Like

10 tries later ..

--LocalScript in StarterPlayerScripts
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UIS = game:GetService("UserInputService")
local DropDownTextButtonTemplate = ReplicatedStorage:WaitForChild("DropDownTextButtonTemplate")

local MaterialFrame = script.Parent
local MaterialTextBox = MaterialFrame.Background1.TextBox
local DropDownScrollingFrameContainer = MaterialFrame.DropDownScrollingFrameContainer
local DropDownScrollingFrame = DropDownScrollingFrameContainer.DropDownScrollingFrame

local Materials = {
	"Asphalt","Basalt","Brick","Cardboard","Carpet","CeramicTiles","ClayRoofTiles","Cobblestone",
	"Concrete","CorrodedMetal","CrackedLava","DiamondPlate","Fabric","Foil","ForceField","Glacier",
	"Glass","Granite","Grass","Ground","Ice","LeafyGrass","Leather","Limestone","Marble","Metal",
	"Mud","Neon","Pavement","Pebble","Plaster","Plastic","Rock","RoofShingles","Rubber","Salt",
	"Sand","Sandstone","Slate","SmoothPlastic","Snow","Wood","WoodPlanks"
}

local ClearTextOnFocus = true
local insertCloneReturnWord = {}
local MaterialChangedConnection = nil
local MaterialTextBoxPreviousText = MaterialTextBox.Text
local skipNextOverwrite = false

local function SelectMaterial(name)
	skipNextOverwrite = true
	MaterialTextBox.Text = name
	MaterialTextBoxPreviousText = name
	DropDownScrollingFrameContainer.Visible = false
end

for i, word in ipairs(Materials) do
	local b = DropDownTextButtonTemplate:Clone()
	b.Name = word
	b.Text = word
	b.LayoutOrder = i
	b.BackgroundColor3 = (i % 2 == 1) and Color3.fromRGB(52,52,52) or Color3.fromRGB(49,49,49)
	insertCloneReturnWord[b] = word
	b.Parent = DropDownScrollingFrame
	b.MouseButton1Click:Connect(function()
		SelectMaterial(word)
	end)
end

local function MaterialTextBoxFocused()
	MaterialTextBoxPreviousText = MaterialTextBox.Text
	if ClearTextOnFocus then MaterialTextBox.Text = "" end

	DropDownScrollingFrameContainer.Visible = true
	for c in pairs(insertCloneReturnWord) do c.Visible = true end

	if MaterialChangedConnection then MaterialChangedConnection:Disconnect() end

	MaterialChangedConnection = MaterialTextBox:GetPropertyChangedSignal("Text"):Connect(function()
		if skipNextOverwrite then
			skipNextOverwrite = false
			return
		end

		local text = MaterialTextBox.Text:gsub("[^%a]", "")
		if text == "" then
			for c in pairs(insertCloneReturnWord) do c.Visible = true end
			MaterialTextBoxPreviousText = ""
		else
			local lower = text:lower()
			local matched = {}

			for _, w in ipairs(Materials) do
				if w:sub(1, #lower):lower() == lower then
					matched[w] = true
				end
			end

			for c, w in pairs(insertCloneReturnWord) do
				c.Visible = matched[w] == true
			end

			if next(matched) then
				MaterialTextBoxPreviousText = string.upper(lower:sub(1,1)) .. lower:sub(2)
			end
		end

		MaterialTextBox.Text = MaterialTextBoxPreviousText
	end)
end

MaterialTextBox.Focused:Connect(MaterialTextBoxFocused)

UIS.InputBegan:Connect(function(input, gp)
	if gp then return end

	if input.KeyCode == Enum.KeyCode.Return then
		local t = MaterialTextBoxPreviousText:lower()
		for _, w in ipairs(Materials) do
			if w:sub(1, #t):lower() == t then
				SelectMaterial(w)
				break
			end
		end
	end

	if input.KeyCode == Enum.KeyCode.Escape then
		MaterialTextBox.Text = MaterialTextBoxPreviousText
		DropDownScrollingFrameContainer.Visible = false
	end
end)

This one almost works.. it’s so close I could cry. If you hit enter twice it will take a few letters and make it the right choice. Going to have to start cheating here next.. I’ll leave that to your troll.

1 Like

a fix is to task.defer your FocusLost, since they happen at the same time, Clicking an option automatically loses focus on a button. Means you need to prioritize Button choosing first, so defer focus lost

1 Like

Only AI would format an array like that?
That is the only way to do that neatly. Also, I hardly care what you in particular have to say about anything at all, troll. I tried a lot of things.. Focus is one of them things that can drive you a bit nuts.

Also, if that was AI, it would have never written it like that; it would have used spaces. You can also see in that script where I think I may be getting sketchy by how it starts to spread out. I tend to get tighter with my confidence level in the chunk.

1 Like

clearly :joy:
you spelled later as latter (I understand you’re tired, don’t worry)

unfortunately, this code does not work. More precisely, clicking the buttons now does work (which is great!) but pressing escape or clicking off screen just kinda leaves it hanging. Also, entering the text “Br” and pressing enter doesn’t automatically select “Brick”…

1 Like

woah, I’ll have to look into that. Thanks for the suggestion!

1 Like

oof, don’t be so mean, he’s just trying to help any way he can :smiling_face_with_three_hearts:

1 Like

I had the functionality of being able to press enter, and it’d automatically select the first result of the list. Even if it was blank, it’d select asphalt. If you just type in the letter “C”, it’d choose the first material alphabetically that starts with a “C”.

1 Like

Why do you even have key submission + search functionality?
Knowing you can type few letters and select the option, seems useless to have a functionality to select an option by writing it’s name fully and pressing enter.

1 Like

I mean, you can write its name fully, or you can just type in the first few letters and press enter, and it’d find the first match in the array. Let me create a quick video for other people on this thread that haven’t might be reading this but haven’t downloaded the file.

This is with the old code, found by downloading the file of my original post at the very top:

I’m pressing “enter” here

1 Like

question: where would I put the task.defer?
This doesn’t work…
image

Edit: even if the focus lost function fires after the clicked function, the focus lost function would just overwrite the clicked function, rendering it useless… there needs to be some greater changes here, maybe a flag?

1 Like

well technically you can use a flag something like chosenByButton and when button is clicked, set that to true, in FocusLost proceed only if its false, else set it to false and return

1 Like

tried that, focus lost still somehow runs first…



1 Like

I’ve found an issue, it’s with the invisibility, how Roblox handles events on Invisible UIs, fix: just don’t close dropdown on FocusLost

1 Like