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)
|
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.
|
12. **< canvas >** component should be theoretically impossible by exposing Godot `_draw()` APIs to Lua.
|
||||||
13. `grid` display property for CSS, using `GridContainer` in Godot.
|
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:
|
Issues:
|
||||||
1. **< br />** counts as 1 element in **WebsiteContainer**, therefore despite being (0,0) in size, it counts as double in spacing
|
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 tldSelector = gurt.select('#tld-selector')
|
||||||
local loadingElement = gurt.select('#tld-loading')
|
local loadingElement = gurt.select('#tld-loading')
|
||||||
local displayElement = gurt.select('#invite-code-display')
|
local displayElement = gurt.select('#invite-code-display')
|
||||||
|
local options
|
||||||
|
|
||||||
displayElement:hide()
|
displayElement:hide()
|
||||||
|
|
||||||
@@ -49,18 +50,23 @@ local function renderTLDSelector()
|
|||||||
['data-tld'] = tld
|
['data-tld'] = tld
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tldSelector:append(option)
|
||||||
|
|
||||||
option:on('click', function()
|
option:on('click', function()
|
||||||
-- Clear previous selection
|
-- Clear previous selection
|
||||||
local options = gurt.selectAll('.tld-option')
|
if not options then
|
||||||
|
options = gurt.selectAll('.tld-option')
|
||||||
|
end
|
||||||
|
|
||||||
for j = 1, #options do
|
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
|
end
|
||||||
|
|
||||||
-- Select this option
|
-- Select this option
|
||||||
option.classList:add('tld-selected')
|
option.classList:add('tld-selected')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
tldSelector:append(option)
|
|
||||||
i = i + 1
|
i = i + 1
|
||||||
end, 16)
|
end, 16)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ var next_callback_ref: int = 1
|
|||||||
|
|
||||||
var element_id_counter: int = 1
|
var element_id_counter: int = 1
|
||||||
var element_id_registry: Dictionary = {}
|
var element_id_registry: Dictionary = {}
|
||||||
|
var pending_event_registrations: Array = []
|
||||||
|
|
||||||
func _init():
|
func _init():
|
||||||
timeout_manager = LuaTimeoutManager.new()
|
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
|
# This runs on the main thread - safe to access DOM nodes
|
||||||
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
var dom_node = dom_parser.parse_result.dom_nodes.get(element_id, null)
|
||||||
if not dom_node:
|
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
|
return
|
||||||
|
|
||||||
# Use provided subscription_id or generate a new one
|
# 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")
|
var signal_node = get_dom_node(dom_node, "signal")
|
||||||
LuaEventUtils.connect_element_event(signal_node, event_name, subscription)
|
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):
|
func _unsubscribe_event_on_main_thread(subscription_id: int):
|
||||||
# This runs on the main thread - safe to cleanup event subscriptions
|
# This runs on the main thread - safe to cleanup event subscriptions
|
||||||
var subscription = event_subscriptions.get(subscription_id, null)
|
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:
|
if not main_scene:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
var element_id = element.get_attribute("id")
|
||||||
|
|
||||||
# Create the visual node for the element
|
# Create the visual node for the element
|
||||||
var element_node = await main_scene.create_element_node(element, dom_parser)
|
var element_node = await main_scene.create_element_node(element, dom_parser)
|
||||||
if not element_node:
|
if not element_node:
|
||||||
@@ -279,7 +281,6 @@ static func render_new_element(element: HTMLParser.HTMLElement, parent_node: Nod
|
|||||||
|
|
||||||
# Register the DOM node
|
# Register the DOM node
|
||||||
dom_parser.register_dom_node(element, element_node)
|
dom_parser.register_dom_node(element, element_node)
|
||||||
|
|
||||||
# Add to parent - handle body special case
|
# Add to parent - handle body special case
|
||||||
var container_node = parent_node
|
var container_node = parent_node
|
||||||
if parent_node is MarginContainer and parent_node.get_child_count() > 0:
|
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_pushcallable(LuaDOMUtils._classlist_toggle_wrapper, "classList.toggle")
|
||||||
vm.lua_setfield(-2, "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
|
# Set classList on the element
|
||||||
vm.lua_setfield(-2, "classList")
|
vm.lua_setfield(-2, "classList")
|
||||||
|
|
||||||
@@ -1017,6 +1029,88 @@ static func _classlist_toggle_wrapper(vm: LuauVM) -> int:
|
|||||||
emit_dom_operation(lua_api, operation)
|
emit_dom_operation(lua_api, operation)
|
||||||
return 0
|
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:
|
static func _element_newindex_wrapper(vm: LuauVM) -> int:
|
||||||
# Get lua_api from VM metadata
|
# Get lua_api from VM metadata
|
||||||
var lua_api = vm.get_meta("lua_api") as LuaAPI
|
var lua_api = vm.get_meta("lua_api") as LuaAPI
|
||||||
|
|||||||
Reference in New Issue
Block a user