fix event reg on Lua added elements, add classList.contains, item and length
This commit is contained in:
@@ -20,6 +20,7 @@ TODO:
|
||||
11. **< table >** component. [🔗 Related Godot proposal](https://github.com/godotengine/godot-proposals/issues/97)
|
||||
12. **< canvas >** component should be theoretically impossible by exposing Godot `_draw()` APIs to Lua.
|
||||
13. `grid` display property for CSS, using `GridContainer` in Godot.
|
||||
14. Position `absolute` can be achieved by wrapping inside a Control node with a 0,0 size (so it's ignored by the layout), and moving the inner child according to CSS.
|
||||
|
||||
Issues:
|
||||
1. **< br />** counts as 1 element in **WebsiteContainer**, therefore despite being (0,0) in size, it counts as double in spacing
|
||||
|
||||
@@ -8,6 +8,7 @@ local domainsList = gurt.select('#domains-list')
|
||||
local tldSelector = gurt.select('#tld-selector')
|
||||
local loadingElement = gurt.select('#tld-loading')
|
||||
local displayElement = gurt.select('#invite-code-display')
|
||||
local options
|
||||
|
||||
displayElement:hide()
|
||||
|
||||
@@ -49,18 +50,23 @@ local function renderTLDSelector()
|
||||
['data-tld'] = tld
|
||||
})
|
||||
|
||||
tldSelector:append(option)
|
||||
|
||||
option:on('click', function()
|
||||
-- Clear previous selection
|
||||
local options = gurt.selectAll('.tld-option')
|
||||
if not options then
|
||||
options = gurt.selectAll('.tld-option')
|
||||
end
|
||||
|
||||
for j = 1, #options do
|
||||
options[j].classList:remove('tld-selected')
|
||||
if options[j].classList:contains('tld-selected') then
|
||||
options[j].classList:remove('tld-selected')
|
||||
end
|
||||
end
|
||||
|
||||
-- Select this option
|
||||
option.classList:add('tld-selected')
|
||||
end)
|
||||
|
||||
tldSelector:append(option)
|
||||
i = i + 1
|
||||
end, 16)
|
||||
end
|
||||
|
||||
@@ -23,6 +23,7 @@ var next_callback_ref: int = 1
|
||||
|
||||
var element_id_counter: int = 1
|
||||
var element_id_registry: Dictionary = {}
|
||||
var pending_event_registrations: Array = []
|
||||
|
||||
func _init():
|
||||
timeout_manager = LuaTimeoutManager.new()
|
||||
@@ -729,6 +730,19 @@ func _register_event_on_main_thread(element_id: String, event_name: String, call
|
||||
# This runs on the main thread - safe to access DOM nodes
|
||||
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||
if not dom_node:
|
||||
var pending_registration = {
|
||||
"element_id": element_id,
|
||||
"event_name": event_name,
|
||||
"callback_ref": callback_ref,
|
||||
"subscription_id": subscription_id if subscription_id != -1 else next_subscription_id
|
||||
}
|
||||
|
||||
if subscription_id == -1:
|
||||
next_subscription_id += 1
|
||||
|
||||
pending_event_registrations.append(pending_registration)
|
||||
|
||||
call_deferred("_process_pending_event_registrations")
|
||||
return
|
||||
|
||||
# Use provided subscription_id or generate a new one
|
||||
@@ -750,6 +764,29 @@ func _register_event_on_main_thread(element_id: String, event_name: String, call
|
||||
var signal_node = get_dom_node(dom_node, "signal")
|
||||
LuaEventUtils.connect_element_event(signal_node, event_name, subscription)
|
||||
|
||||
func _process_pending_event_registrations():
|
||||
|
||||
var i = 0
|
||||
while i < pending_event_registrations.size():
|
||||
var registration = pending_event_registrations[i]
|
||||
var element_id = registration.element_id
|
||||
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||
|
||||
if dom_node:
|
||||
pending_event_registrations.remove_at(i)
|
||||
|
||||
_register_event_on_main_thread(
|
||||
registration.element_id,
|
||||
registration.event_name,
|
||||
registration.callback_ref,
|
||||
registration.subscription_id
|
||||
)
|
||||
else:
|
||||
i += 1
|
||||
|
||||
if pending_event_registrations.size() > 0:
|
||||
call_deferred("_process_pending_event_registrations")
|
||||
|
||||
func _unsubscribe_event_on_main_thread(subscription_id: int):
|
||||
# This runs on the main thread - safe to cleanup event subscriptions
|
||||
var subscription = event_subscriptions.get(subscription_id, null)
|
||||
|
||||
@@ -268,6 +268,8 @@ static func render_new_element(element: HTMLParser.HTMLElement, parent_node: Nod
|
||||
if not main_scene:
|
||||
return
|
||||
|
||||
var element_id = element.get_attribute("id")
|
||||
|
||||
# Create the visual node for the element
|
||||
var element_node = await main_scene.create_element_node(element, dom_parser)
|
||||
if not element_node:
|
||||
@@ -279,7 +281,6 @@ static func render_new_element(element: HTMLParser.HTMLElement, parent_node: Nod
|
||||
|
||||
# Register the DOM node
|
||||
dom_parser.register_dom_node(element, element_node)
|
||||
|
||||
# Add to parent - handle body special case
|
||||
var container_node = parent_node
|
||||
if parent_node is MarginContainer and parent_node.get_child_count() > 0:
|
||||
@@ -945,6 +946,17 @@ static func _add_classlist_support(vm: LuauVM, lua_api: LuaAPI) -> void:
|
||||
vm.lua_pushcallable(LuaDOMUtils._classlist_toggle_wrapper, "classList.toggle")
|
||||
vm.lua_setfield(-2, "toggle")
|
||||
|
||||
vm.lua_pushcallable(LuaDOMUtils._classlist_contains_wrapper, "classList.contains")
|
||||
vm.lua_setfield(-2, "contains")
|
||||
|
||||
vm.lua_pushcallable(LuaDOMUtils._classlist_item_wrapper, "classList.item")
|
||||
vm.lua_setfield(-2, "item")
|
||||
|
||||
vm.lua_newtable()
|
||||
vm.lua_pushcallable(LuaDOMUtils._classlist_index_wrapper, "classList.__index")
|
||||
vm.lua_setfield(-2, "__index")
|
||||
vm.lua_setmetatable(-2)
|
||||
|
||||
# Set classList on the element
|
||||
vm.lua_setfield(-2, "classList")
|
||||
|
||||
@@ -1017,6 +1029,88 @@ static func _classlist_toggle_wrapper(vm: LuauVM) -> int:
|
||||
emit_dom_operation(lua_api, operation)
|
||||
return 0
|
||||
|
||||
static func _classlist_contains_wrapper(vm: LuauVM) -> int:
|
||||
var start_time = Time.get_ticks_msec()
|
||||
|
||||
var lua_api = vm.get_meta("lua_api") as LuaAPI
|
||||
if not lua_api:
|
||||
vm.lua_pushboolean(false)
|
||||
return 1
|
||||
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
var cls: String = vm.luaL_checkstring(2)
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = lua_api.dom_parser.find_by_id(element_id) if element_id != "body" else lua_api.dom_parser.find_first("body")
|
||||
if element:
|
||||
var current_style = element.get_attribute("style", "")
|
||||
var style_classes = CSSParser.smart_split_utility_classes(current_style) if current_style.length() > 0 else []
|
||||
|
||||
var has_class = cls in style_classes
|
||||
|
||||
vm.lua_pushboolean(has_class)
|
||||
return 1
|
||||
|
||||
vm.lua_pushboolean(false)
|
||||
return 1
|
||||
|
||||
static func _classlist_item_wrapper(vm: LuauVM) -> int:
|
||||
var lua_api = vm.get_meta("lua_api") as LuaAPI
|
||||
if not lua_api:
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
var index: int = vm.luaL_checkint(2) - 1 # Convert from 1-based to 0-based indexing
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = lua_api.dom_parser.find_by_id(element_id) if element_id != "body" else lua_api.dom_parser.find_first("body")
|
||||
if element:
|
||||
var current_style = element.get_attribute("style", "")
|
||||
var style_classes = CSSParser.smart_split_utility_classes(current_style) if current_style.length() > 0 else []
|
||||
if index >= 0 and index < style_classes.size():
|
||||
vm.lua_pushstring(style_classes[index])
|
||||
return 1
|
||||
|
||||
vm.lua_pushnil()
|
||||
return 1
|
||||
|
||||
static func _classlist_index_wrapper(vm: LuauVM) -> int:
|
||||
vm.luaL_checktype(1, vm.LUA_TTABLE)
|
||||
var key: String = vm.luaL_checkstring(2)
|
||||
|
||||
if key == "length":
|
||||
var lua_api = vm.get_meta("lua_api") as LuaAPI
|
||||
if not lua_api:
|
||||
vm.lua_pushinteger(0)
|
||||
return 1
|
||||
|
||||
vm.lua_getfield(1, "_element_id")
|
||||
var element_id: String = vm.lua_tostring(-1)
|
||||
vm.lua_pop(1)
|
||||
|
||||
var element = lua_api.dom_parser.find_by_id(element_id) if element_id != "body" else lua_api.dom_parser.find_first("body")
|
||||
if element:
|
||||
var current_style = element.get_attribute("style", "")
|
||||
var style_classes = CSSParser.smart_split_utility_classes(current_style) if current_style.length() > 0 else []
|
||||
vm.lua_pushinteger(style_classes.size())
|
||||
return 1
|
||||
|
||||
vm.lua_pushinteger(0)
|
||||
return 1
|
||||
|
||||
vm.lua_pushvalue(1)
|
||||
vm.lua_pushstring(key)
|
||||
vm.lua_rawget(-2)
|
||||
vm.lua_remove(-2)
|
||||
return 1
|
||||
|
||||
static func _element_newindex_wrapper(vm: LuauVM) -> int:
|
||||
# Get lua_api from VM metadata
|
||||
var lua_api = vm.get_meta("lua_api") as LuaAPI
|
||||
|
||||
Reference in New Issue
Block a user