input (radio/password), max/min length, pattern
This commit is contained in:
1
Assets/Icons/radio.svg
Normal file
1
Assets/Icons/radio.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 134 134" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><ellipse cx="66.61" cy="66.646" rx="62.416" ry="62.478" style="fill:none;stroke:#000;stroke-width:8.33px;"/></svg>
|
||||
|
After Width: | Height: | Size: 579 B |
37
Assets/Icons/radio.svg.import
Normal file
37
Assets/Icons/radio.svg.import
Normal file
@@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b2v8ee23580c3"
|
||||
path="res://.godot/imported/radio.svg-320eafa791feaf0d1d926ec0d2ba3722.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Icons/radio.svg"
|
||||
dest_files=["res://.godot/imported/radio.svg-320eafa791feaf0d1d926ec0d2ba3722.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
Assets/Icons/radio_checked.svg
Normal file
1
Assets/Icons/radio_checked.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 134 134" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><ellipse cx="66.61" cy="66.646" rx="62.416" ry="62.478" style="fill:none;stroke:#3f77ce;stroke-width:8.33px;"/><ellipse cx="66.667" cy="66.646" rx="45.648" ry="45.693" style="fill:#3f77ce;"/></svg>
|
||||
|
After Width: | Height: | Size: 662 B |
37
Assets/Icons/radio_checked.svg.import
Normal file
37
Assets/Icons/radio_checked.svg.import
Normal file
@@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bj7bpovnm25ml"
|
||||
path="res://.godot/imported/radio_checked.svg-81396277cd631c074cae607c415d3a5c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Icons/radio_checked.svg"
|
||||
dest_files=["res://.godot/imported/radio_checked.svg-81396277cd631c074cae607c415d3a5c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
Assets/Icons/radio_checked_grayscale.svg
Normal file
1
Assets/Icons/radio_checked_grayscale.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:serif="http://www.serif.com/" width="100%" height="100%" viewBox="0 0 134 134" version="1.1" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><ellipse cx="66.61" cy="66.646" rx="62.416" ry="62.478" style="fill: none;stroke: #707070;stroke-width:8.33px;"/><ellipse cx="66.667" cy="66.646" rx="45.648" ry="45.693" style="fill: #707070;"/></svg>
|
||||
|
After Width: | Height: | Size: 513 B |
37
Assets/Icons/radio_checked_grayscale.svg.import
Normal file
37
Assets/Icons/radio_checked_grayscale.svg.import
Normal file
@@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://y1xqfcd8ro5t"
|
||||
path="res://.godot/imported/radio_checked_grayscale.svg-6ce9eb51f7fcbe2c1034ed12866d95cf.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Icons/radio_checked_grayscale.svg"
|
||||
dest_files=["res://.godot/imported/radio_checked_grayscale.svg-6ce9eb51f7fcbe2c1034ed12866d95cf.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
Assets/Icons/radio_disabled.svg
Normal file
1
Assets/Icons/radio_disabled.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 134 134" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><ellipse cx="66.61" cy="66.646" rx="62.416" ry="62.478" style="fill:none;stroke:#707070;stroke-width:8.33px;"/></svg>
|
||||
|
After Width: | Height: | Size: 582 B |
37
Assets/Icons/radio_disabled.svg.import
Normal file
37
Assets/Icons/radio_disabled.svg.import
Normal file
@@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bs414mrvwdmcn"
|
||||
path="res://.godot/imported/radio_disabled.svg-04a182ffa1f439025aa6457482c84d92.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://Assets/Icons/radio_disabled.svg"
|
||||
dest_files=["res://.godot/imported/radio_disabled.svg-04a182ffa1f439025aa6457482c84d92.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
@@ -6,7 +6,8 @@ TODO:
|
||||
5. **Store** tab containers so switching tabs won't erase previous tab.
|
||||
6. **GIF** support
|
||||
7. **Video** support via [GDE GoZen](https://github.com/VoylinsGamedevJourney/gde_gozen)
|
||||
8. **More input types** (password, email, number, etc.)
|
||||
8. **More input types** (url, tel, date, time, etc.)
|
||||
9. **Required** attribute for inputs
|
||||
|
||||
Issues:
|
||||
1. **< br />** counts as 1 element in **WebsiteContainer**, therefore despite being (0,0) in size, it counts as double in spacing.
|
||||
@@ -1,9 +1,13 @@
|
||||
[gd_resource type="Theme" load_steps=17 format=3 uid="uid://bn6rbmdy60lhr"]
|
||||
[gd_resource type="Theme" load_steps=21 format=3 uid="uid://bn6rbmdy60lhr"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://dn4dxn8hkrd64" path="res://Assets/Icons/checkbox.svg" id="1_75mhk"]
|
||||
[ext_resource type="Texture2D" uid="uid://b6ucuyluuw43" path="res://Assets/Icons/checkbox_pressed_grayscale.svg" id="2_2abar"]
|
||||
[ext_resource type="Texture2D" uid="uid://c5scqw224r2e5" path="res://Assets/Icons/checkbox_pressed.svg" id="2_3k2jb"]
|
||||
[ext_resource type="Texture2D" uid="uid://b2v8ee23580c3" path="res://Assets/Icons/radio.svg" id="3_3weog"]
|
||||
[ext_resource type="Texture2D" uid="uid://bap17ryrkcyey" path="res://Assets/Icons/checkbox_disabled.svg" id="4_c32on"]
|
||||
[ext_resource type="Texture2D" uid="uid://y1xqfcd8ro5t" path="res://Assets/Icons/radio_checked_grayscale.svg" id="4_n77xs"]
|
||||
[ext_resource type="Texture2D" uid="uid://bj7bpovnm25ml" path="res://Assets/Icons/radio_checked.svg" id="4_sesrd"]
|
||||
[ext_resource type="Texture2D" uid="uid://bs414mrvwdmcn" path="res://Assets/Icons/radio_disabled.svg" id="6_r011l"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_c32on"]
|
||||
|
||||
@@ -77,6 +81,10 @@ Button/styles/hover = SubResource("StyleBoxFlat_7g0pl")
|
||||
Button/styles/normal = SubResource("StyleBoxFlat_c32on")
|
||||
CheckBox/icons/checked = ExtResource("2_3k2jb")
|
||||
CheckBox/icons/checked_disabled = ExtResource("2_2abar")
|
||||
CheckBox/icons/radio_checked = ExtResource("4_sesrd")
|
||||
CheckBox/icons/radio_checked_disabled = ExtResource("4_n77xs")
|
||||
CheckBox/icons/radio_unchecked = ExtResource("3_3weog")
|
||||
CheckBox/icons/radio_unchecked_disabled = ExtResource("6_r011l")
|
||||
CheckBox/icons/unchecked = ExtResource("1_75mhk")
|
||||
CheckBox/icons/unchecked_disabled = ExtResource("4_c32on")
|
||||
CheckBox/styles/focus = SubResource("StyleBoxEmpty_75mhk")
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://c7yay102a3b4c"]
|
||||
[gd_scene load_steps=4 format=3 uid="uid://c7yay102a3b4c"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://kv6ebscarj2e" path="res://Scripts/Tags/input.gd" id="1_input"]
|
||||
[ext_resource type="Theme" uid="uid://bn6rbmdy60lhr" path="res://Scenes/Styles/BrowserText.tres" id="2_theme"]
|
||||
[ext_resource type="ButtonGroup" uid="uid://dgvdef1uht5ht" path="res://Scenes/Tags/new_button_group.tres" id="3_a88g6"]
|
||||
|
||||
[node name="Input" type="Control"]
|
||||
layout_mode = 3
|
||||
@@ -21,6 +22,7 @@ layout_mode = 1
|
||||
offset_right = 400.0
|
||||
offset_bottom = 35.0
|
||||
theme = ExtResource("2_theme")
|
||||
text = "test"
|
||||
placeholder_text = "Enter text..."
|
||||
caret_blink = true
|
||||
|
||||
@@ -32,3 +34,13 @@ offset_bottom = 31.0
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_constants/icon_max_width = 24
|
||||
flat = true
|
||||
|
||||
[node name="RadioButton" type="CheckBox" parent="."]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_right = 31.0
|
||||
offset_bottom = 31.0
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_constants/icon_max_width = 24
|
||||
button_group = ExtResource("3_a88g6")
|
||||
flat = true
|
||||
|
||||
45
Scenes/Tags/input.tscn8601746517.tmp
Normal file
45
Scenes/Tags/input.tscn8601746517.tmp
Normal file
@@ -0,0 +1,45 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://c7yay102a3b4c"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://kv6ebscarj2e" path="res://Scripts/Tags/input.gd" id="1_input"]
|
||||
[ext_resource type="Theme" uid="uid://bn6rbmdy60lhr" path="res://Scenes/Styles/BrowserText.tres" id="2_theme"]
|
||||
[ext_resource type="ButtonGroup" uid="uid://dgvdef1uht5ht" path="res://Scenes/Tags/new_button_group.tres" id="3_a88g6"]
|
||||
|
||||
[node name="Input" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_right = 400.0
|
||||
offset_bottom = 31.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 0
|
||||
script = ExtResource("1_input")
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
offset_right = 400.0
|
||||
offset_bottom = 35.0
|
||||
theme = ExtResource("2_theme")
|
||||
placeholder_text = "Enter text..."
|
||||
caret_blink = true
|
||||
|
||||
[node name="CheckBox" type="CheckBox" parent="."]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_right = 31.0
|
||||
offset_bottom = 31.0
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_constants/icon_max_width = 24
|
||||
flat = true
|
||||
|
||||
[node name="RadioButton" type="CheckBox" parent="."]
|
||||
layout_mode = 0
|
||||
offset_right = 31.0
|
||||
offset_bottom = 31.0
|
||||
theme = ExtResource("2_theme")
|
||||
theme_override_constants/icon_max_width = 24
|
||||
button_group = ExtResource("3_a88g6")
|
||||
flat = true
|
||||
3
Scenes/Tags/new_button_group.tres
Normal file
3
Scenes/Tags/new_button_group.tres
Normal file
@@ -0,0 +1,3 @@
|
||||
[gd_resource type="ButtonGroup" format=3 uid="uid://dgvdef1uht5ht"]
|
||||
|
||||
[resource]
|
||||
@@ -1,23 +1,93 @@
|
||||
extends Control
|
||||
static var button_groups: Dictionary = {}
|
||||
|
||||
func init(element: HTMLParser.HTMLElement) -> void:
|
||||
var line_edit: LineEdit = $LineEdit
|
||||
var check_box: CheckBox = $CheckBox
|
||||
var radio_button: CheckBox = $RadioButton
|
||||
|
||||
var input_type = element.get_attribute("type").to_lower()
|
||||
var placeholder = element.get_attribute("placeholder")
|
||||
var value = element.get_attribute("value")
|
||||
var group = element.get_attribute("group")
|
||||
var minlength = element.get_attribute("minlength")
|
||||
var maxlength = element.get_attribute("maxlength")
|
||||
var pattern = element.get_attribute("pattern")
|
||||
|
||||
# Hide all inputs initially
|
||||
line_edit.visible = false
|
||||
check_box.visible = false
|
||||
radio_button.visible = false
|
||||
|
||||
match input_type:
|
||||
"checkbox":
|
||||
line_edit.visible = false
|
||||
check_box.visible = true
|
||||
if value and value == "true": check_box.button_pressed = true
|
||||
custom_minimum_size = check_box.size
|
||||
"radio":
|
||||
radio_button.visible = true
|
||||
radio_button.toggle_mode = true
|
||||
if value and value == "true": radio_button.button_pressed = true
|
||||
custom_minimum_size = radio_button.size
|
||||
|
||||
if group.length() > 0:
|
||||
if not button_groups.has(group):
|
||||
button_groups[group] = ButtonGroup.new()
|
||||
radio_button.button_group = button_groups[group]
|
||||
"password":
|
||||
line_edit.visible = true
|
||||
line_edit.secret = true
|
||||
custom_minimum_size = line_edit.size
|
||||
setup_text_input(line_edit, placeholder, value, minlength, maxlength, pattern)
|
||||
_: # Default to text input
|
||||
line_edit.visible = true
|
||||
check_box.visible = false
|
||||
line_edit.secret = false
|
||||
custom_minimum_size = line_edit.size
|
||||
|
||||
if placeholder: line_edit.placeholder_text = placeholder
|
||||
if value: line_edit.text = value
|
||||
setup_text_input(line_edit, placeholder, value, minlength, maxlength, pattern)
|
||||
|
||||
func setup_text_input(line_edit: LineEdit, placeholder: String, value: String, minlength: String, maxlength: String, pattern: String) -> void:
|
||||
if placeholder: line_edit.placeholder_text = placeholder
|
||||
if value: line_edit.text = value
|
||||
|
||||
line_edit.max_length = maxlength.to_int()
|
||||
|
||||
if minlength.length() > 0 or pattern.length() > 0:
|
||||
line_edit.text_changed.connect(_on_text_changed.bind(minlength, pattern))
|
||||
|
||||
func _on_text_changed(new_text: String, minlength: String, pattern: String) -> void:
|
||||
var line_edit = get_node("LineEdit") as LineEdit
|
||||
var is_valid = true
|
||||
|
||||
# Check minimum length
|
||||
if minlength.length() > 0 and minlength.is_valid_int():
|
||||
var min_len = minlength.to_int()
|
||||
if new_text.length() < min_len and new_text.length() > 0:
|
||||
is_valid = false
|
||||
|
||||
# Check pattern (regex)
|
||||
if pattern.length() > 0 and new_text.length() > 0:
|
||||
var regex = RegEx.new()
|
||||
if regex.compile(pattern) == OK:
|
||||
if not regex.search(new_text):
|
||||
is_valid = false
|
||||
|
||||
if is_valid:
|
||||
# Reset to default styles
|
||||
line_edit.remove_theme_stylebox_override("normal")
|
||||
line_edit.remove_theme_stylebox_override("focus")
|
||||
line_edit.modulate = Color.WHITE
|
||||
else:
|
||||
var normal_style = create_red_border_style_from_theme(line_edit, "normal")
|
||||
var focus_style = create_red_border_style_from_theme(line_edit, "focus")
|
||||
|
||||
line_edit.add_theme_stylebox_override("normal", normal_style)
|
||||
line_edit.add_theme_stylebox_override("focus", focus_style)
|
||||
line_edit.modulate = Color.WHITE
|
||||
|
||||
func create_red_border_style_from_theme(line_edit: LineEdit, style_name: String) -> StyleBoxFlat:
|
||||
var original_style: StyleBoxFlat = line_edit.get_theme_stylebox(style_name)
|
||||
var style: StyleBoxFlat = original_style.duplicate()
|
||||
|
||||
style.border_color = Color.RED
|
||||
|
||||
return style
|
||||
|
||||
174
Scripts/main.gd
174
Scripts/main.gd
@@ -74,15 +74,28 @@ both spaces and
|
||||
line breaks
|
||||
</pre>
|
||||
|
||||
<form>
|
||||
<!-- action, method, and type=submit are for when we implement Lua -->
|
||||
<form action=\"/submit\" method=\"POST\">
|
||||
<span>Name:</span>
|
||||
<input type=\"text\" placeholder=\"First name\" value=\"John\" />
|
||||
<span>Surname:</span>
|
||||
<input type=\"text\" placeholder=\"Last name\" value=\"Doe\" />
|
||||
<input type=\"text\" placeholder=\"First name\" value=\"John\" maxlength=\"20\" minlength=\"3\" />
|
||||
<span>Email regex:</span>
|
||||
<input type=\"text\" placeholder=\"Last name\" value=\"Doe\" pattern=\"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\" />
|
||||
<span>Smart:</span>
|
||||
<input type=\"checkbox\" />
|
||||
<input type=\"checkbox\" value=\"true\" />
|
||||
<button>Submit</button>
|
||||
|
||||
<p>favorite food</p>
|
||||
<input type=\"radio\" group=\"food\" />
|
||||
<span>Pizza</span>
|
||||
<input type=\"radio\" group=\"food\" />
|
||||
<span>Berry</span>
|
||||
<input type=\"radio\" group=\"food\" />
|
||||
<span>Gary</span>
|
||||
|
||||
<input type=\"password\" placeholder=\"your password...\" />
|
||||
<button type=\"submit\">Submit</button>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
<separator direction=\"horizontal\" />
|
||||
@@ -138,89 +151,14 @@ line breaks
|
||||
|
||||
continue
|
||||
|
||||
match element.tag_name:
|
||||
"p":
|
||||
var p = P.instantiate()
|
||||
p.init(element)
|
||||
website_container.add_child(p)
|
||||
if contains_hyperlink(element):
|
||||
p.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
"h1":
|
||||
var h1 = H1.instantiate()
|
||||
h1.init(element)
|
||||
website_container.add_child(h1)
|
||||
if contains_hyperlink(element):
|
||||
h1.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
"h2":
|
||||
var h2 = H2.instantiate()
|
||||
h2.init(element)
|
||||
website_container.add_child(h2)
|
||||
if contains_hyperlink(element):
|
||||
h2.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
"h3":
|
||||
var h3 = H3.instantiate()
|
||||
h3.init(element)
|
||||
website_container.add_child(h3)
|
||||
if contains_hyperlink(element):
|
||||
h3.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
"h4":
|
||||
var h4 = H4.instantiate()
|
||||
h4.init(element)
|
||||
website_container.add_child(h4)
|
||||
if contains_hyperlink(element):
|
||||
h4.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
"h5":
|
||||
var h5 = H5.instantiate()
|
||||
h5.init(element)
|
||||
website_container.add_child(h5)
|
||||
if contains_hyperlink(element):
|
||||
h5.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
"h6":
|
||||
var h6 = H6.instantiate()
|
||||
h6.init(element)
|
||||
website_container.add_child(h6)
|
||||
if contains_hyperlink(element):
|
||||
h6.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
"pre":
|
||||
var pre = PRE.instantiate()
|
||||
pre.init(element)
|
||||
website_container.add_child(pre)
|
||||
"br":
|
||||
var br = BR.instantiate()
|
||||
br.init(element)
|
||||
website_container.add_child(br)
|
||||
"img":
|
||||
var img = IMG.instantiate()
|
||||
img.init(element)
|
||||
website_container.add_child(img)
|
||||
"separator":
|
||||
var separator = SEPARATOR.instantiate()
|
||||
separator.init(element)
|
||||
website_container.add_child(separator)
|
||||
"form":
|
||||
var form = FORM.instantiate()
|
||||
form.init(element)
|
||||
website_container.add_child(form)
|
||||
|
||||
# Render form children
|
||||
for child_element in element.children:
|
||||
var child_node = create_element_node(child_element)
|
||||
if child_node:
|
||||
form.add_child(child_node)
|
||||
"input":
|
||||
var input = INPUT.instantiate()
|
||||
input.init(element)
|
||||
website_container.add_child(input)
|
||||
"button":
|
||||
var button = BUTTON.instantiate()
|
||||
button.init(element)
|
||||
website_container.add_child(button)
|
||||
"span":
|
||||
var span = SPAN.instantiate()
|
||||
span.init(element)
|
||||
website_container.add_child(span)
|
||||
_:
|
||||
print("Couldn't parse unsupported HTML tag \"%s\"" % element.tag_name)
|
||||
var element_node = create_element_node(element)
|
||||
if element_node:
|
||||
website_container.add_child(element_node)
|
||||
# Handle hyperlinks for all elements
|
||||
if contains_hyperlink(element) and element_node.has_method("get") and element_node.get("rich_text_label"):
|
||||
element_node.rich_text_label.meta_clicked.connect(func(meta): OS.shell_open(str(meta)))
|
||||
else:
|
||||
print("Couldn't parse unsupported HTML tag \"%s\"" % element.tag_name)
|
||||
|
||||
i += 1
|
||||
|
||||
@@ -254,18 +192,60 @@ func contains_hyperlink(element: HTMLParser.HTMLElement) -> bool:
|
||||
return false
|
||||
|
||||
func create_element_node(element: HTMLParser.HTMLElement) -> Control:
|
||||
var node: Control = null
|
||||
|
||||
match element.tag_name:
|
||||
"p":
|
||||
node = P.instantiate()
|
||||
node.init(element)
|
||||
"h1":
|
||||
node = H1.instantiate()
|
||||
node.init(element)
|
||||
"h2":
|
||||
node = H2.instantiate()
|
||||
node.init(element)
|
||||
"h3":
|
||||
node = H3.instantiate()
|
||||
node.init(element)
|
||||
"h4":
|
||||
node = H4.instantiate()
|
||||
node.init(element)
|
||||
"h5":
|
||||
node = H5.instantiate()
|
||||
node.init(element)
|
||||
"h6":
|
||||
node = H6.instantiate()
|
||||
node.init(element)
|
||||
"pre":
|
||||
node = PRE.instantiate()
|
||||
node.init(element)
|
||||
"br":
|
||||
node = BR.instantiate()
|
||||
node.init(element)
|
||||
"img":
|
||||
node = IMG.instantiate()
|
||||
node.init(element)
|
||||
"separator":
|
||||
node = SEPARATOR.instantiate()
|
||||
node.init(element)
|
||||
"form":
|
||||
node = FORM.instantiate()
|
||||
node.init(element)
|
||||
|
||||
for child_element in element.children:
|
||||
var child_node = create_element_node(child_element)
|
||||
if child_node:
|
||||
node.add_child(child_node)
|
||||
"input":
|
||||
var input = INPUT.instantiate()
|
||||
input.init(element)
|
||||
return input
|
||||
node = INPUT.instantiate()
|
||||
node.init(element)
|
||||
"button":
|
||||
var button = BUTTON.instantiate()
|
||||
button.init(element)
|
||||
return button
|
||||
node = BUTTON.instantiate()
|
||||
node.init(element)
|
||||
"span":
|
||||
var span = SPAN.instantiate()
|
||||
span.init(element)
|
||||
return span
|
||||
node = SPAN.instantiate()
|
||||
node.init(element)
|
||||
_:
|
||||
return null
|
||||
|
||||
return node
|
||||
|
||||
Reference in New Issue
Block a user