Creating HYPERLINKS (for internal documentation)

I’m developing an INTERNAL Online Help for my game, ie, a manual inside Frames (because Roblox blocks access to EXTERNAL hyperlinks).

So I have a frame with a TextLabel like this:

image

As in HTML Links Hyperlinks, I would like that when the player hovers over the link it changes color and when he clicks on the link it opens another frame.

But I came across this limitation of Roblox, which doesn’t allow to the creation of hyperlinks.

I also noticed that the seamless concatenation between objects of type TextLabel and TextButton is a very annoying thing to do manually.


So I decided to come up with a solution for this, where, providing a single TextLabel like this…

… and creating something like this…

To get to this result, you must provide an original TextLabel containing your normal text, but wrapping the part of the text you want to hyperlink with the same HTML syntax.
Example:

<a href="link1">Click here</a> or also <a href="link2">click on this link</a> to open some links.

So here’s the code you can put on your LocalScript:

-- from: rogeriodec_games

local function Hyperlinks(TextLabel, LinkColor, HoverColor)

	local function ExtractTextAndLinks(String)
		local Sequence = {}
		repeat
			local PosOpenA = string.find(String, '<a', 1)
			if PosOpenA then
				if PosOpenA > 1 then 
					local Text = string.sub(String, 1, PosOpenA-1)
					table.insert(Sequence, {Type = 'Text', Text = Text})
				end
				local PosCloseA = string.find(String, '</a>', PosOpenA+2)
				if not PosCloseA then
					warn('No closing </a>')
					return
				end
				local Tag = string.sub(String, PosOpenA, PosCloseA+3)
				local PosHref = string.find(Tag, 'href', 4)
				if not PosHref then
					warn('No href')
					return
				end
				local Key = Tag:split('"')
				if #Key ~= 3 then
					warn('Incomplete quotes on href')
					return
				end
				local Href = Key[2]
				local PosCloseA2 = string.find(Key[3], '</a>', 1)
				local Text = string.sub(Key[3], 2, PosCloseA2-1)
				table.insert(Sequence, {Type = 'Link', Href = Href, Text = Text})
				String = string.sub(String, PosCloseA+4)			
			end
		until not PosOpenA
		if String then
			table.insert(Sequence, {Type = 'Text', Text = String})
		end
		return Sequence
	end
	
	local function Trim(str)
		return string.gsub(str, "^%s*(.-)%s*$", "%1")
	end
	
	local Sequence = ExtractTextAndLinks(TextLabel.Text)
	if #Sequence == 1 and Sequence[1].Type == 'Text' then return end

	local Pos = Vector2.new(0, 0)
	
	for Id, Object in ipairs(Sequence) do
		local Type = Object.Type == 'Link' and 'TextButton' or 'TextLabel'
		local Text = Instance.new(Type)
		Text.Name = string.format("%02i", Id) .. '_' .. Type 
		Text.Parent = TextLabel.Parent
		Text.AutomaticSize = TextLabel.AutomaticSize
		Text.BackgroundColor3 = TextLabel.BackgroundColor3
		Text.BorderColor3 = TextLabel.BorderColor3
		Text.BorderMode = TextLabel.BorderMode
		Text.BorderSizePixel = TextLabel.BorderSizePixel
		Text.LayoutOrder = TextLabel.LayoutOrder
		Text.SizeConstraint = TextLabel.SizeConstraint
		Text.Visible = TextLabel.Visible
		Text.ZIndex = TextLabel.ZIndex
		Text.AutoLocalize = TextLabel.AutoLocalize
		Text.BackgroundTransparency = TextLabel.BackgroundTransparency
		Text.FontFace = TextLabel.FontFace
		Text.RichText = true
		Text.Text = Object.Text
		Text.TextColor3 = TextLabel.TextColor3
		Text.TextSize = TextLabel.TextSize
		Text.TextStrokeColor3 = TextLabel.TextStrokeColor3
		Text.TextStrokeTransparency = TextLabel.TextStrokeTransparency
		Text.TextTransparency = TextLabel.TextTransparency
		Text.TextTruncate = TextLabel.TextTruncate
		Text.TextXAlignment = TextLabel.TextXAlignment
		Text.TextYAlignment = TextLabel.TextYAlignment
		Text.Position = UDim2.new(0, Pos.X, 0, Pos.Y)
		
		local Size
		local Text2 = ''
		repeat		
			Size = Text.TextBounds
			Text.Size = UDim2.new(0, Size.X, 0, Size.Y)
			if Pos.X + Size.X > TextLabel.Parent.AbsoluteSize.X then -- whether text must be wrapped
				if Object.Type == 'Link' then
					Pos = Vector2.new(0, Pos.Y + Size.Y)
					--Size = Vector2.new(0, 0)
					Text.Position = UDim2.new(0, 0, 0, Pos.Y)
				else
					repeat
						local Char = string.sub(Text.Text, -1)
						Text.Text = string.sub(Text.Text, 1, string.len(Text.Text) - 1)
						Text2 = Char .. Text2
					until not Char or Char == ' '
				end
			elseif Text2 ~= '' then
				Text2 = Trim(Text2)
				table.insert(Sequence, Id + 1, {Type = 'Text', Text = Text2})
				Pos = Vector2.new(0, Pos.Y + Size.Y)
				Size = Vector2.new(0, 0)
				Text2 = ''
			end
		until Text2 == ''
		Pos += Vector2.new(Size.X, 0)
		if Type == 'TextButton' then
			Text.Text = '<u>' .. Text.Text .. '</u>'
			if LinkColor then Text.TextColor3 = LinkColor end
			local TextColor3 = Text.TextColor3

			Text.MouseEnter:Connect(function()
				if HoverColor then Text.TextColor3 = HoverColor end
			end)

			Text.MouseLeave:Connect(function()
				Text.TextColor3 = TextColor3
			end)

			Text.MouseButton1Down:Connect(function()
				print(Object.Href)
			end)

		end
	end
	
	TextLabel:Destroy() -- remove the original TextLabel (with HTML Tags)
end

-- START ---

local TextLabel = game.Players.LocalPlayer.PlayerGui.ScreenGui.Frame2.TextLabel -- your original TextLabel (with the HTML tags)
Hyperlinks(TextLabel, Color3.fromRGB(255, 0, 0), Color3.fromRGB(127, 127, 127)) -- create many TextLabels and TextButtons as children of the same original TextLabel's Parent

Edit v1.2

Did some improvements to wrap the resulting text when its size is greater than its Parent’s size:

image

18 Likes

Wouldn’t just be easier to simply use RichText by default, and just add in the Input functions instead of creating a whole module that converts HTML, or am I understanding this wrong.

1 Like

:point_up_2:t2:


Hyperlinks lead to sites (or experiences in roblox), it does not seem like this does that.

Anyways, Great Tutorial.

Hyperlinks lead to ANYTHING, depending on where’s your content.
Here I’m using the same concept of the HTML to lead to a internal documentation (Frames).

1 Like

However doesn’t it seem tedious to use HTML in a place where it’s not meant to be used?

thanks for this amazing [Hyperlink Blocked] tutorial!!!

3 Likes

This is useless considering you can’t actually make it lead to anywhere.

2 Likes

@sasqwothlives @mutedarlo
Sorry, it wasn’t clear at the beginning that it was to be used in an internal manual inside the game, with frames.
I changed the initial sentence in the OP.

If it did then there would be a lot of scammers sending users to off-site fake robux scam sites

1 Like

Works well however it doesn’t support line breaks/new line characters. The order get’s all jacked up.
image

Am I doing something wrong or is a space here unsupported?
image

RichText is also using a HTML-inspired syntax.

SmartSelect_20221016_083925_Chrome

This module basically creates a hyperlink effect and allows you to execute code on clicking.

2 Likes

did you find a fix for this?

im having the same problem