dommy 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dommy/attr.rb +46 -8
- data/lib/dommy/backend/makiri_adapter.rb +34 -0
- data/lib/dommy/backend.rb +29 -0
- data/lib/dommy/blob.rb +48 -6
- data/lib/dommy/browser.rb +239 -36
- data/lib/dommy/callable_invoker.rb +6 -2
- data/lib/dommy/document.rb +525 -57
- data/lib/dommy/element.rb +479 -239
- data/lib/dommy/event.rb +296 -15
- data/lib/dommy/fetch.rb +431 -25
- data/lib/dommy/history.rb +24 -3
- data/lib/dommy/html_collection.rb +145 -21
- data/lib/dommy/html_elements.rb +1675 -266
- data/lib/dommy/interaction/driver.rb +155 -14
- data/lib/dommy/interaction/event_synthesis.rb +115 -7
- data/lib/dommy/interaction/field_interactor.rb +60 -0
- data/lib/dommy/internal/child_node.rb +199 -0
- data/lib/dommy/internal/css/cascade.rb +44 -2
- data/lib/dommy/internal/global_functions.rb +23 -10
- data/lib/dommy/internal/mutation_coordinator.rb +27 -7
- data/lib/dommy/internal/node_wrapper_cache.rb +56 -14
- data/lib/dommy/internal/observer_manager.rb +6 -0
- data/lib/dommy/internal/observer_matcher.rb +6 -8
- data/lib/dommy/internal/parent_node.rb +37 -73
- data/lib/dommy/internal/selector_matcher.rb +89 -0
- data/lib/dommy/internal/selector_parser.rb +44 -7
- data/lib/dommy/js/custom_element_bridge.rb +13 -2
- data/lib/dommy/js/dom_interfaces.rb +19 -4
- data/lib/dommy/js/host_bridge.rb +21 -0
- data/lib/dommy/js/host_runtime.js +926 -64
- data/lib/dommy/js/script_boot.rb +80 -0
- data/lib/dommy/location.rb +76 -13
- data/lib/dommy/mutation_observer.rb +3 -4
- data/lib/dommy/navigation.rb +263 -0
- data/lib/dommy/node.rb +180 -27
- data/lib/dommy/range.rb +15 -3
- data/lib/dommy/scheduler.rb +16 -0
- data/lib/dommy/shadow_root.rb +33 -0
- data/lib/dommy/storage.rb +61 -10
- data/lib/dommy/tree_walker.rb +18 -36
- data/lib/dommy/url.rb +4 -2
- data/lib/dommy/version.rb +1 -1
- data/lib/dommy/web_socket.rb +45 -2
- data/lib/dommy/window.rb +126 -7
- data/lib/dommy/xml_http_request.rb +30 -4
- data/lib/dommy.rb +2 -0
- metadata +6 -10
data/lib/dommy/event.rb
CHANGED
|
@@ -6,12 +6,12 @@ module Dommy
|
|
|
6
6
|
# surface.
|
|
7
7
|
|
|
8
8
|
module EventTarget
|
|
9
|
-
def add_event_listener(type, listener = nil, options = nil, &block)
|
|
9
|
+
def add_event_listener(type, listener = nil, options = nil, event_handler: false, &block)
|
|
10
10
|
cb = listener || block
|
|
11
11
|
return nil if type.nil? || cb.nil?
|
|
12
12
|
|
|
13
13
|
list = listeners_for(type.to_s)
|
|
14
|
-
entry = Listener.new(cb, options)
|
|
14
|
+
entry = Listener.new(cb, options, event_handler)
|
|
15
15
|
# Per spec, a listener is deduplicated by (type, callback, capture) — so
|
|
16
16
|
# the same function may be registered once as a capture and once as a
|
|
17
17
|
# bubble listener.
|
|
@@ -56,6 +56,29 @@ module Dommy
|
|
|
56
56
|
nil
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
+
# Event handler IDL attributes (`el.onclick = fn`, `window.onload = fn`): one
|
|
60
|
+
# named handler registered as a listener, where assignment replaces any
|
|
61
|
+
# previous handler and a nil value removes it. Shared by Element and Window.
|
|
62
|
+
def event_name_from_on(key)
|
|
63
|
+
key.to_s.sub(/\Aon/, "").downcase
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def on_handler(event_name)
|
|
67
|
+
@on_handlers&.[](event_name)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def set_on_handler(event_name, value)
|
|
71
|
+
@on_handlers ||= {}
|
|
72
|
+
previous = @on_handlers[event_name]
|
|
73
|
+
remove_event_listener(event_name, previous) if previous
|
|
74
|
+
if value
|
|
75
|
+
add_event_listener(event_name, value, event_handler: true)
|
|
76
|
+
@on_handlers[event_name] = value
|
|
77
|
+
else
|
|
78
|
+
@on_handlers.delete(event_name)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
59
82
|
def dispatch_event(event)
|
|
60
83
|
return true if event.nil?
|
|
61
84
|
|
|
@@ -130,11 +153,16 @@ module Dommy
|
|
|
130
153
|
end
|
|
131
154
|
end
|
|
132
155
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
156
|
+
result =
|
|
157
|
+
if entry.passive?
|
|
158
|
+
event.__internal_run_passive__ { invoke_listener_isolated(entry.listener, event, self) }
|
|
159
|
+
else
|
|
160
|
+
invoke_listener_isolated(entry.listener, event, self)
|
|
161
|
+
end
|
|
162
|
+
# Event handler processing algorithm: a handler registered via onX has its
|
|
163
|
+
# return value processed — onerror on a global cancels on `true`, every
|
|
164
|
+
# other handler cancels on `false` (`onsubmit="return false"`).
|
|
165
|
+
__internal_process_event_handler_return__(event, result) if entry.event_handler?
|
|
138
166
|
|
|
139
167
|
break if event.immediate_propagation_stopped?
|
|
140
168
|
end
|
|
@@ -142,6 +170,19 @@ module Dommy
|
|
|
142
170
|
nil
|
|
143
171
|
end
|
|
144
172
|
|
|
173
|
+
# WHATWG event handler processing algorithm, step "process return value":
|
|
174
|
+
# the special error handler (onerror on a Window) cancels the event when the
|
|
175
|
+
# handler returns true; onbeforeunload has its own returnValue handling
|
|
176
|
+
# (left alone); any other handler cancels when it returns exactly false
|
|
177
|
+
# (`return false` from onclick/onsubmit). A non-cancelable event ignores it.
|
|
178
|
+
def __internal_process_event_handler_return__(event, result)
|
|
179
|
+
if event.type == "error" && defined?(Dommy::Window) && is_a?(Dommy::Window)
|
|
180
|
+
event.__js_call__("preventDefault", []) if result == true
|
|
181
|
+
elsif event.type != "beforeunload" && result == false
|
|
182
|
+
event.__js_call__("preventDefault", [])
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
145
186
|
# Run one listener, isolating a throw so it can't escape the dispatch.
|
|
146
187
|
# WHATWG "inner invoke": if a listener's callback throws, the exception is
|
|
147
188
|
# *reported* (to the global error handler) and event dispatch continues with
|
|
@@ -152,8 +193,8 @@ module Dommy
|
|
|
152
193
|
# engine/Ruby-version-dependent — on some QuickJS/Ruby combinations a JS
|
|
153
194
|
# listener's throw surfaces as a Ruby exception here — so guard the
|
|
154
195
|
# host-initiated path too, mirroring MutationObserver#flush.
|
|
155
|
-
def invoke_listener_isolated(listener, event)
|
|
156
|
-
CallableInvoker.invoke_listener(listener, event)
|
|
196
|
+
def invoke_listener_isolated(listener, event, current_target = nil)
|
|
197
|
+
CallableInvoker.invoke_listener(listener, event, current_target)
|
|
157
198
|
rescue StandardError => e
|
|
158
199
|
__dommy_dump_event_failure__(event, listener, e) if ENV["DOMMY_EVENT_DEBUG"]
|
|
159
200
|
nil
|
|
@@ -181,7 +222,12 @@ module Dommy
|
|
|
181
222
|
|
|
182
223
|
private
|
|
183
224
|
|
|
184
|
-
Listener = Struct.new(:listener, :options) do
|
|
225
|
+
Listener = Struct.new(:listener, :options, :event_handler) do
|
|
226
|
+
# True when this listener was registered via an event handler IDL/content
|
|
227
|
+
# attribute (el.onclick = fn / onclick="…"): its return value is processed
|
|
228
|
+
# per the event handler processing algorithm (a false return cancels).
|
|
229
|
+
def event_handler? = event_handler ? true : false
|
|
230
|
+
|
|
185
231
|
def once?
|
|
186
232
|
case options
|
|
187
233
|
when Hash
|
|
@@ -489,7 +535,9 @@ module Dommy
|
|
|
489
535
|
@immediate_propagation_stopped = true
|
|
490
536
|
nil
|
|
491
537
|
when "composedPath"
|
|
492
|
-
|
|
538
|
+
# composedPath() is the event path only while the event is being
|
|
539
|
+
# dispatched; once dispatch finishes (currentTarget is null) it is empty.
|
|
540
|
+
@dispatch_flag ? @composed_path.dup : []
|
|
493
541
|
when "initEvent"
|
|
494
542
|
# WebIDL: the `type` argument is mandatory.
|
|
495
543
|
raise Bridge::TypeError, "initEvent requires a type argument" if args.empty?
|
|
@@ -584,6 +632,71 @@ module Dommy
|
|
|
584
632
|
end
|
|
585
633
|
end
|
|
586
634
|
|
|
635
|
+
# UIEvent — the base for user-interface events (MouseEvent, KeyboardEvent,
|
|
636
|
+
# CompositionEvent, …), adding `view` (the associated window) and `detail`.
|
|
637
|
+
# Carries the legacy `initUIEvent`, which — like initEvent — is a no-op while
|
|
638
|
+
# the event is being dispatched.
|
|
639
|
+
class UIEvent < Event
|
|
640
|
+
def initialize(type, init = nil)
|
|
641
|
+
super
|
|
642
|
+
@view = read_init(init, "view")
|
|
643
|
+
# WebIDL: `view` is `Window?`, so a present non-null value that isn't a
|
|
644
|
+
# Window is a TypeError during dictionary conversion.
|
|
645
|
+
unless @view.nil? || (defined?(Bridge::UNDEFINED) && @view.equal?(Bridge::UNDEFINED)) ||
|
|
646
|
+
@view.is_a?(Dommy::Window)
|
|
647
|
+
raise Bridge::TypeError, "'view' member must be a Window or null"
|
|
648
|
+
end
|
|
649
|
+
@view = nil if defined?(Bridge::UNDEFINED) && @view.equal?(Bridge::UNDEFINED)
|
|
650
|
+
@detail = (read_init(init, "detail") || 0).to_i
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
def __js_get__(key)
|
|
654
|
+
case key
|
|
655
|
+
when "view" then @view
|
|
656
|
+
when "detail" then @detail
|
|
657
|
+
else super
|
|
658
|
+
end
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
js_methods %w[initUIEvent]
|
|
662
|
+
def __js_call__(method, args)
|
|
663
|
+
case method
|
|
664
|
+
when "initUIEvent"
|
|
665
|
+
# Deprecated initUIEvent(type, bubbles=false, cancelable=false, view=null,
|
|
666
|
+
# detail=0). Mandatory type; a no-op while dispatching.
|
|
667
|
+
raise Bridge::TypeError, "initUIEvent requires a type argument" if args.empty?
|
|
668
|
+
|
|
669
|
+
unless @dispatch_flag
|
|
670
|
+
init_event(args[0], args[1], args[2])
|
|
671
|
+
@view = args[3]
|
|
672
|
+
@detail = (args[4] || 0).to_i
|
|
673
|
+
end
|
|
674
|
+
nil
|
|
675
|
+
else
|
|
676
|
+
super
|
|
677
|
+
end
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
# ToggleEvent — fired at a `<details>` (and other poppable elements) when it
|
|
682
|
+
# opens/closes, exposing the transition via `oldState` / `newState`
|
|
683
|
+
# ("open"/"closed"). A plain Event subclass.
|
|
684
|
+
class ToggleEvent < Event
|
|
685
|
+
def initialize(type, init = nil)
|
|
686
|
+
super
|
|
687
|
+
@old_state = read_init(init, "oldState").to_s
|
|
688
|
+
@new_state = read_init(init, "newState").to_s
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
def __js_get__(key)
|
|
692
|
+
case key
|
|
693
|
+
when "oldState" then @old_state
|
|
694
|
+
when "newState" then @new_state
|
|
695
|
+
else super
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
end
|
|
699
|
+
|
|
587
700
|
# PopStateEvent — fired on history back/forward. Exposes the history entry's
|
|
588
701
|
# serialized state via `event.state` (the spec property; framework routers like
|
|
589
702
|
# Turbo read `event.state.turbo` to recognise their own navigations and restore
|
|
@@ -604,6 +717,47 @@ module Dommy
|
|
|
604
717
|
end
|
|
605
718
|
end
|
|
606
719
|
|
|
720
|
+
# HashChangeEvent — fired on the window when the URL fragment changes (a
|
|
721
|
+
# fragment-navigation link, `location.hash = ...`). Exposes the full document
|
|
722
|
+
# URL before and after the change as `oldURL` / `newURL` (spec USVStrings). A
|
|
723
|
+
# plain `Event` subclass, NOT a CustomEvent.
|
|
724
|
+
class HashChangeEvent < Event
|
|
725
|
+
attr_reader :old_url, :new_url
|
|
726
|
+
|
|
727
|
+
def initialize(type, init = nil)
|
|
728
|
+
super
|
|
729
|
+
@old_url = read_init(init, "oldURL").to_s
|
|
730
|
+
@new_url = read_init(init, "newURL").to_s
|
|
731
|
+
end
|
|
732
|
+
|
|
733
|
+
def __js_get__(key)
|
|
734
|
+
case key
|
|
735
|
+
when "oldURL" then @old_url
|
|
736
|
+
when "newURL" then @new_url
|
|
737
|
+
else super
|
|
738
|
+
end
|
|
739
|
+
end
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
# SubmitEvent — fired on a form at submission. Exposes the button/input that
|
|
743
|
+
# triggered submission via `submitter` (null for `form.requestSubmit()` with
|
|
744
|
+
# no argument or an implicit submission). Frameworks (Turbo) read
|
|
745
|
+
# `event.submitter` to locate the clicked control.
|
|
746
|
+
class SubmitEvent < Event
|
|
747
|
+
attr_reader :submitter
|
|
748
|
+
|
|
749
|
+
def initialize(type, init = nil)
|
|
750
|
+
super
|
|
751
|
+
@submitter = read_init(init, "submitter")
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
def __js_get__(key)
|
|
755
|
+
return @submitter if key == "submitter"
|
|
756
|
+
|
|
757
|
+
super
|
|
758
|
+
end
|
|
759
|
+
end
|
|
760
|
+
|
|
607
761
|
# `ErrorEvent` — the event interface for an uncaught error (fired at
|
|
608
762
|
# `window.onerror`). Error-reporting code constructs it directly
|
|
609
763
|
# (`new ErrorEvent("error", { message, error, … })`); without the constructor
|
|
@@ -658,7 +812,7 @@ module Dommy
|
|
|
658
812
|
end
|
|
659
813
|
end
|
|
660
814
|
|
|
661
|
-
class MouseEvent <
|
|
815
|
+
class MouseEvent < UIEvent
|
|
662
816
|
def initialize(type, init = nil)
|
|
663
817
|
super
|
|
664
818
|
@button = read_init(init, "button") || 0
|
|
@@ -666,6 +820,10 @@ module Dommy
|
|
|
666
820
|
@shift_key = !!read_init(init, "shiftKey")
|
|
667
821
|
@alt_key = !!read_init(init, "altKey")
|
|
668
822
|
@meta_key = !!read_init(init, "metaKey")
|
|
823
|
+
@buttons = read_init(init, "buttons") || 0
|
|
824
|
+
@related_target = read_init(init, "relatedTarget")
|
|
825
|
+
@screen_x = read_init(init, "screenX") || 0
|
|
826
|
+
@screen_y = read_init(init, "screenY") || 0
|
|
669
827
|
@client_x = read_init(init, "clientX") || 0
|
|
670
828
|
@client_y = read_init(init, "clientY") || 0
|
|
671
829
|
end
|
|
@@ -682,6 +840,14 @@ module Dommy
|
|
|
682
840
|
@alt_key
|
|
683
841
|
when "metaKey"
|
|
684
842
|
@meta_key
|
|
843
|
+
when "buttons"
|
|
844
|
+
@buttons
|
|
845
|
+
when "relatedTarget"
|
|
846
|
+
@related_target
|
|
847
|
+
when "screenX"
|
|
848
|
+
@screen_x
|
|
849
|
+
when "screenY"
|
|
850
|
+
@screen_y
|
|
685
851
|
when "clientX"
|
|
686
852
|
@client_x
|
|
687
853
|
when "clientY"
|
|
@@ -690,6 +856,35 @@ module Dommy
|
|
|
690
856
|
super
|
|
691
857
|
end
|
|
692
858
|
end
|
|
859
|
+
|
|
860
|
+
js_methods %w[initMouseEvent]
|
|
861
|
+
def __js_call__(method, args)
|
|
862
|
+
case method
|
|
863
|
+
when "initMouseEvent"
|
|
864
|
+
# Legacy initMouseEvent(type, bubbles, cancelable, view, detail, screenX,
|
|
865
|
+
# screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button,
|
|
866
|
+
# relatedTarget). A no-op while dispatching.
|
|
867
|
+
raise Bridge::TypeError, "initMouseEvent requires a type argument" if args.empty?
|
|
868
|
+
|
|
869
|
+
unless @dispatch_flag
|
|
870
|
+
init_event(args[0], args[1], args[2])
|
|
871
|
+
@view = args[3]
|
|
872
|
+
@detail = (args[4] || 0).to_i
|
|
873
|
+
@screen_x = (args[5] || 0).to_i
|
|
874
|
+
@screen_y = (args[6] || 0).to_i
|
|
875
|
+
@client_x = (args[7] || 0).to_i
|
|
876
|
+
@client_y = (args[8] || 0).to_i
|
|
877
|
+
@ctrl_key = !!args[9]
|
|
878
|
+
@alt_key = !!args[10]
|
|
879
|
+
@shift_key = !!args[11]
|
|
880
|
+
@meta_key = !!args[12]
|
|
881
|
+
@button = (args[13] || 0).to_i
|
|
882
|
+
end
|
|
883
|
+
nil
|
|
884
|
+
else
|
|
885
|
+
super
|
|
886
|
+
end
|
|
887
|
+
end
|
|
693
888
|
end
|
|
694
889
|
|
|
695
890
|
# `DragEvent` — fired during drag-and-drop with a `dataTransfer`
|
|
@@ -713,20 +908,60 @@ module Dommy
|
|
|
713
908
|
end
|
|
714
909
|
end
|
|
715
910
|
|
|
716
|
-
class KeyboardEvent <
|
|
911
|
+
class KeyboardEvent < UIEvent
|
|
912
|
+
js_methods %w[getModifierState initKeyboardEvent]
|
|
913
|
+
|
|
914
|
+
# Legacy keyCode values for non-printable keys (UI Events "keyCode"
|
|
915
|
+
# informative mapping) — jQuery-era code still branches on these.
|
|
916
|
+
LEGACY_KEY_CODES = {
|
|
917
|
+
"Backspace" => 8, "Tab" => 9, "Enter" => 13, "Shift" => 16,
|
|
918
|
+
"Control" => 17, "Alt" => 18, "CapsLock" => 20, "Escape" => 27,
|
|
919
|
+
" " => 32, "PageUp" => 33, "PageDown" => 34, "End" => 35, "Home" => 36,
|
|
920
|
+
"ArrowLeft" => 37, "ArrowUp" => 38, "ArrowRight" => 39, "ArrowDown" => 40,
|
|
921
|
+
"Delete" => 46, "Meta" => 91,
|
|
922
|
+
}.freeze
|
|
923
|
+
|
|
717
924
|
def initialize(type, init = nil)
|
|
718
925
|
super
|
|
719
926
|
@key = read_init(init, "key").to_s
|
|
927
|
+
@code = read_init(init, "code").to_s
|
|
720
928
|
@ctrl_key = !!read_init(init, "ctrlKey")
|
|
721
929
|
@shift_key = !!read_init(init, "shiftKey")
|
|
722
930
|
@alt_key = !!read_init(init, "altKey")
|
|
723
931
|
@meta_key = !!read_init(init, "metaKey")
|
|
932
|
+
@repeat = !!read_init(init, "repeat")
|
|
933
|
+
@location = (read_init(init, "location") || 0).to_i
|
|
934
|
+
@is_composing = !!read_init(init, "isComposing")
|
|
935
|
+
@key_code = read_init(init, "keyCode")
|
|
936
|
+
@char_code = read_init(init, "charCode")
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
# Legacy keyCode: explicit init wins; a printable keypress reports the
|
|
940
|
+
# character code (Chrome parity), a printable keydown/keyup the upcased
|
|
941
|
+
# character; named keys use the legacy table.
|
|
942
|
+
def key_code
|
|
943
|
+
return @key_code.to_i if @key_code
|
|
944
|
+
|
|
945
|
+
if printable_key?
|
|
946
|
+
type == "keypress" ? @key.ord : @key.upcase(:ascii).ord
|
|
947
|
+
else
|
|
948
|
+
LEGACY_KEY_CODES[@key] || 0
|
|
949
|
+
end
|
|
950
|
+
end
|
|
951
|
+
|
|
952
|
+
# Legacy charCode: nonzero only on a printable keypress.
|
|
953
|
+
def char_code
|
|
954
|
+
return @char_code.to_i if @char_code
|
|
955
|
+
|
|
956
|
+
type == "keypress" && printable_key? ? @key.ord : 0
|
|
724
957
|
end
|
|
725
958
|
|
|
726
959
|
def __js_get__(key)
|
|
727
960
|
case key
|
|
728
961
|
when "key"
|
|
729
962
|
@key
|
|
963
|
+
when "code"
|
|
964
|
+
@code
|
|
730
965
|
when "ctrlKey"
|
|
731
966
|
@ctrl_key
|
|
732
967
|
when "shiftKey"
|
|
@@ -735,10 +970,56 @@ module Dommy
|
|
|
735
970
|
@alt_key
|
|
736
971
|
when "metaKey"
|
|
737
972
|
@meta_key
|
|
973
|
+
when "repeat"
|
|
974
|
+
@repeat
|
|
975
|
+
when "location"
|
|
976
|
+
@location
|
|
977
|
+
when "isComposing"
|
|
978
|
+
@is_composing
|
|
979
|
+
when "keyCode"
|
|
980
|
+
key_code
|
|
981
|
+
when "charCode"
|
|
982
|
+
char_code
|
|
983
|
+
when "which"
|
|
984
|
+
key_code.zero? ? char_code : key_code
|
|
985
|
+
else
|
|
986
|
+
super
|
|
987
|
+
end
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
def __js_call__(method, args)
|
|
991
|
+
case method
|
|
992
|
+
when "getModifierState"
|
|
993
|
+
case (args || []).first.to_s
|
|
994
|
+
when "Shift" then @shift_key
|
|
995
|
+
when "Control" then @ctrl_key
|
|
996
|
+
when "Alt" then @alt_key
|
|
997
|
+
when "Meta" then @meta_key
|
|
998
|
+
else false
|
|
999
|
+
end
|
|
1000
|
+
when "initKeyboardEvent"
|
|
1001
|
+
# Legacy initKeyboardEvent(type, bubbles, cancelable, view, key, location,
|
|
1002
|
+
# modifiersList, repeat, locale). A no-op while dispatching.
|
|
1003
|
+
raise Bridge::TypeError, "initKeyboardEvent requires a type argument" if args.empty?
|
|
1004
|
+
|
|
1005
|
+
unless @dispatch_flag
|
|
1006
|
+
init_event(args[0], args[1], args[2])
|
|
1007
|
+
@view = args[3]
|
|
1008
|
+
@key = args[4].to_s
|
|
1009
|
+
@location = (args[5] || 0).to_i
|
|
1010
|
+
@repeat = !!args[7]
|
|
1011
|
+
end
|
|
1012
|
+
nil
|
|
738
1013
|
else
|
|
739
1014
|
super
|
|
740
1015
|
end
|
|
741
1016
|
end
|
|
1017
|
+
|
|
1018
|
+
private
|
|
1019
|
+
|
|
1020
|
+
def printable_key?
|
|
1021
|
+
@key.length == 1
|
|
1022
|
+
end
|
|
742
1023
|
end
|
|
743
1024
|
|
|
744
1025
|
# `InputEvent` — fired by `input` / `beforeinput`. Carries `data`
|
|
@@ -1012,7 +1293,7 @@ module Dommy
|
|
|
1012
1293
|
|
|
1013
1294
|
# `CompositionEvent` — IME composition events (compositionstart /
|
|
1014
1295
|
# compositionupdate / compositionend). `data` holds the composing text.
|
|
1015
|
-
class CompositionEvent <
|
|
1296
|
+
class CompositionEvent < UIEvent
|
|
1016
1297
|
def initialize(type, init = nil)
|
|
1017
1298
|
super
|
|
1018
1299
|
@data = (read_init(init, "data") || "").to_s
|
|
@@ -1065,7 +1346,7 @@ module Dommy
|
|
|
1065
1346
|
|
|
1066
1347
|
# `FocusEvent` — focus / blur / focusin / focusout. `relatedTarget`
|
|
1067
1348
|
# is the element gaining/losing focus on the other side.
|
|
1068
|
-
class FocusEvent <
|
|
1349
|
+
class FocusEvent < UIEvent
|
|
1069
1350
|
def initialize(type, init = nil)
|
|
1070
1351
|
super
|
|
1071
1352
|
@related_target = read_init(init, "relatedTarget")
|