opal-browser 0.2.0.beta1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/build.yml +95 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +17 -3
- data/LICENSE +2 -1
- data/README.md +183 -52
- 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 +8 -6
- data/lib/opal-browser.rb +1 -0
- data/opal/browser/animation_frame.rb +26 -1
- 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 -11
- data/opal/browser/canvas/gradient.rb +1 -11
- data/opal/browser/canvas/style.rb +3 -11
- data/opal/browser/canvas/text.rb +1 -11
- data/opal/browser/canvas.rb +17 -13
- data/opal/browser/console.rb +3 -1
- data/opal/browser/cookies.rb +78 -42
- 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 +193 -0
- data/opal/browser/delay.rb +41 -7
- data/opal/browser/dom/attribute.rb +13 -12
- data/opal/browser/dom/builder.rb +31 -17
- data/opal/browser/dom/document.rb +174 -42
- 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 +111 -0
- 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 +82 -0
- 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 +48 -1
- data/opal/browser/dom/element/media.rb +17 -0
- data/opal/browser/dom/element/offset.rb +5 -0
- data/opal/browser/dom/element/position.rb +11 -2
- data/opal/browser/dom/element/scroll.rb +123 -24
- data/opal/browser/dom/element/select.rb +42 -0
- data/opal/browser/dom/element/size.rb +17 -0
- data/opal/browser/dom/element/template.rb +11 -0
- data/opal/browser/dom/element/textarea.rb +26 -0
- data/opal/browser/dom/element.rb +468 -238
- data/opal/browser/dom/mutation_observer.rb +4 -4
- data/opal/browser/dom/node.rb +142 -60
- data/opal/browser/dom/node_set.rb +73 -44
- data/opal/browser/dom/shadow_root.rb +12 -0
- data/opal/browser/dom/text.rb +2 -2
- data/opal/browser/dom.rb +40 -16
- data/opal/browser/effects.rb +180 -3
- data/opal/browser/event/all.rb +26 -0
- data/opal/browser/{dom/event → event}/animation.rb +4 -2
- data/opal/browser/{dom/event → event}/audio_processing.rb +4 -2
- data/opal/browser/{dom/event → event}/base.rb +98 -9
- data/opal/browser/{dom/event → event}/before_unload.rb +4 -2
- data/opal/browser/{dom/event → event}/clipboard.rb +11 -2
- data/opal/browser/{dom/event → event}/close.rb +4 -2
- data/opal/browser/{dom/event → event}/composition.rb +4 -2
- data/opal/browser/{dom/event → event}/custom.rb +3 -3
- data/opal/browser/event/data_transfer.rb +95 -0
- data/opal/browser/{dom/event → event}/device_light.rb +4 -2
- data/opal/browser/{dom/event → event}/device_motion.rb +4 -2
- data/opal/browser/{dom/event → event}/device_orientation.rb +4 -2
- data/opal/browser/{dom/event → event}/device_proximity.rb +4 -2
- data/opal/browser/{dom/event → event}/drag.rb +11 -7
- data/opal/browser/{dom/event → event}/focus.rb +4 -2
- data/opal/browser/{dom/event → event}/gamepad.rb +5 -3
- data/opal/browser/{dom/event → event}/hash_change.rb +4 -2
- data/opal/browser/{dom/event → event}/keyboard.rb +16 -3
- data/opal/browser/{dom/event → event}/message.rb +4 -2
- data/opal/browser/{dom/event → event}/mouse.rb +12 -8
- data/opal/browser/{dom/event → event}/page_transition.rb +4 -2
- data/opal/browser/{dom/event → event}/pop_state.rb +4 -2
- data/opal/browser/{dom/event → event}/progress.rb +4 -2
- data/opal/browser/{dom/event → event}/sensor.rb +4 -2
- data/opal/browser/{dom/event → event}/storage.rb +4 -2
- data/opal/browser/{dom/event → event}/touch.rb +4 -2
- data/opal/browser/{dom/event → event}/ui.rb +2 -2
- data/opal/browser/{dom/event → event}/wheel.rb +4 -2
- data/opal/browser/event.rb +163 -0
- data/opal/browser/event_source.rb +2 -2
- data/opal/browser/form_data.rb +225 -0
- data/opal/browser/history.rb +4 -8
- data/opal/browser/http/binary.rb +1 -0
- data/opal/browser/http/headers.rb +16 -2
- data/opal/browser/http/request.rb +46 -48
- data/opal/browser/http/response.rb +5 -1
- data/opal/browser/http.rb +25 -2
- data/opal/browser/immediate.rb +9 -5
- data/opal/browser/interval.rb +34 -11
- data/opal/browser/location.rb +7 -1
- data/opal/browser/navigator.rb +127 -7
- data/opal/browser/polyfill/visual_viewport.rb +216 -0
- data/opal/browser/screen.rb +3 -3
- 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 +8 -4
- data/opal/browser/storage.rb +53 -35
- data/opal/browser/support.rb +72 -5
- 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 +31 -3
- data/opal/browser/window/view.rb +15 -0
- data/opal/browser/window.rb +46 -25
- data/opal/browser.rb +1 -10
- data/opal/opal-browser.rb +1 -0
- data/opal-browser.gemspec +3 -3
- data/spec/database/sql_spec.rb +139 -0
- data/spec/delay_spec.rb +41 -0
- data/spec/dom/attribute_spec.rb +49 -0
- data/spec/dom/builder_spec.rb +25 -8
- data/spec/dom/document_spec.rb +22 -0
- data/spec/dom/element/attributes_spec.rb +52 -0
- data/spec/dom/element/custom_spec.rb +106 -0
- data/spec/dom/element/subclass_spec.rb +144 -0
- data/spec/dom/element_spec.rb +181 -4
- data/spec/dom/mutation_observer_spec.rb +12 -8
- data/spec/dom/node_set_spec.rb +44 -0
- 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 +59 -0
- data/spec/native_cached_wrapper_spec.rb +46 -0
- data/spec/runner.rb +62 -69
- data/spec/socket_spec.rb +16 -12
- data/spec/spec_helper.rb +2 -5
- data/spec/spec_helper_promise.rb.erb +25 -0
- data/spec/storage_spec.rb +1 -1
- metadata +172 -50
- data/.travis.yml +0 -60
- data/opal/browser/dom/event.rb +0 -253
- data/opal/browser/http/parameters.rb +0 -8
- data/opal/browser/window/scroll.rb +0 -59
@@ -9,11 +9,11 @@ class MutationObserver
|
|
9
9
|
Browser.supports? :MutationObserver
|
10
10
|
end
|
11
11
|
|
12
|
-
include Native
|
12
|
+
include Native::Wrapper
|
13
13
|
|
14
14
|
# Encapsulates a recorded change.
|
15
15
|
class Record
|
16
|
-
include
|
16
|
+
include Browser::NativeCachedWrapper
|
17
17
|
|
18
18
|
# @!attribute [r] type
|
19
19
|
# @return [:attributes, :tree, :cdata] the type of the recorded change
|
@@ -49,7 +49,7 @@ class MutationObserver
|
|
49
49
|
[]
|
50
50
|
end
|
51
51
|
|
52
|
-
NodeSet
|
52
|
+
NodeSet[array]
|
53
53
|
end
|
54
54
|
|
55
55
|
# @!attribute [r] removed
|
@@ -61,7 +61,7 @@ class MutationObserver
|
|
61
61
|
[]
|
62
62
|
end
|
63
63
|
|
64
|
-
NodeSet
|
64
|
+
NodeSet[array]
|
65
65
|
end
|
66
66
|
|
67
67
|
# @!attribute [r] target
|
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,20 +38,27 @@ 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]
|
44
49
|
def ==(other)
|
45
|
-
`#@native === #{Native.
|
50
|
+
`#@native === #{Native.convert(other)}`
|
46
51
|
end
|
47
52
|
|
48
|
-
#
|
53
|
+
# Initialize a new node after `#dup` or `#clone`.
|
49
54
|
#
|
50
|
-
#
|
55
|
+
# This method is not to be called directly. Use `Node#dup` or
|
56
|
+
# `Node#clone`.
|
51
57
|
#
|
52
|
-
#
|
53
|
-
|
54
|
-
|
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)`
|
55
62
|
end
|
56
63
|
|
57
64
|
# Append a child to the node.
|
@@ -65,36 +72,79 @@ class Node
|
|
65
72
|
#
|
66
73
|
# @return [self]
|
67
74
|
def <<(node)
|
68
|
-
if
|
75
|
+
if Opal.respond_to? node, :each
|
76
|
+
node.each { |n| self << n }
|
77
|
+
return self
|
78
|
+
elsif Opal.respond_to? node, :to_dom
|
79
|
+
node = node.to_dom(document)
|
80
|
+
end
|
81
|
+
|
82
|
+
unless native?(node)
|
83
|
+
if String === node
|
84
|
+
node = `#@native.ownerDocument.createTextNode(node)`
|
85
|
+
else
|
86
|
+
node = Native.convert(node)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
`#@native.appendChild(node)`
|
91
|
+
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def >>(node)
|
96
|
+
if Opal.respond_to? node, :each
|
97
|
+
node.each { |n| self >> n }
|
98
|
+
return self
|
99
|
+
elsif Opal.respond_to? node, :to_dom
|
100
|
+
node = node.to_dom(document)
|
101
|
+
end
|
102
|
+
|
103
|
+
unless native?(node)
|
104
|
+
if String === node
|
105
|
+
node = `#@native.ownerDocument.createTextNode(node)`
|
106
|
+
else
|
107
|
+
node = Native.convert(node)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
if `#@native.firstChild == null`
|
69
112
|
`#@native.appendChild(node)`
|
70
|
-
elsif node.respond_to? :each
|
71
|
-
node.each { |n| add_child(n) }
|
72
|
-
elsif String === node
|
73
|
-
`#@native.appendChild(#@native.ownerDocument.createTextNode(node))`
|
74
113
|
else
|
75
|
-
`#@native.
|
114
|
+
`#@native.insertBefore(node, #@native.firstChild)`
|
76
115
|
end
|
77
116
|
|
78
117
|
self
|
79
118
|
end
|
80
119
|
|
81
|
-
|
120
|
+
def add_child(node = nil, &block)
|
121
|
+
unless node
|
122
|
+
node = DOM(&block)
|
123
|
+
end
|
124
|
+
|
125
|
+
self << node
|
126
|
+
end
|
82
127
|
|
83
128
|
# Add the passed node after this one.
|
84
129
|
#
|
85
130
|
# When passing a {String} a text node will be created.
|
86
131
|
#
|
87
132
|
# @param node [String, Node, #to_n] the node to add
|
88
|
-
def add_next_sibling(node)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
133
|
+
def add_next_sibling(node = nil, &block)
|
134
|
+
unless node
|
135
|
+
node = DOM(&block)
|
136
|
+
end
|
137
|
+
node = node.to_dom(document) if Opal.respond_to? node, :to_dom
|
138
|
+
|
139
|
+
unless native?(node)
|
140
|
+
if String === node
|
141
|
+
node = `#@native.ownerDocument.createTextNode(node)`
|
142
|
+
else
|
143
|
+
node = Native.convert(node)
|
144
|
+
end
|
97
145
|
end
|
146
|
+
|
147
|
+
`#@native.parentNode.insertBefore(node, #@native.nextSibling)`
|
98
148
|
end
|
99
149
|
|
100
150
|
# Add the passed node before this one.
|
@@ -102,15 +152,21 @@ class Node
|
|
102
152
|
# When passing a {String} a text node will be created.
|
103
153
|
#
|
104
154
|
# @param node [String, Node, #to_n] the node to add
|
105
|
-
def add_previous_sibling(node)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
155
|
+
def add_previous_sibling(node = nil, &block)
|
156
|
+
unless node
|
157
|
+
node = DOM(&block)
|
158
|
+
end
|
159
|
+
node = node.to_dom(document) if Opal.respond_to? node, :to_dom
|
160
|
+
|
161
|
+
unless native?(node)
|
162
|
+
if String === node
|
163
|
+
node = `#@native.ownerDocument.createTextNode(node)`
|
164
|
+
else
|
165
|
+
node = Native.convert(node)
|
166
|
+
end
|
113
167
|
end
|
168
|
+
|
169
|
+
`#@native.parentNode.insertBefore(node, #@native)`
|
114
170
|
end
|
115
171
|
|
116
172
|
alias after add_next_sibling
|
@@ -119,7 +175,8 @@ class Node
|
|
119
175
|
#
|
120
176
|
# @param node [Node] the node to append to
|
121
177
|
def append_to(node)
|
122
|
-
node
|
178
|
+
node << self
|
179
|
+
self
|
123
180
|
end
|
124
181
|
|
125
182
|
# Get an array of ancestors.
|
@@ -130,7 +187,7 @@ class Node
|
|
130
187
|
#
|
131
188
|
# @return [NodeSet]
|
132
189
|
def ancestors(expression = nil)
|
133
|
-
return NodeSet
|
190
|
+
return NodeSet[] unless parent
|
134
191
|
|
135
192
|
parents = [parent]
|
136
193
|
|
@@ -143,12 +200,14 @@ class Node
|
|
143
200
|
end
|
144
201
|
|
145
202
|
if expression
|
146
|
-
parents.select! {|p|
|
147
|
-
p.matches? expression
|
148
|
-
}
|
203
|
+
parents.select! { |p| p =~ expression }
|
149
204
|
end
|
150
205
|
|
151
|
-
NodeSet.new
|
206
|
+
NodeSet.new(parents)
|
207
|
+
end
|
208
|
+
|
209
|
+
def attached?
|
210
|
+
`#@native.isConnected`
|
152
211
|
end
|
153
212
|
|
154
213
|
alias before add_previous_sibling
|
@@ -156,11 +215,12 @@ class Node
|
|
156
215
|
# Remove the node from its parent.
|
157
216
|
def remove
|
158
217
|
parent.remove_child(self) if parent
|
218
|
+
self
|
159
219
|
end
|
160
220
|
|
161
221
|
# Remove all the children of the node.
|
162
222
|
def clear
|
163
|
-
children.
|
223
|
+
children.remove
|
164
224
|
end
|
165
225
|
|
166
226
|
# @!attribute content
|
@@ -209,7 +269,7 @@ class Node
|
|
209
269
|
# @!attribute children
|
210
270
|
# @return [NodeSet] the children of the node
|
211
271
|
def children
|
212
|
-
NodeSet
|
272
|
+
NodeSet[Native::Array.new(`#@native.childNodes`)]
|
213
273
|
end
|
214
274
|
|
215
275
|
def children=(node)
|
@@ -221,12 +281,22 @@ class Node
|
|
221
281
|
node_type == COMMENT_NODE
|
222
282
|
end
|
223
283
|
|
224
|
-
#
|
284
|
+
# Return true if the node is a custom element.
|
285
|
+
def custom?
|
286
|
+
false
|
287
|
+
end
|
288
|
+
|
289
|
+
# @!attribute [rw] document
|
225
290
|
# @return [Document?] the document the node is attached to
|
226
291
|
def document
|
227
292
|
DOM(`#@native.ownerDocument`) if defined?(`#@native.ownerDocument`)
|
228
293
|
end
|
229
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
|
+
|
230
300
|
# Return true if the node is a document.
|
231
301
|
def document?
|
232
302
|
node_type == DOCUMENT_NODE
|
@@ -258,16 +328,6 @@ class Node
|
|
258
328
|
node_type == DOCUMENT_FRAGMENT_NODE
|
259
329
|
end
|
260
330
|
|
261
|
-
# @!attribute inner_html
|
262
|
-
# @return [String] the inner HTML of the node
|
263
|
-
def inner_html
|
264
|
-
`#@native.innerHTML`
|
265
|
-
end
|
266
|
-
|
267
|
-
def inner_html=(value)
|
268
|
-
`#@native.innerHTML = #{value}`
|
269
|
-
end
|
270
|
-
|
271
331
|
alias inner_text content
|
272
332
|
alias inner_text= content=
|
273
333
|
|
@@ -277,13 +337,6 @@ class Node
|
|
277
337
|
element_children.last
|
278
338
|
end
|
279
339
|
|
280
|
-
# Check if the node matches the given CSS selector.
|
281
|
-
#
|
282
|
-
# @param expression [String] the CSS selector
|
283
|
-
def matches?(expression)
|
284
|
-
false
|
285
|
-
end
|
286
|
-
|
287
340
|
# @!attribute name
|
288
341
|
# @return [String] the name of the node
|
289
342
|
def name
|
@@ -332,6 +385,14 @@ class Node
|
|
332
385
|
`#@native.nodeType`
|
333
386
|
end
|
334
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
|
+
|
335
396
|
# @!attribute parent
|
336
397
|
# @return [Element?] the parent of the node
|
337
398
|
def parent
|
@@ -339,7 +400,7 @@ class Node
|
|
339
400
|
end
|
340
401
|
|
341
402
|
def parent=(node)
|
342
|
-
`#@native.parentNode = #{Native.
|
403
|
+
`#@native.parentNode = #{Native.convert(node)}`
|
343
404
|
end
|
344
405
|
|
345
406
|
def parse(text, options = {})
|
@@ -350,6 +411,14 @@ class Node
|
|
350
411
|
raise NotImplementedError
|
351
412
|
end
|
352
413
|
|
414
|
+
# Prepend the node to the passed one.
|
415
|
+
#
|
416
|
+
# @param node [Node] the node to prepend to
|
417
|
+
def prepend_to(node)
|
418
|
+
node >> self
|
419
|
+
self
|
420
|
+
end
|
421
|
+
|
353
422
|
# @!attribute previous
|
354
423
|
# @return [Node?] the previous sibling of the node
|
355
424
|
def previous
|
@@ -375,6 +444,7 @@ class Node
|
|
375
444
|
# Remove the given node from the children of this node.
|
376
445
|
def remove_child(node)
|
377
446
|
`#@native.removeChild(#{Native.try_convert(node)})`
|
447
|
+
self
|
378
448
|
end
|
379
449
|
|
380
450
|
# Replace the node with the given one.
|
@@ -384,11 +454,23 @@ class Node
|
|
384
454
|
# @param node [Node] the node to replace with
|
385
455
|
# @return [Node] the passed node
|
386
456
|
def replace(node)
|
387
|
-
|
457
|
+
node = node.to_dom(document) if Opal.respond_to? node, :to_dom
|
458
|
+
|
459
|
+
unless native?(node)
|
460
|
+
if String === node
|
461
|
+
node = `#@native.ownerDocument.createTextNode(node)`
|
462
|
+
else
|
463
|
+
node = Native.convert(node)
|
464
|
+
end
|
465
|
+
end
|
388
466
|
|
389
|
-
node
|
467
|
+
`#@native.parentNode.replaceChild(node, #@native)`
|
468
|
+
|
469
|
+
DOM(node)
|
390
470
|
end
|
391
471
|
|
472
|
+
alias replace_with replace
|
473
|
+
|
392
474
|
alias text content
|
393
475
|
alias text= content=
|
394
476
|
|
@@ -1,25 +1,20 @@
|
|
1
1
|
module Browser; module DOM
|
2
2
|
|
3
|
+
# Allows manipulation of a set of {Node}s.
|
3
4
|
class NodeSet
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
list.each {|el|
|
11
|
-
if NodeSet === el
|
12
|
-
@literal.concat(el.to_a)
|
13
|
-
else
|
14
|
-
@literal.push DOM(Native.convert(el))
|
15
|
-
end
|
16
|
-
}
|
5
|
+
# Create a new {NodeSet} from the given nodes.
|
6
|
+
#
|
7
|
+
# Note that the nodes are flattened and converted with DOM automatically,
|
8
|
+
# this means you can pass {NodeSet}s and {Native::Array}s as well.
|
9
|
+
def self.[](*nodes)
|
10
|
+
new(nodes.flatten.map { |x| DOM(Native.convert(x)) }.uniq)
|
17
11
|
end
|
18
12
|
|
19
|
-
def
|
20
|
-
@literal
|
13
|
+
def initialize(literal)
|
14
|
+
@literal = literal
|
21
15
|
end
|
22
16
|
|
17
|
+
# Any other method will be called on every node in the set.
|
23
18
|
def method_missing(name, *args, &block)
|
24
19
|
unless @literal.respond_to? name
|
25
20
|
each {|el|
|
@@ -34,59 +29,93 @@ class NodeSet
|
|
34
29
|
if `result === #@literal`
|
35
30
|
self
|
36
31
|
elsif Array === result
|
37
|
-
NodeSet.new(
|
32
|
+
NodeSet.new(result)
|
38
33
|
else
|
39
34
|
result
|
40
35
|
end
|
41
36
|
end
|
42
37
|
|
43
|
-
def
|
44
|
-
|
38
|
+
def respond_to_missing?(name, *)
|
39
|
+
@literal.respond_to?(name)
|
45
40
|
end
|
46
41
|
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
# Get the first node matching the given CSS selectors.
|
43
|
+
#
|
44
|
+
# @param rules [Array<String>] the CSS selectors to match with
|
45
|
+
#
|
46
|
+
# @return [Node?]
|
47
|
+
def at_css(*rules)
|
48
|
+
each {|node|
|
49
|
+
if node = node.at_css(*rules)
|
50
|
+
return node
|
51
|
+
end
|
52
|
+
}
|
50
53
|
|
51
|
-
|
52
|
-
last.after node
|
54
|
+
nil
|
53
55
|
end
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
57
|
+
# Get the first node matching the given XPath.
|
58
|
+
#
|
59
|
+
# @param paths [Array<String>] the XPath to match with
|
60
|
+
#
|
61
|
+
# @return [Node?]
|
62
|
+
def at_xpath(*paths)
|
63
|
+
each {|node|
|
64
|
+
if node = node.at_xpath(*paths)
|
65
|
+
return node
|
66
|
+
end
|
67
|
+
}
|
58
68
|
|
59
|
-
|
60
|
-
raise NotImplementedError
|
69
|
+
nil
|
61
70
|
end
|
62
71
|
|
63
|
-
|
64
|
-
|
72
|
+
# Query for children matching the given CSS selector.
|
73
|
+
#
|
74
|
+
# @param path [String] the CSS selector
|
75
|
+
#
|
76
|
+
# @return [NodeSet]
|
77
|
+
def css(path)
|
78
|
+
NodeSet[@literal.map {|node|
|
79
|
+
node.css(path)
|
80
|
+
}]
|
65
81
|
end
|
66
82
|
|
67
|
-
|
68
|
-
|
83
|
+
# Create another {NodeSet} with all the nodes that match the given
|
84
|
+
# expression.
|
85
|
+
#
|
86
|
+
# @param expression [String] a CSS selector
|
87
|
+
#
|
88
|
+
# @return [NodeSet] the new {NodeSet} with the matching nodes
|
89
|
+
def filter(expression)
|
90
|
+
NodeSet[@literal.select { |node| node =~ expression }]
|
69
91
|
end
|
70
92
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
each { |n| result.concat(n.children) }
|
75
|
-
|
76
|
-
result
|
93
|
+
# Search for multiple selectors
|
94
|
+
def search(*what)
|
95
|
+
NodeSet[@literal.map { |node| node.search(*what) }]
|
77
96
|
end
|
78
97
|
|
79
|
-
|
80
|
-
|
98
|
+
# Outer HTML of the entire nodeset
|
99
|
+
def outer_html
|
100
|
+
@literal.map(&:outer_html).join
|
81
101
|
end
|
82
102
|
|
83
|
-
|
84
|
-
|
103
|
+
# Query for children matching the given XPath.
|
104
|
+
#
|
105
|
+
# @param path [String] the XPath
|
106
|
+
#
|
107
|
+
# @return [NodeSet]
|
108
|
+
def xpath(path)
|
109
|
+
NodeSet[@literal.map {|node|
|
110
|
+
node.xpath(path)
|
111
|
+
}]
|
85
112
|
end
|
86
113
|
|
87
|
-
def
|
88
|
-
|
114
|
+
def to_ary
|
115
|
+
@literal
|
89
116
|
end
|
117
|
+
|
118
|
+
alias to_a to_ary
|
90
119
|
end
|
91
120
|
|
92
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
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'browser/dom/event'
|
2
1
|
require 'browser/dom/node_set'
|
3
2
|
require 'browser/dom/node'
|
4
3
|
require 'browser/dom/attribute'
|
@@ -7,9 +6,10 @@ require 'browser/dom/text'
|
|
7
6
|
require 'browser/dom/cdata'
|
8
7
|
require 'browser/dom/comment'
|
9
8
|
require 'browser/dom/element'
|
9
|
+
require 'browser/dom/document_or_shadow_root'
|
10
10
|
require 'browser/dom/document'
|
11
11
|
require 'browser/dom/document_fragment'
|
12
|
-
require 'browser/dom/
|
12
|
+
require 'browser/dom/shadow_root'
|
13
13
|
require 'browser/dom/mutation_observer'
|
14
14
|
|
15
15
|
module Kernel
|
@@ -34,29 +34,59 @@ module Kernel
|
|
34
34
|
DOM(`doc`)
|
35
35
|
end
|
36
36
|
|
37
|
-
#
|
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]
|
38
63
|
#
|
39
|
-
# @return [Browser::DOM::Node]
|
40
64
|
def DOM(*args, &block)
|
41
65
|
if block
|
42
66
|
document = args.shift || $document
|
43
|
-
|
44
|
-
|
45
|
-
roots = Browser::DOM::Builder.new(document, element, &block).to_a
|
67
|
+
roots = Browser::DOM::Builder.new(document, &block).to_a
|
46
68
|
|
47
69
|
if roots.length == 1
|
48
70
|
roots.first
|
49
71
|
else
|
50
|
-
Browser::DOM::NodeSet.new(
|
72
|
+
Browser::DOM::NodeSet.new(roots)
|
51
73
|
end
|
52
74
|
else
|
53
75
|
what = args.shift
|
54
76
|
document = args.shift || $document
|
55
77
|
|
56
|
-
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)
|
57
83
|
Browser::DOM::Node.new(what)
|
58
84
|
elsif Browser::DOM::Node === what
|
59
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
|
60
90
|
elsif String === what
|
61
91
|
%x{
|
62
92
|
var doc = #{Native.try_convert(document)}.createElement('div');
|
@@ -65,7 +95,7 @@ module Kernel
|
|
65
95
|
return #{DOM(`doc.childNodes.length == 1 ? doc.childNodes[0] : doc`)};
|
66
96
|
}
|
67
97
|
else
|
68
|
-
raise ArgumentError,
|
98
|
+
raise ArgumentError, 'argument is not DOM convertible'
|
69
99
|
end
|
70
100
|
end
|
71
101
|
end
|
@@ -74,12 +104,6 @@ end
|
|
74
104
|
module Browser
|
75
105
|
|
76
106
|
class Window
|
77
|
-
include DOM::Event::Target
|
78
|
-
|
79
|
-
target {|value|
|
80
|
-
$window if `#{value} == window`
|
81
|
-
}
|
82
|
-
|
83
107
|
# Get the {DOM::Document} for this window.
|
84
108
|
#
|
85
109
|
# @return [DOM::Document]
|