opal-browser 0.2.0 → 0.3.3
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 +5 -5
- data/.github/workflows/build.yml +78 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +17 -3
- data/LICENSE +2 -1
- data/README.md +131 -54
- data/Rakefile +29 -1
- data/config.ru +20 -3
- data/docs/polyfills.md +24 -0
- data/examples/2048/Gemfile +6 -0
- data/examples/2048/README.md +13 -0
- data/examples/2048/app/application.rb +169 -0
- data/examples/2048/config.ru +9 -0
- data/examples/canvas/Gemfile +6 -0
- data/examples/canvas/README.md +9 -0
- data/examples/canvas/app/application.rb +55 -0
- data/examples/canvas/config.ru +9 -0
- data/examples/component/Gemfile +6 -0
- data/examples/component/README.md +10 -0
- data/examples/component/app/application.rb +66 -0
- data/examples/component/config.ru +9 -0
- data/examples/integrations/README.md +24 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/Gemfile +6 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/README.md +16 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/app/application.rb +6 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/config.ru +9 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/.gitignore +1 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/Gemfile +7 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/README.md +22 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/Rakefile +4 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/app/application.rb +6 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/app.rb +32 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/config.ru +3 -0
- data/examples/integrations/dynamic-roda-tilt/.gitignore +1 -0
- data/examples/integrations/dynamic-roda-tilt/Gemfile +8 -0
- data/examples/integrations/dynamic-roda-tilt/README.md +17 -0
- data/examples/integrations/dynamic-roda-tilt/Rakefile +6 -0
- data/examples/integrations/dynamic-roda-tilt/app/application.rb +6 -0
- data/examples/integrations/dynamic-roda-tilt/app.rb +50 -0
- data/examples/integrations/dynamic-roda-tilt/config.ru +3 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/Gemfile +7 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/README.md +16 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/app/application.rb +6 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/config.ru +29 -0
- data/examples/integrations/static-bash/.gitignore +2 -0
- data/examples/integrations/static-bash/Gemfile +3 -0
- data/examples/integrations/static-bash/README.md +8 -0
- data/examples/integrations/static-bash/app/application.rb +6 -0
- data/examples/integrations/static-bash/build.sh +4 -0
- data/examples/integrations/static-bash/index.html +10 -0
- data/examples/integrations/static-bash-opal-parser/.gitignore +3 -0
- data/examples/integrations/static-bash-opal-parser/Gemfile +3 -0
- data/examples/integrations/static-bash-opal-parser/README.md +10 -0
- data/examples/integrations/static-bash-opal-parser/build.sh +4 -0
- data/examples/integrations/static-bash-opal-parser/index.html +19 -0
- data/examples/integrations/static-rake/.gitignore +1 -0
- data/examples/integrations/static-rake/Gemfile +4 -0
- data/examples/integrations/static-rake/README.md +7 -0
- data/examples/integrations/static-rake/Rakefile +10 -0
- data/examples/integrations/static-rake/app/application.rb +6 -0
- data/examples/integrations/static-rake/index.html +9 -0
- data/examples/integrations/static-rake-guard/.gitignore +1 -0
- data/examples/integrations/static-rake-guard/Gemfile +6 -0
- data/examples/integrations/static-rake-guard/Guardfile +3 -0
- data/examples/integrations/static-rake-guard/README.md +10 -0
- data/examples/integrations/static-rake-guard/Rakefile +10 -0
- data/examples/integrations/static-rake-guard/app/application.rb +6 -0
- data/examples/integrations/static-rake-guard/index.html +9 -0
- data/examples/svg/.gitignore +1 -0
- data/examples/svg/Gemfile +4 -0
- data/examples/svg/README.md +7 -0
- data/examples/svg/Rakefile +10 -0
- data/examples/svg/app/application.rb +11 -0
- data/examples/svg/index.html +17 -0
- data/examples/svg/index.svg +6 -0
- data/index.html.erb +2 -3
- data/opal/browser/audio/node.rb +121 -0
- data/opal/browser/audio/param_schedule.rb +43 -0
- data/opal/browser/audio.rb +66 -0
- data/opal/browser/blob.rb +94 -0
- data/opal/browser/canvas/data.rb +1 -1
- data/opal/browser/canvas/gradient.rb +1 -1
- data/opal/browser/canvas/style.rb +3 -1
- data/opal/browser/canvas/text.rb +1 -1
- data/opal/browser/canvas.rb +17 -3
- data/opal/browser/console.rb +3 -1
- data/opal/browser/cookies.rb +72 -34
- data/opal/browser/crypto.rb +79 -0
- data/opal/browser/css/declaration.rb +1 -1
- data/opal/browser/css/rule.rb +1 -1
- data/opal/browser/css/style_sheet.rb +2 -2
- data/opal/browser/css.rb +23 -7
- data/opal/browser/database/sql.rb +7 -8
- data/opal/browser/delay.rb +16 -0
- data/opal/browser/dom/attribute.rb +1 -1
- data/opal/browser/dom/builder.rb +29 -10
- data/opal/browser/dom/document.rb +81 -13
- data/opal/browser/dom/document_fragment.rb +18 -0
- data/opal/browser/dom/document_or_shadow_root.rb +19 -0
- data/opal/browser/dom/element/attributes.rb +28 -4
- data/opal/browser/dom/element/button.rb +31 -0
- data/opal/browser/dom/element/custom.rb +177 -0
- data/opal/browser/dom/element/data.rb +17 -2
- data/opal/browser/dom/element/editable.rb +47 -0
- data/opal/browser/dom/element/form.rb +38 -0
- data/opal/browser/dom/element/iframe.rb +37 -0
- data/opal/browser/dom/element/image.rb +2 -0
- data/opal/browser/dom/element/input.rb +36 -0
- data/opal/browser/dom/element/media.rb +17 -0
- data/opal/browser/dom/element/scroll.rb +106 -74
- data/opal/browser/dom/element/select.rb +6 -0
- data/opal/browser/dom/element/size.rb +12 -0
- data/opal/browser/dom/element/template.rb +2 -0
- data/opal/browser/dom/element/textarea.rb +2 -0
- data/opal/browser/dom/element.rb +194 -50
- data/opal/browser/dom/mutation_observer.rb +2 -2
- data/opal/browser/dom/node.rb +53 -13
- data/opal/browser/dom/node_set.rb +13 -2
- data/opal/browser/dom/shadow_root.rb +12 -0
- data/opal/browser/dom/text.rb +2 -2
- data/opal/browser/dom.rb +38 -5
- data/opal/browser/effects.rb +170 -4
- data/opal/browser/event/all.rb +26 -0
- data/opal/browser/event/animation.rb +2 -0
- data/opal/browser/event/audio_processing.rb +2 -0
- data/opal/browser/event/base.rb +35 -4
- data/opal/browser/event/before_unload.rb +2 -0
- data/opal/browser/event/clipboard.rb +9 -0
- data/opal/browser/event/close.rb +2 -0
- data/opal/browser/event/composition.rb +2 -0
- data/opal/browser/event/custom.rb +1 -1
- data/opal/browser/event/data_transfer.rb +95 -0
- data/opal/browser/event/device_light.rb +2 -0
- data/opal/browser/event/device_motion.rb +2 -0
- data/opal/browser/event/device_orientation.rb +2 -0
- data/opal/browser/event/device_proximity.rb +2 -0
- data/opal/browser/event/drag.rb +9 -5
- data/opal/browser/event/focus.rb +2 -0
- data/opal/browser/event/gamepad.rb +3 -1
- data/opal/browser/event/hash_change.rb +2 -0
- data/opal/browser/event/keyboard.rb +14 -1
- data/opal/browser/event/message.rb +2 -0
- data/opal/browser/event/mouse.rb +10 -6
- data/opal/browser/event/page_transition.rb +2 -0
- data/opal/browser/event/pop_state.rb +2 -0
- data/opal/browser/event/progress.rb +2 -0
- data/opal/browser/event/sensor.rb +2 -0
- data/opal/browser/event/storage.rb +2 -0
- data/opal/browser/event/touch.rb +2 -0
- data/opal/browser/event/wheel.rb +2 -0
- data/opal/browser/event.rb +26 -116
- data/opal/browser/event_source.rb +1 -1
- data/opal/browser/form_data.rb +225 -0
- data/opal/browser/history.rb +4 -8
- data/opal/browser/http/request.rb +32 -10
- data/opal/browser/http/response.rb +5 -1
- data/opal/browser/http.rb +0 -2
- data/opal/browser/immediate.rb +0 -2
- data/opal/browser/location.rb +7 -1
- data/opal/browser/navigator.rb +105 -4
- data/opal/browser/polyfill/visual_viewport.rb +216 -0
- data/opal/browser/screen.rb +2 -2
- data/opal/browser/setup/base.rb +6 -0
- data/opal/browser/setup/full.rb +13 -0
- data/opal/browser/setup/large.rb +17 -0
- data/opal/browser/setup/mini.rb +8 -0
- data/opal/browser/setup/traditional.rb +10 -0
- data/opal/browser/socket.rb +3 -3
- data/opal/browser/storage.rb +2 -2
- data/opal/browser/support.rb +46 -22
- data/opal/browser/utils.rb +94 -14
- data/opal/browser/version.rb +1 -1
- data/opal/browser/visual_viewport.rb +39 -0
- data/opal/browser/window/size.rb +14 -0
- data/opal/browser/window/view.rb +15 -0
- data/opal/browser/window.rb +29 -16
- data/opal/browser.rb +1 -11
- data/opal-browser.gemspec +3 -3
- data/spec/database/sql_spec.rb +43 -35
- data/spec/delay_spec.rb +15 -12
- data/spec/dom/document_spec.rb +10 -8
- data/spec/dom/element/custom_spec.rb +106 -0
- data/spec/dom/element/subclass_spec.rb +144 -0
- data/spec/dom/element_spec.rb +42 -0
- data/spec/dom/mutation_observer_spec.rb +12 -8
- data/spec/dom/node_spec.rb +48 -0
- data/spec/dom_spec.rb +8 -0
- data/spec/event_source_spec.rb +15 -12
- data/spec/{dom/event_spec.rb → event_spec.rb} +44 -15
- data/spec/history_spec.rb +23 -19
- data/spec/http_spec.rb +19 -31
- data/spec/immediate_spec.rb +5 -4
- data/spec/interval_spec.rb +18 -9
- data/spec/native_cached_wrapper_spec.rb +46 -0
- data/spec/runner.rb +37 -62
- data/spec/socket_spec.rb +15 -12
- data/spec/spec_helper.rb +2 -1
- data/spec/spec_helper_promise.rb.erb +25 -0
- metadata +120 -16
- data/.travis.yml +0 -74
- data/opal/browser/window/scroll.rb +0 -59
data/opal/browser/dom/node.rb
CHANGED
|
@@ -4,7 +4,7 @@ module Browser; module DOM
|
|
|
4
4
|
#
|
|
5
5
|
# @see https://developer.mozilla.org/en-US/docs/Web/API/Node
|
|
6
6
|
class Node
|
|
7
|
-
include
|
|
7
|
+
include Browser::NativeCachedWrapper
|
|
8
8
|
|
|
9
9
|
ELEMENT_NODE = 1
|
|
10
10
|
ATTRIBUTE_NODE = 2
|
|
@@ -38,6 +38,11 @@ class Node
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
def initialize(node)
|
|
42
|
+
raise ArgumentError, "Please ensure that #initialize of #{self.class} accepts one argument" unless node
|
|
43
|
+
super
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
# Return true of the other element is the same underlying DOM node.
|
|
42
47
|
#
|
|
43
48
|
# @return [Boolean]
|
|
@@ -45,6 +50,17 @@ class Node
|
|
|
45
50
|
`#@native === #{Native.convert(other)}`
|
|
46
51
|
end
|
|
47
52
|
|
|
53
|
+
# Initialize a new node after `#dup` or `#clone`.
|
|
54
|
+
#
|
|
55
|
+
# This method is not to be called directly. Use `Node#dup` or
|
|
56
|
+
# `Node#clone`.
|
|
57
|
+
#
|
|
58
|
+
# This method creates a deep detached clone of a DOM subtree to be used
|
|
59
|
+
# in the same document. The new node will have all events detached.
|
|
60
|
+
def initialize_copy(old)
|
|
61
|
+
set_native_reference `#{old.to_n}.cloneNode(true)`
|
|
62
|
+
end
|
|
63
|
+
|
|
48
64
|
# Append a child to the node.
|
|
49
65
|
#
|
|
50
66
|
# When passing a {String} a text node will be created.
|
|
@@ -59,6 +75,8 @@ class Node
|
|
|
59
75
|
if Opal.respond_to? node, :each
|
|
60
76
|
node.each { |n| self << n }
|
|
61
77
|
return self
|
|
78
|
+
elsif Opal.respond_to? node, :to_dom
|
|
79
|
+
node = node.to_dom(document)
|
|
62
80
|
end
|
|
63
81
|
|
|
64
82
|
unless native?(node)
|
|
@@ -78,6 +96,8 @@ class Node
|
|
|
78
96
|
if Opal.respond_to? node, :each
|
|
79
97
|
node.each { |n| self >> n }
|
|
80
98
|
return self
|
|
99
|
+
elsif Opal.respond_to? node, :to_dom
|
|
100
|
+
node = node.to_dom(document)
|
|
81
101
|
end
|
|
82
102
|
|
|
83
103
|
unless native?(node)
|
|
@@ -114,6 +134,7 @@ class Node
|
|
|
114
134
|
unless node
|
|
115
135
|
node = DOM(&block)
|
|
116
136
|
end
|
|
137
|
+
node = node.to_dom(document) if Opal.respond_to? node, :to_dom
|
|
117
138
|
|
|
118
139
|
unless native?(node)
|
|
119
140
|
if String === node
|
|
@@ -135,6 +156,7 @@ class Node
|
|
|
135
156
|
unless node
|
|
136
157
|
node = DOM(&block)
|
|
137
158
|
end
|
|
159
|
+
node = node.to_dom(document) if Opal.respond_to? node, :to_dom
|
|
138
160
|
|
|
139
161
|
unless native?(node)
|
|
140
162
|
if String === node
|
|
@@ -154,6 +176,7 @@ class Node
|
|
|
154
176
|
# @param node [Node] the node to append to
|
|
155
177
|
def append_to(node)
|
|
156
178
|
node << self
|
|
179
|
+
self
|
|
157
180
|
end
|
|
158
181
|
|
|
159
182
|
# Get an array of ancestors.
|
|
@@ -183,11 +206,16 @@ class Node
|
|
|
183
206
|
NodeSet.new(parents)
|
|
184
207
|
end
|
|
185
208
|
|
|
209
|
+
def attached?
|
|
210
|
+
`#@native.isConnected`
|
|
211
|
+
end
|
|
212
|
+
|
|
186
213
|
alias before add_previous_sibling
|
|
187
214
|
|
|
188
215
|
# Remove the node from its parent.
|
|
189
216
|
def remove
|
|
190
217
|
parent.remove_child(self) if parent
|
|
218
|
+
self
|
|
191
219
|
end
|
|
192
220
|
|
|
193
221
|
# Remove all the children of the node.
|
|
@@ -253,12 +281,22 @@ class Node
|
|
|
253
281
|
node_type == COMMENT_NODE
|
|
254
282
|
end
|
|
255
283
|
|
|
256
|
-
#
|
|
284
|
+
# Return true if the node is a custom element.
|
|
285
|
+
def custom?
|
|
286
|
+
false
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# @!attribute [rw] document
|
|
257
290
|
# @return [Document?] the document the node is attached to
|
|
258
291
|
def document
|
|
259
292
|
DOM(`#@native.ownerDocument`) if defined?(`#@native.ownerDocument`)
|
|
260
293
|
end
|
|
261
294
|
|
|
295
|
+
# Detach a node and transfer it to another document.
|
|
296
|
+
def document=(new_document)
|
|
297
|
+
`#{Native.try_convert(new_document, new_document)}.adoptNode(#@native)`
|
|
298
|
+
end
|
|
299
|
+
|
|
262
300
|
# Return true if the node is a document.
|
|
263
301
|
def document?
|
|
264
302
|
node_type == DOCUMENT_NODE
|
|
@@ -290,16 +328,6 @@ class Node
|
|
|
290
328
|
node_type == DOCUMENT_FRAGMENT_NODE
|
|
291
329
|
end
|
|
292
330
|
|
|
293
|
-
# @!attribute inner_html
|
|
294
|
-
# @return [String] the inner HTML of the node
|
|
295
|
-
def inner_html
|
|
296
|
-
`#@native.innerHTML`
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
def inner_html=(value)
|
|
300
|
-
`#@native.innerHTML = #{value}`
|
|
301
|
-
end
|
|
302
|
-
|
|
303
331
|
alias inner_text content
|
|
304
332
|
alias inner_text= content=
|
|
305
333
|
|
|
@@ -357,6 +385,14 @@ class Node
|
|
|
357
385
|
`#@native.nodeType`
|
|
358
386
|
end
|
|
359
387
|
|
|
388
|
+
# @!attribute outer_html
|
|
389
|
+
# @return [String] the simulated outer html of the node
|
|
390
|
+
def outer_html
|
|
391
|
+
div = $document.create_element("DIV")
|
|
392
|
+
div << self.dup
|
|
393
|
+
div.inner_html
|
|
394
|
+
end
|
|
395
|
+
|
|
360
396
|
# @!attribute parent
|
|
361
397
|
# @return [Element?] the parent of the node
|
|
362
398
|
def parent
|
|
@@ -380,6 +416,7 @@ class Node
|
|
|
380
416
|
# @param node [Node] the node to prepend to
|
|
381
417
|
def prepend_to(node)
|
|
382
418
|
node >> self
|
|
419
|
+
self
|
|
383
420
|
end
|
|
384
421
|
|
|
385
422
|
# @!attribute previous
|
|
@@ -407,6 +444,7 @@ class Node
|
|
|
407
444
|
# Remove the given node from the children of this node.
|
|
408
445
|
def remove_child(node)
|
|
409
446
|
`#@native.removeChild(#{Native.try_convert(node)})`
|
|
447
|
+
self
|
|
410
448
|
end
|
|
411
449
|
|
|
412
450
|
# Replace the node with the given one.
|
|
@@ -416,6 +454,8 @@ class Node
|
|
|
416
454
|
# @param node [Node] the node to replace with
|
|
417
455
|
# @return [Node] the passed node
|
|
418
456
|
def replace(node)
|
|
457
|
+
node = node.to_dom(document) if Opal.respond_to? node, :to_dom
|
|
458
|
+
|
|
419
459
|
unless native?(node)
|
|
420
460
|
if String === node
|
|
421
461
|
node = `#@native.ownerDocument.createTextNode(node)`
|
|
@@ -426,7 +466,7 @@ class Node
|
|
|
426
466
|
|
|
427
467
|
`#@native.parentNode.replaceChild(node, #@native)`
|
|
428
468
|
|
|
429
|
-
node
|
|
469
|
+
DOM(node)
|
|
430
470
|
end
|
|
431
471
|
|
|
432
472
|
alias replace_with replace
|
|
@@ -35,6 +35,10 @@ class NodeSet
|
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
def respond_to_missing?(name, *)
|
|
39
|
+
@literal.respond_to?(name)
|
|
40
|
+
end
|
|
41
|
+
|
|
38
42
|
# Get the first node matching the given CSS selectors.
|
|
39
43
|
#
|
|
40
44
|
# @param rules [Array<String>] the CSS selectors to match with
|
|
@@ -67,7 +71,7 @@ class NodeSet
|
|
|
67
71
|
|
|
68
72
|
# Query for children matching the given CSS selector.
|
|
69
73
|
#
|
|
70
|
-
# @param
|
|
74
|
+
# @param path [String] the CSS selector
|
|
71
75
|
#
|
|
72
76
|
# @return [NodeSet]
|
|
73
77
|
def css(path)
|
|
@@ -83,7 +87,7 @@ class NodeSet
|
|
|
83
87
|
#
|
|
84
88
|
# @return [NodeSet] the new {NodeSet} with the matching nodes
|
|
85
89
|
def filter(expression)
|
|
86
|
-
@literal.select { |node| node =~ expression }
|
|
90
|
+
NodeSet[@literal.select { |node| node =~ expression }]
|
|
87
91
|
end
|
|
88
92
|
|
|
89
93
|
# Search for multiple selectors
|
|
@@ -91,6 +95,11 @@ class NodeSet
|
|
|
91
95
|
NodeSet[@literal.map { |node| node.search(*what) }]
|
|
92
96
|
end
|
|
93
97
|
|
|
98
|
+
# Outer HTML of the entire nodeset
|
|
99
|
+
def outer_html
|
|
100
|
+
@literal.map(&:outer_html).join
|
|
101
|
+
end
|
|
102
|
+
|
|
94
103
|
# Query for children matching the given XPath.
|
|
95
104
|
#
|
|
96
105
|
# @param path [String] the XPath
|
|
@@ -105,6 +114,8 @@ class NodeSet
|
|
|
105
114
|
def to_ary
|
|
106
115
|
@literal
|
|
107
116
|
end
|
|
117
|
+
|
|
118
|
+
alias to_a to_ary
|
|
108
119
|
end
|
|
109
120
|
|
|
110
121
|
end; end
|
data/opal/browser/dom/text.rb
CHANGED
|
@@ -5,8 +5,8 @@ module Browser; module DOM
|
|
|
5
5
|
# @see https://developer.mozilla.org/en-US/docs/Web/API/Text
|
|
6
6
|
class Text < CharacterData
|
|
7
7
|
# (see Document#create_text)
|
|
8
|
-
def self.create(
|
|
9
|
-
$document.create_text(
|
|
8
|
+
def self.create(content)
|
|
9
|
+
$document.create_text(content)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
# @!attribute [r] whole
|
data/opal/browser/dom.rb
CHANGED
|
@@ -6,9 +6,10 @@ require 'browser/dom/text'
|
|
|
6
6
|
require 'browser/dom/cdata'
|
|
7
7
|
require 'browser/dom/comment'
|
|
8
8
|
require 'browser/dom/element'
|
|
9
|
+
require 'browser/dom/document_or_shadow_root'
|
|
9
10
|
require 'browser/dom/document'
|
|
10
11
|
require 'browser/dom/document_fragment'
|
|
11
|
-
require 'browser/dom/
|
|
12
|
+
require 'browser/dom/shadow_root'
|
|
12
13
|
require 'browser/dom/mutation_observer'
|
|
13
14
|
|
|
14
15
|
module Kernel
|
|
@@ -33,9 +34,33 @@ module Kernel
|
|
|
33
34
|
DOM(`doc`)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
#
|
|
37
|
+
# @overload DOM(document = $document, &block)
|
|
38
|
+
#
|
|
39
|
+
# Create a DOM tree using the {Paggio::HTML} DSL.
|
|
40
|
+
#
|
|
41
|
+
# @param document [Browser::DOM::Document] the document instance
|
|
42
|
+
# we intend to use
|
|
43
|
+
#
|
|
44
|
+
# @return [Browser::DOM::Node, Browser::DOM::NodeSet]
|
|
45
|
+
#
|
|
46
|
+
# @overload DOM(string, document = $document)
|
|
47
|
+
#
|
|
48
|
+
# Create a DOM tree from a HTML string.
|
|
49
|
+
#
|
|
50
|
+
# @param string [String] the HTML string
|
|
51
|
+
# @param document [Browser::DOM::Document] the document instance
|
|
52
|
+
# we intend to use
|
|
53
|
+
#
|
|
54
|
+
# @return [Browser::DOM::Node]
|
|
55
|
+
#
|
|
56
|
+
# @overload DOM(native)
|
|
57
|
+
#
|
|
58
|
+
# Wrap a native element to create a DOM tree.
|
|
59
|
+
#
|
|
60
|
+
# @param native [Native] the Native node
|
|
61
|
+
#
|
|
62
|
+
# @return [Browser::DOM::Node]
|
|
37
63
|
#
|
|
38
|
-
# @return [Browser::DOM::Node]
|
|
39
64
|
def DOM(*args, &block)
|
|
40
65
|
if block
|
|
41
66
|
document = args.shift || $document
|
|
@@ -50,10 +75,18 @@ module Kernel
|
|
|
50
75
|
what = args.shift
|
|
51
76
|
document = args.shift || $document
|
|
52
77
|
|
|
53
|
-
if
|
|
78
|
+
what = what.to_dom(document) if Opal.respond_to? what, :to_dom
|
|
79
|
+
|
|
80
|
+
if `typeof(#{what}) === 'undefined' || #{what} === null`
|
|
81
|
+
raise ArgumentError, 'argument is null'
|
|
82
|
+
elsif native?(what)
|
|
54
83
|
Browser::DOM::Node.new(what)
|
|
55
84
|
elsif Browser::DOM::Node === what
|
|
56
85
|
what
|
|
86
|
+
elsif Opal.respond_to? what, :each # eg. NodeSet, Array
|
|
87
|
+
document.create_element("DIV").tap do |div|
|
|
88
|
+
div << what
|
|
89
|
+
end
|
|
57
90
|
elsif String === what
|
|
58
91
|
%x{
|
|
59
92
|
var doc = #{Native.try_convert(document)}.createElement('div');
|
|
@@ -62,7 +95,7 @@ module Kernel
|
|
|
62
95
|
return #{DOM(`doc.childNodes.length == 1 ? doc.childNodes[0] : doc`)};
|
|
63
96
|
}
|
|
64
97
|
else
|
|
65
|
-
raise ArgumentError,
|
|
98
|
+
raise ArgumentError, 'argument is not DOM convertible'
|
|
66
99
|
end
|
|
67
100
|
end
|
|
68
101
|
end
|
data/opal/browser/effects.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'browser/animation_frame'
|
|
2
|
+
|
|
1
3
|
module Browser; module DOM
|
|
2
4
|
|
|
3
5
|
class Document < Element
|
|
@@ -14,37 +16,201 @@ class Element
|
|
|
14
16
|
# @param what [Symbol] how to display it
|
|
15
17
|
def show(what = :block)
|
|
16
18
|
style[:display] = what
|
|
19
|
+
self
|
|
17
20
|
end
|
|
18
21
|
|
|
19
22
|
# Hide the element.
|
|
20
23
|
def hide
|
|
21
24
|
style[:display] = :none
|
|
25
|
+
self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def visible?
|
|
29
|
+
# Let's check if we want to lie about the real visibility of an element.
|
|
30
|
+
# It could be wise to lie about it when it's in a process of animation...
|
|
31
|
+
if !@virtually_visible.nil?
|
|
32
|
+
@virtually_visible
|
|
33
|
+
else
|
|
34
|
+
style![:display] != :none
|
|
35
|
+
end
|
|
22
36
|
end
|
|
23
37
|
|
|
24
38
|
# Toggle the visibility of the element, hide it if it's shown, show it if
|
|
25
39
|
# it's hidden.
|
|
26
|
-
def toggle
|
|
27
|
-
if
|
|
28
|
-
show
|
|
29
|
-
else
|
|
40
|
+
def toggle(what = :block)
|
|
41
|
+
if visible?
|
|
30
42
|
hide
|
|
43
|
+
else
|
|
44
|
+
show(what)
|
|
31
45
|
end
|
|
46
|
+
self
|
|
32
47
|
end
|
|
33
48
|
|
|
34
49
|
# Set the focus on the element.
|
|
35
50
|
def focus
|
|
36
51
|
`#@native.focus()`
|
|
52
|
+
self
|
|
37
53
|
end
|
|
38
54
|
|
|
39
55
|
# Blur the focus from the element.
|
|
40
56
|
def blur
|
|
41
57
|
`#@native.blur()`
|
|
58
|
+
self
|
|
42
59
|
end
|
|
43
60
|
|
|
44
61
|
# Check if the element is focused.
|
|
45
62
|
def focused?
|
|
46
63
|
`#@native.hasFocus`
|
|
47
64
|
end
|
|
65
|
+
|
|
66
|
+
# Queue the block to happen when currently queued animations finish or during
|
|
67
|
+
# the next animation frame.
|
|
68
|
+
def animation_queue &block
|
|
69
|
+
promise = Promise.new
|
|
70
|
+
|
|
71
|
+
promise_resolve = proc do
|
|
72
|
+
@animation_promise = nil if @animation_promise == promise
|
|
73
|
+
promise.resolve
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
@animation_promise = (@animation_promise || Promise.value(true)).then do
|
|
77
|
+
animation_frame do
|
|
78
|
+
yield promise_resolve
|
|
79
|
+
end
|
|
80
|
+
promise
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Transform an element smoothly using CSS transitions, jQuery style. Yield
|
|
85
|
+
# a block afterwards if it's provided.
|
|
86
|
+
def animate(properties, duration: 0.4.s, easing: :ease, resolve: false, &block)
|
|
87
|
+
animation_queue(resolve) do |res|
|
|
88
|
+
duration = 0.6.s if duration == :slow
|
|
89
|
+
duration = 0.2.s if duration == :fast
|
|
90
|
+
|
|
91
|
+
original_value = style['transition']
|
|
92
|
+
|
|
93
|
+
style['transition'] = [original_value,
|
|
94
|
+
*properties.keys.map do |key|
|
|
95
|
+
"#{key} #{duration} #{easing}"
|
|
96
|
+
end].compact.join(", ")
|
|
97
|
+
|
|
98
|
+
properties.each do |key, value|
|
|
99
|
+
style[key] = value
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
promise = Promise.new
|
|
103
|
+
|
|
104
|
+
one :transitionend do |*args|
|
|
105
|
+
style['transition'] = original_value
|
|
106
|
+
|
|
107
|
+
yield(*args) if block_given?
|
|
108
|
+
|
|
109
|
+
res.call
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
self
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Show a hidden element with a "fade in" animation. Yield a block afterwards.
|
|
116
|
+
def fade_in(**kwargs, &block)
|
|
117
|
+
animation_queue do |resolve|
|
|
118
|
+
if !visible?
|
|
119
|
+
@virtually_visible = true
|
|
120
|
+
show
|
|
121
|
+
|
|
122
|
+
style[:opacity] = 0.0
|
|
123
|
+
animate opacity: 1.0, **kwargs do |*args|
|
|
124
|
+
@virtually_visible = nil
|
|
125
|
+
style[:opacity] = nil
|
|
126
|
+
yield(*args) if block_given?
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
resolve.call
|
|
130
|
+
end
|
|
131
|
+
self
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Hide a visible element with a "fade out" animation. Yield a block afterwards.
|
|
135
|
+
def fade_out(**kwargs, &block)
|
|
136
|
+
animation_queue do |resolve|
|
|
137
|
+
if visible?
|
|
138
|
+
@virtually_visible = false
|
|
139
|
+
|
|
140
|
+
style[:opacity] = 1.0
|
|
141
|
+
animate opacity: 0.0, **kwargs do |*args|
|
|
142
|
+
@virtually_visible = nil
|
|
143
|
+
style[:opacity] = nil
|
|
144
|
+
hide
|
|
145
|
+
yield(*args) if block_given?
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
resolve.call
|
|
149
|
+
end
|
|
150
|
+
self
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Toggle a visibility of an element with a "fade in"/"fade out" animation. Yield
|
|
154
|
+
# a block afterwards.
|
|
155
|
+
def fade_toggle(**kwargs, &block)
|
|
156
|
+
if visible?
|
|
157
|
+
fade_out(**kwargs, &block)
|
|
158
|
+
else
|
|
159
|
+
fade_in(**kwargs, &block)
|
|
160
|
+
end
|
|
161
|
+
self
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Show a hidden element with a "slide down" animation. Yield a block afterwards.
|
|
165
|
+
def slide_down(**kwargs, &block)
|
|
166
|
+
animation_queue do |resolve|
|
|
167
|
+
if !visible?
|
|
168
|
+
@virtually_visible = true
|
|
169
|
+
show
|
|
170
|
+
height = size.height
|
|
171
|
+
orig_height = style[:height]
|
|
172
|
+
style[:height] = 0.px
|
|
173
|
+
|
|
174
|
+
animate height: height.px, **kwargs do |*args|
|
|
175
|
+
@virtually_visible = nil
|
|
176
|
+
style[:height] = orig_height
|
|
177
|
+
yield(*args) if block_given?
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
resolve.call
|
|
181
|
+
end
|
|
182
|
+
self
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Hide a visible element with a "slide up" animation. Yield a block afterwards.
|
|
186
|
+
def slide_up(**kwargs, &block)
|
|
187
|
+
animation_queue do |resolve|
|
|
188
|
+
if visible?
|
|
189
|
+
@virtually_visible = false
|
|
190
|
+
orig_height = style[:height]
|
|
191
|
+
|
|
192
|
+
animate height: 0.px, **kwargs do |*args|
|
|
193
|
+
@virtually_visible = nil
|
|
194
|
+
style[:height] = orig_height
|
|
195
|
+
hide
|
|
196
|
+
yield(*args) if block_given?
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
resolve.call
|
|
200
|
+
end
|
|
201
|
+
self
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Toggle a visibility of an element with a "slide up"/"slide down" animation.
|
|
205
|
+
# Yield a block afterwards.
|
|
206
|
+
def slide_toggle(**kwargs, &block)
|
|
207
|
+
if visible?
|
|
208
|
+
slide_up(**kwargs, &block)
|
|
209
|
+
else
|
|
210
|
+
slide_down(**kwargs, &block)
|
|
211
|
+
end
|
|
212
|
+
self
|
|
213
|
+
end
|
|
48
214
|
end
|
|
49
215
|
|
|
50
216
|
end; end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# browser/event/all: Load support for all events
|
|
2
|
+
|
|
3
|
+
require 'browser/event/focus'
|
|
4
|
+
require 'browser/event/wheel'
|
|
5
|
+
require 'browser/event/data_transfer'
|
|
6
|
+
require 'browser/event/composition'
|
|
7
|
+
require 'browser/event/animation'
|
|
8
|
+
require 'browser/event/audio_processing'
|
|
9
|
+
require 'browser/event/before_unload'
|
|
10
|
+
require 'browser/event/composition'
|
|
11
|
+
require 'browser/event/clipboard'
|
|
12
|
+
require 'browser/event/device_light'
|
|
13
|
+
require 'browser/event/device_motion'
|
|
14
|
+
require 'browser/event/device_orientation'
|
|
15
|
+
require 'browser/event/device_proximity'
|
|
16
|
+
require 'browser/event/drag'
|
|
17
|
+
require 'browser/event/gamepad'
|
|
18
|
+
require 'browser/event/hash_change'
|
|
19
|
+
require 'browser/event/progress'
|
|
20
|
+
require 'browser/event/page_transition'
|
|
21
|
+
require 'browser/event/pop_state'
|
|
22
|
+
require 'browser/event/storage'
|
|
23
|
+
require 'browser/event/touch'
|
|
24
|
+
require 'browser/event/sensor'
|
|
25
|
+
require 'browser/event/message'
|
|
26
|
+
require 'browser/event/close'
|
data/opal/browser/event/base.rb
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module Browser
|
|
2
2
|
|
|
3
3
|
class Event
|
|
4
|
-
include Native
|
|
4
|
+
include Native::Wrapper
|
|
5
5
|
|
|
6
6
|
# @see https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
|
|
7
7
|
class Definition
|
|
8
|
-
include Native
|
|
8
|
+
include Native::Wrapper
|
|
9
9
|
|
|
10
10
|
# @private
|
|
11
11
|
def self.new(&block)
|
|
@@ -270,6 +270,37 @@ class Event
|
|
|
270
270
|
end
|
|
271
271
|
end
|
|
272
272
|
|
|
273
|
+
# @overload one(name, &block)
|
|
274
|
+
#
|
|
275
|
+
# Start listening for an event on the target. Remove the event after firing
|
|
276
|
+
# so that it is fired at most once.
|
|
277
|
+
#
|
|
278
|
+
# @param name [String] the event name
|
|
279
|
+
#
|
|
280
|
+
# @yieldparam event [Event] the event
|
|
281
|
+
#
|
|
282
|
+
# @return [Callback]
|
|
283
|
+
#
|
|
284
|
+
# @overload one(name, selector, &block)
|
|
285
|
+
#
|
|
286
|
+
# Start listening for an event on the target children. Remove the event after
|
|
287
|
+
# firing so that it is fired at most once.
|
|
288
|
+
#
|
|
289
|
+
# @param name [String] the event name
|
|
290
|
+
# @param selector [String] the CSS selector to trigger the event on
|
|
291
|
+
#
|
|
292
|
+
# @yieldparam event [Event] the event
|
|
293
|
+
#
|
|
294
|
+
# @return [Delegate]
|
|
295
|
+
def one (name, selector = nil, &block)
|
|
296
|
+
raise ArgumentError, 'no block has been given' unless block
|
|
297
|
+
|
|
298
|
+
cb = on name, selector do |*args|
|
|
299
|
+
out = block.call(*args)
|
|
300
|
+
cb.off
|
|
301
|
+
out
|
|
302
|
+
end
|
|
303
|
+
end
|
|
273
304
|
# @overload off()
|
|
274
305
|
# Stop listening for any event.
|
|
275
306
|
#
|
|
@@ -344,7 +375,7 @@ class Event
|
|
|
344
375
|
|
|
345
376
|
# Trigger an event on the target.
|
|
346
377
|
#
|
|
347
|
-
# @param
|
|
378
|
+
# @param event [String] the event name
|
|
348
379
|
# @param args [Array] optional arguments to the event callback
|
|
349
380
|
#
|
|
350
381
|
# @yieldparam definition [Definition] definition to customize the event
|
|
@@ -358,7 +389,7 @@ class Event
|
|
|
358
389
|
|
|
359
390
|
# Trigger an event on the target without bubbling.
|
|
360
391
|
#
|
|
361
|
-
# @param
|
|
392
|
+
# @param event [String] the event name
|
|
362
393
|
# @param args [Array] optional arguments to the event callback
|
|
363
394
|
#
|
|
364
395
|
# @yieldparam definition [Definition] definition to customize the event
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Browser; class Event
|
|
2
2
|
|
|
3
3
|
class Clipboard < Event
|
|
4
|
+
handles 'copy', 'cut', 'paste'
|
|
5
|
+
|
|
4
6
|
def self.supported?
|
|
5
7
|
Browser.supports? 'Event.Clipboard'
|
|
6
8
|
end
|
|
@@ -23,6 +25,13 @@ class Clipboard < Event
|
|
|
23
25
|
|
|
24
26
|
alias_native :data
|
|
25
27
|
alias_native :type, :dataType
|
|
28
|
+
|
|
29
|
+
# Returns a {DataTransfer} related to this event
|
|
30
|
+
#
|
|
31
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer
|
|
32
|
+
def transfer
|
|
33
|
+
DataTransfer.new(`#@native.clipboardData`)
|
|
34
|
+
end
|
|
26
35
|
end
|
|
27
36
|
|
|
28
37
|
end; end
|