DOM manipulation (insertBefore, insertAfter, replace, clone) (parent, nextSibling, previousSibling, firstChild, lastChild)
This commit is contained in:
@@ -138,21 +138,21 @@ func add_element_methods(vm: LuauVM, index: String = "element") -> void:
|
||||
vm.lua_pushcallable(_element_set_attribute_handler, index + ".setAttribute")
|
||||
vm.lua_setfield(-2, "setAttribute")
|
||||
|
||||
# Create metatable for property access
|
||||
vm.lua_newtable() # metatable
|
||||
LuaDOMUtils.add_enhanced_element_methods(vm, self, index)
|
||||
|
||||
# __index method for property getters
|
||||
vm.lua_pushcallable(_element_index_handler, index + ".__index")
|
||||
vm.lua_newtable()
|
||||
|
||||
vm.lua_pushcallable(_index_handler, index + ".__index")
|
||||
vm.lua_setfield(-2, "__index")
|
||||
|
||||
# __newindex method for property setters
|
||||
vm.lua_pushcallable(_element_newindex_handler, index + ".__newindex")
|
||||
vm.lua_setfield(-2, "__newindex")
|
||||
|
||||
# Set metatable on element table
|
||||
vm.lua_setmetatable(-2)
|
||||
|
||||
# Property access handlers
|
||||
func _index_handler(vm: LuauVM) -> int:
|
||||
return LuaDOMUtils._index_handler(vm, self)
|
||||
|
||||
func _element_index_handler(vm: LuauVM) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
var key: String = vm.luaL_checkstring(2)
|
||||
@@ -406,6 +406,35 @@ func _element_classlist_remove_wrapper(vm: LuauVM) -> int:
|
||||
func _element_classlist_toggle_wrapper(vm: LuauVM) -> int:
|
||||
return LuaClassListUtils.element_classlist_toggle_handler(vm, dom_parser)
|
||||
|
||||
# DOM manipulation wrapper functions
|
||||
func _element_insert_before_wrapper(vm: LuauVM) -> int:
|
||||
return LuaDOMUtils.insert_before_handler(vm, dom_parser, self)
|
||||
|
||||
func _element_insert_after_wrapper(vm: LuauVM) -> int:
|
||||
return LuaDOMUtils.insert_after_handler(vm, dom_parser, self)
|
||||
|
||||
func _element_replace_wrapper(vm: LuauVM) -> int:
|
||||
return LuaDOMUtils.replace_handler(vm, dom_parser, self)
|
||||
|
||||
func _element_clone_wrapper(vm: LuauVM) -> int:
|
||||
return LuaDOMUtils.clone_handler(vm, dom_parser, self)
|
||||
|
||||
# DOM traversal property wrapper functions
|
||||
func _get_element_parent_wrapper(vm: LuauVM, lua_api: LuaAPI) -> int:
|
||||
return LuaDOMUtils.get_element_parent_handler(vm, dom_parser, lua_api)
|
||||
|
||||
func _get_element_next_sibling_wrapper(vm: LuauVM, lua_api: LuaAPI) -> int:
|
||||
return LuaDOMUtils.get_element_next_sibling_handler(vm, dom_parser, lua_api)
|
||||
|
||||
func _get_element_previous_sibling_wrapper(vm: LuauVM, lua_api: LuaAPI) -> int:
|
||||
return LuaDOMUtils.get_element_previous_sibling_handler(vm, dom_parser, lua_api)
|
||||
|
||||
func _get_element_first_child_wrapper(vm: LuauVM, lua_api: LuaAPI) -> int:
|
||||
return LuaDOMUtils.get_element_first_child_handler(vm, dom_parser, lua_api)
|
||||
|
||||
func _get_element_last_child_wrapper(vm: LuauVM, lua_api: LuaAPI) -> int:
|
||||
return LuaDOMUtils.get_element_last_child_handler(vm, dom_parser, lua_api)
|
||||
|
||||
func _render_new_element(element: HTMLParser.HTMLElement, parent_node: Node) -> void:
|
||||
# Get reference to main scene for rendering
|
||||
var main_scene = get_node("/root/Main")
|
||||
|
||||
@@ -797,6 +797,79 @@ var HTML_CONTENT_ADD_REMOVE = """<head>
|
||||
</body>
|
||||
""".to_utf8_buffer()
|
||||
|
||||
var HTML_CONTENT_DOM_MANIPULATION = """
|
||||
<head>
|
||||
<title>DOM Utilities Test</title>
|
||||
<style>
|
||||
.test-item { bg-[#e0e7ef] text-[#22223b] rounded p-2 mb-2 }
|
||||
.highlight { bg-[#ffd700] }
|
||||
</style>
|
||||
<script>
|
||||
local log = gurt.select("#log")
|
||||
local function log_msg(msg)
|
||||
log.text = log.text .. msg .. "\\n"
|
||||
end
|
||||
|
||||
local parent = gurt.select("#parent")
|
||||
local child1 = gurt.select("#child1")
|
||||
local child2 = gurt.select("#child2")
|
||||
local child3 = gurt.select("#child3")
|
||||
print(log)
|
||||
-- Show DOM property usage
|
||||
log.text = ""
|
||||
log_msg("parent of child2: " .. table.tostring(child2.parent))
|
||||
log_msg("nextSibling of child2: " .. table.tostring(child2.nextSibling))
|
||||
log_msg("previousSibling of child2: " .. table.tostring(child2.previousSibling))
|
||||
log_msg("firstChild of parent: " .. table.tostring(parent.firstChild))
|
||||
log_msg("lastChild of parent: " .. table.tostring(parent.lastChild))
|
||||
|
||||
-- Insert Before
|
||||
gurt.select("#btn-insert-before"):on("click", function()
|
||||
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Inserted Before Child 2" })
|
||||
parent:insertBefore(newDiv, child2)
|
||||
log_msg("Inserted before child2: " .. newDiv._element_id)
|
||||
end)
|
||||
|
||||
-- Insert After
|
||||
gurt.select("#btn-insert-after"):on("click", function()
|
||||
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Inserted After Child 2" })
|
||||
parent:insertAfter(newDiv, child2)
|
||||
log_msg("Inserted after child2: " .. newDiv._element_id)
|
||||
end)
|
||||
|
||||
-- Replace
|
||||
gurt.select("#btn-replace"):on("click", function()
|
||||
local newDiv = gurt.create("div", { class = "test-item highlight", text = "Replacement for Child 2" })
|
||||
parent:replace(newDiv, child2)
|
||||
log_msg("Replaced child2 with: " .. newDiv._element_id)
|
||||
end)
|
||||
|
||||
-- Clone
|
||||
gurt.select("#btn-clone"):on("click", function()
|
||||
local clone = child3:clone(true)
|
||||
parent:append(clone)
|
||||
log_msg("Cloned child3: " .. clone._element_id)
|
||||
end)
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>DOM Utilities Demo</h1>
|
||||
<div id="parent" style="bg-[#f8fafc] p-4 rounded flex flex-col gap-2">
|
||||
<div class="test-item">Non-interactible</div>
|
||||
<div id="child1" class="test-item">Child 1</div>
|
||||
<div id="child2" class="test-item">Child 2</div>
|
||||
<div id="child3" class="test-item">Child 3</div>
|
||||
</div>
|
||||
<div style="flex gap-2 mt-4">
|
||||
<button id="btn-insert-before">Insert Before Child 2</button>
|
||||
<button id="btn-insert-after">Insert After Child 2</button>
|
||||
<button id="btn-replace">Replace Child 2</button>
|
||||
<button id="btn-clone">Clone Child 3</button>
|
||||
</div>
|
||||
<p id="log" style="mt-4 text-[#444] text-sm">Test</p>
|
||||
</body>
|
||||
""".to_utf8_buffer()
|
||||
|
||||
var HTML_CONTENT = """<head>
|
||||
<title>Signal API Demo</title>
|
||||
<icon src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cf/Lua-Logo.svg/256px-Lua-Logo.svg.png">
|
||||
|
||||
@@ -4,6 +4,9 @@ func fetch_image(url: String) -> ImageTexture:
|
||||
var http_request = HTTPRequest.new()
|
||||
add_child(http_request)
|
||||
|
||||
if url.is_empty():
|
||||
return null
|
||||
|
||||
var error = http_request.request(url)
|
||||
if error != OK:
|
||||
print("Error making HTTP request: ", error)
|
||||
|
||||
494
flumi/Scripts/Utils/Lua/DOM.gd
Normal file
494
flumi/Scripts/Utils/Lua/DOM.gd
Normal file
@@ -0,0 +1,494 @@
|
||||
class_name LuaDOMUtils
|
||||
extends RefCounted
|
||||
|
||||
# DOM traversal properties (read-only)
|
||||
static func get_element_parent_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api: LuaAPI) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = find_element_by_id(element_id, dom_parser)
|
||||
if not element or not element.parent:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
create_element_wrapper(vm, element.parent, lua_api)
|
||||
return 1
|
||||
|
||||
static func get_element_next_sibling_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api: LuaAPI) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = find_element_by_id(element_id, dom_parser)
|
||||
if not element or not element.parent:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
var siblings = element.parent.children
|
||||
var current_index = siblings.find(element)
|
||||
|
||||
if current_index >= 0 and current_index < siblings.size() - 1:
|
||||
var next_sibling = siblings[current_index + 1]
|
||||
create_element_wrapper(vm, next_sibling, lua_api)
|
||||
else:
|
||||
vm.lua_pushnil()
|
||||
|
||||
return 1
|
||||
|
||||
static func get_element_previous_sibling_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api: LuaAPI) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = find_element_by_id(element_id, dom_parser)
|
||||
if not element or not element.parent:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
var siblings = element.parent.children
|
||||
var current_index = siblings.find(element)
|
||||
|
||||
if current_index > 0:
|
||||
var prev_sibling = siblings[current_index - 1]
|
||||
create_element_wrapper(vm, prev_sibling, lua_api)
|
||||
else:
|
||||
vm.lua_pushnil()
|
||||
|
||||
return 1
|
||||
|
||||
static func get_element_first_child_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api: LuaAPI) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = find_element_by_id(element_id, dom_parser)
|
||||
if not element or element.children.is_empty():
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
create_element_wrapper(vm, element.children[0], lua_api)
|
||||
return 1
|
||||
|
||||
static func get_element_last_child_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api: LuaAPI) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = find_element_by_id(element_id, dom_parser)
|
||||
if not element or element.children.is_empty():
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
create_element_wrapper(vm, element.children[-1], lua_api)
|
||||
return 1
|
||||
|
||||
# DOM Manipulation Methods
|
||||
static func insert_before_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE) # parent
|
||||
vm.luaL_checktype(2, vm.LUA_TTABLE) # new_child
|
||||
vm.luaL_checktype(3, vm.LUA_TTABLE) # reference_child
|
||||
|
||||
# Get parent element info
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var parent_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Get new child element info
|
||||
vm.lua_getfield(2, "_element_id")
|
||||
var new_child_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Get reference child element info
|
||||
vm.lua_getfield(3, "_element_id")
|
||||
var reference_child_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Find elements
|
||||
var parent_element = find_element_by_id(parent_element_id, dom_parser)
|
||||
var new_child_element = find_element_by_id(new_child_element_id, dom_parser)
|
||||
var reference_child_element = find_element_by_id(reference_child_element_id, dom_parser)
|
||||
|
||||
if not parent_element or not new_child_element or not reference_child_element:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
# Find reference child index in parent's children
|
||||
var reference_index = parent_element.children.find(reference_child_element)
|
||||
if reference_index < 0:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
# Remove new child from its current parent if it has one
|
||||
if new_child_element.parent:
|
||||
var current_parent = new_child_element.parent
|
||||
var current_index = current_parent.children.find(new_child_element)
|
||||
if current_index >= 0:
|
||||
current_parent.children.remove_at(current_index)
|
||||
|
||||
# Insert new child before reference child
|
||||
new_child_element.parent = parent_element
|
||||
parent_element.children.insert(reference_index, new_child_element)
|
||||
|
||||
# Handle visual rendering if parent is already rendered
|
||||
handle_visual_insertion_by_reference(parent_element_id, new_child_element, reference_child_element_id, true, dom_parser, lua_api)
|
||||
|
||||
# Return the new child
|
||||
vm.lua_pushvalue(2)
|
||||
return 1
|
||||
|
||||
static func insert_after_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE) # parent
|
||||
vm.luaL_checktype(2, vm.LUA_TTABLE) # new_child
|
||||
vm.luaL_checktype(3, vm.LUA_TTABLE) # reference_child
|
||||
|
||||
# Get parent element info
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var parent_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Get new child element info
|
||||
vm.lua_getfield(2, "_element_id")
|
||||
var new_child_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Get reference child element info
|
||||
vm.lua_getfield(3, "_element_id")
|
||||
var reference_child_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Find elements
|
||||
var parent_element = find_element_by_id(parent_element_id, dom_parser)
|
||||
var new_child_element = find_element_by_id(new_child_element_id, dom_parser)
|
||||
var reference_child_element = find_element_by_id(reference_child_element_id, dom_parser)
|
||||
|
||||
if not parent_element or not new_child_element or not reference_child_element:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
# Find reference child index in parent's children
|
||||
var reference_index = parent_element.children.find(reference_child_element)
|
||||
if reference_index < 0:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
# Remove new child from its current parent if it has one
|
||||
if new_child_element.parent:
|
||||
var current_parent = new_child_element.parent
|
||||
var current_index = current_parent.children.find(new_child_element)
|
||||
if current_index >= 0:
|
||||
current_parent.children.remove_at(current_index)
|
||||
|
||||
# Insert new child after reference child
|
||||
new_child_element.parent = parent_element
|
||||
parent_element.children.insert(reference_index + 1, new_child_element)
|
||||
|
||||
# Handle visual rendering if parent is already rendered
|
||||
handle_visual_insertion_by_reference(parent_element_id, new_child_element, reference_child_element_id, false, dom_parser, lua_api)
|
||||
|
||||
# Return the new child
|
||||
vm.lua_pushvalue(2)
|
||||
return 1
|
||||
|
||||
static func replace_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE) # parent
|
||||
vm.luaL_checktype(2, vm.LUA_TTABLE) # new_child
|
||||
vm.luaL_checktype(3, vm.LUA_TTABLE) # old_child
|
||||
|
||||
# Get parent element info
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var parent_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Get new child element info
|
||||
vm.lua_getfield(2, "_element_id")
|
||||
var new_child_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Get old child element info
|
||||
vm.lua_getfield(3, "_element_id")
|
||||
var old_child_element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Find elements
|
||||
var parent_element = find_element_by_id(parent_element_id, dom_parser)
|
||||
var new_child_element = find_element_by_id(new_child_element_id, dom_parser)
|
||||
var old_child_element = find_element_by_id(old_child_element_id, dom_parser)
|
||||
|
||||
if not parent_element or not new_child_element or not old_child_element:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
# Find old child index in parent's children
|
||||
var old_index = parent_element.children.find(old_child_element)
|
||||
if old_index < 0:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
# Remove new child from its current parent if it has one
|
||||
if new_child_element.parent:
|
||||
var current_parent = new_child_element.parent
|
||||
var current_index = current_parent.children.find(new_child_element)
|
||||
if current_index >= 0:
|
||||
current_parent.children.remove_at(current_index)
|
||||
|
||||
# Replace old child with new child
|
||||
old_child_element.parent = null
|
||||
new_child_element.parent = parent_element
|
||||
parent_element.children[old_index] = new_child_element
|
||||
|
||||
# Handle visual updates
|
||||
handle_visual_replacement(old_child_element_id, new_child_element, parent_element_id, dom_parser, lua_api)
|
||||
|
||||
# Return the old child
|
||||
vm.lua_pushvalue(3)
|
||||
return 1
|
||||
|
||||
static func clone_handler(vm: LuauVM, dom_parser: HTMLParser, lua_api) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE) # element to clone
|
||||
var deep: bool = false
|
||||
|
||||
if vm.lua_gettop() >= 2:
|
||||
deep = vm.lua_toboolean(2)
|
||||
|
||||
# Get element info
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
# Find the element
|
||||
var element = find_element_by_id(element_id, dom_parser)
|
||||
if not element:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
# Clone the element
|
||||
var cloned_element = clone_element(element, deep)
|
||||
|
||||
# Add cloned element to parser's element collection
|
||||
dom_parser.parse_result.all_elements.append(cloned_element)
|
||||
|
||||
# Create Lua element wrapper with full functionality
|
||||
create_element_wrapper(vm, cloned_element, lua_api)
|
||||
|
||||
return 1
|
||||
|
||||
# Helper functions
|
||||
static func find_element_by_id(element_id: String, dom_parser: HTMLParser) -> HTMLParser.HTMLElement:
|
||||
if element_id == "body":
|
||||
return dom_parser.find_first("body")
|
||||
else:
|
||||
return dom_parser.find_by_id(element_id)
|
||||
|
||||
static func create_element_wrapper(vm: LuauVM, element: HTMLParser.HTMLElement, lua_api: LuaAPI) -> void:
|
||||
vm.lua_newtable()
|
||||
|
||||
var element_id: String
|
||||
if element.tag_name == "body":
|
||||
element_id = "body"
|
||||
else:
|
||||
element_id = element.get_attribute("id")
|
||||
if element_id.is_empty():
|
||||
element_id = lua_api.get_or_assign_element_id(element)
|
||||
element.set_attribute("id", element_id)
|
||||
|
||||
vm.lua_pushstring(element_id)
|
||||
vm.lua_setfield(-2, "_element_id")
|
||||
vm.lua_pushstring(element.tag_name)
|
||||
vm.lua_setfield(-2, "_tag_name")
|
||||
|
||||
if lua_api:
|
||||
lua_api.add_element_methods(vm)
|
||||
|
||||
static func clone_element(element: HTMLParser.HTMLElement, deep: bool) -> HTMLParser.HTMLElement:
|
||||
var cloned = HTMLParser.HTMLElement.new(element.tag_name)
|
||||
|
||||
for attr_name in element.attributes:
|
||||
if attr_name != "id":
|
||||
cloned.attributes[attr_name] = element.attributes[attr_name]
|
||||
|
||||
cloned.text_content = element.text_content
|
||||
|
||||
if deep:
|
||||
for child in element.children:
|
||||
var cloned_child = clone_element(child, true)
|
||||
cloned_child.parent = cloned
|
||||
cloned.children.append(cloned_child)
|
||||
|
||||
return cloned
|
||||
|
||||
|
||||
static func handle_visual_insertion_by_reference(parent_element_id: String, new_child_element: HTMLParser.HTMLElement, reference_element_id: String, insert_before: bool, dom_parser: HTMLParser, lua_api) -> void:
|
||||
var parent_dom_node: Node = null
|
||||
if parent_element_id == "body":
|
||||
var main_scene = lua_api.get_node("/root/Main")
|
||||
if main_scene:
|
||||
parent_dom_node = main_scene.website_container
|
||||
else:
|
||||
parent_dom_node = dom_parser.parse_result.dom_nodes.get(parent_element_id, null)
|
||||
|
||||
if parent_dom_node:
|
||||
render_new_element_by_reference.call_deferred(new_child_element, parent_dom_node, reference_element_id, insert_before, dom_parser)
|
||||
|
||||
static func handle_visual_replacement(old_child_element_id: String, new_child_element: HTMLParser.HTMLElement, parent_element_id: String, dom_parser: HTMLParser, lua_api) -> void:
|
||||
var old_dom_node = dom_parser.parse_result.dom_nodes.get(old_child_element_id, null)
|
||||
if not old_dom_node:
|
||||
return
|
||||
|
||||
var parent_container = old_dom_node.get_parent()
|
||||
if not parent_container:
|
||||
return
|
||||
|
||||
var old_position = -1
|
||||
for i in parent_container.get_child_count():
|
||||
if parent_container.get_child(i) == old_dom_node:
|
||||
old_position = i
|
||||
break
|
||||
|
||||
old_dom_node.queue_free()
|
||||
dom_parser.parse_result.dom_nodes.erase(old_child_element_id)
|
||||
|
||||
if old_position >= 0:
|
||||
var parent_dom_node: Node = null
|
||||
if parent_element_id == "body":
|
||||
var main_scene = lua_api.get_node("/root/Main")
|
||||
if main_scene:
|
||||
parent_dom_node = main_scene.website_container
|
||||
else:
|
||||
parent_dom_node = dom_parser.parse_result.dom_nodes.get(parent_element_id, null)
|
||||
|
||||
if parent_dom_node:
|
||||
render_new_element_at_position.call_deferred(new_child_element, parent_dom_node, old_position, dom_parser)
|
||||
|
||||
static func add_enhanced_element_methods(vm: LuauVM, lua_api, index: String = "element") -> void:
|
||||
vm.lua_pushcallable(lua_api._element_insert_before_wrapper, index + ".insertBefore")
|
||||
vm.lua_setfield(-2, "insertBefore")
|
||||
|
||||
vm.lua_pushcallable(lua_api._element_insert_after_wrapper, index + ".insertAfter")
|
||||
vm.lua_setfield(-2, "insertAfter")
|
||||
|
||||
vm.lua_pushcallable(lua_api._element_replace_wrapper, index + ".replace")
|
||||
vm.lua_setfield(-2, "replace")
|
||||
|
||||
vm.lua_pushcallable(lua_api._element_clone_wrapper, index + ".clone")
|
||||
vm.lua_setfield(-2, "clone")
|
||||
|
||||
static func is_same_element_visual_node(node1: Node, node2: Node) -> bool:
|
||||
if node1 == node2:
|
||||
return true
|
||||
|
||||
var current = node1
|
||||
var node1_grandparent = node1.get_parent()
|
||||
if node1_grandparent:
|
||||
node1_grandparent = node1_grandparent.get_parent()
|
||||
while current:
|
||||
if current == node2:
|
||||
return true
|
||||
var parent = current.get_parent()
|
||||
if not parent or (node1_grandparent and current == node1_grandparent):
|
||||
break
|
||||
current = parent
|
||||
|
||||
current = node2
|
||||
var node2_grandparent = node2.get_parent()
|
||||
if node2_grandparent:
|
||||
node2_grandparent = node2_grandparent.get_parent()
|
||||
while current:
|
||||
if current == node1:
|
||||
return true
|
||||
var parent = current.get_parent()
|
||||
if not parent or (node2_grandparent and current == node2_grandparent):
|
||||
break
|
||||
current = parent
|
||||
|
||||
return false
|
||||
|
||||
static func render_new_element_at_position(element: HTMLParser.HTMLElement, parent_node: Node, position: int, dom_parser: HTMLParser) -> void:
|
||||
var main_scene = Engine.get_main_loop().current_scene.get_node("/root/Main")
|
||||
if not main_scene:
|
||||
return
|
||||
|
||||
var element_node = await main_scene.create_element_node(element, dom_parser)
|
||||
if not element_node:
|
||||
return
|
||||
|
||||
element_node.set_meta("html_element", element)
|
||||
dom_parser.register_dom_node(element, element_node)
|
||||
|
||||
var container_node = parent_node
|
||||
if parent_node is MarginContainer and parent_node.get_child_count() > 0:
|
||||
container_node = parent_node.get_child(0)
|
||||
elif parent_node == main_scene.website_container:
|
||||
container_node = parent_node
|
||||
|
||||
container_node.add_child(element_node)
|
||||
if position >= 0 and position < container_node.get_child_count():
|
||||
container_node.move_child(element_node, position)
|
||||
|
||||
static func render_new_element_by_reference(element: HTMLParser.HTMLElement, parent_node: Node, reference_element_id: String, insert_before: bool, dom_parser: HTMLParser) -> void:
|
||||
var main_scene = Engine.get_main_loop().current_scene.get_node("/root/Main")
|
||||
if not main_scene:
|
||||
return
|
||||
|
||||
var reference_dom_node = dom_parser.parse_result.dom_nodes.get(reference_element_id, null)
|
||||
if not reference_dom_node:
|
||||
return
|
||||
|
||||
var container_node = parent_node
|
||||
if parent_node is MarginContainer and parent_node.get_child_count() > 0:
|
||||
container_node = parent_node.get_child(0)
|
||||
elif parent_node == main_scene.website_container:
|
||||
container_node = parent_node
|
||||
|
||||
var reference_position = -1
|
||||
for i in container_node.get_child_count():
|
||||
var child = container_node.get_child(i)
|
||||
if child == reference_dom_node or is_same_element_visual_node(child, reference_dom_node):
|
||||
reference_position = i
|
||||
break
|
||||
|
||||
if reference_position < 0:
|
||||
reference_position = container_node.get_child_count()
|
||||
|
||||
var insert_position = reference_position
|
||||
if not insert_before:
|
||||
insert_position = reference_position + 1
|
||||
|
||||
var element_node = await main_scene.create_element_node(element, dom_parser)
|
||||
if not element_node:
|
||||
return
|
||||
|
||||
element_node.set_meta("html_element", element)
|
||||
dom_parser.register_dom_node(element, element_node)
|
||||
|
||||
container_node.add_child(element_node)
|
||||
if insert_position >= 0 and insert_position < container_node.get_child_count() - 1:
|
||||
container_node.move_child(element_node, insert_position)
|
||||
|
||||
static func _index_handler(vm: LuauVM, lua_api: LuaAPI) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
var key: String = vm.luaL_checkstring(2)
|
||||
|
||||
match key:
|
||||
"parent":
|
||||
return lua_api._get_element_parent_wrapper(vm, lua_api)
|
||||
"nextSibling":
|
||||
return lua_api._get_element_next_sibling_wrapper(vm, lua_api)
|
||||
"previousSibling":
|
||||
return lua_api._get_element_previous_sibling_wrapper(vm, lua_api)
|
||||
"firstChild":
|
||||
return lua_api._get_element_first_child_wrapper(vm, lua_api)
|
||||
"lastChild":
|
||||
return lua_api._get_element_last_child_wrapper(vm, lua_api)
|
||||
_:
|
||||
return lua_api._element_index_handler(vm)
|
||||
1
flumi/Scripts/Utils/Lua/DOM.gd.uid
Normal file
1
flumi/Scripts/Utils/Lua/DOM.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://odam12sq4d5d
|
||||
Reference in New Issue
Block a user