opal-browser 0.1.0.beta1 → 0.3.1
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/.yardopts +1 -1
- data/Gemfile +22 -3
- data/LICENSE +20 -0
- data/README.md +200 -20
- data/Rakefile +29 -1
- data/config.ru +20 -2
- 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 +24 -0
- data/lib/opal-browser.rb +1 -0
- data/opal/browser/animation_frame.rb +92 -10
- 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 +2 -12
- 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 +86 -28
- data/opal/browser/console.rb +6 -38
- data/opal/browser/cookies.rb +90 -27
- data/opal/browser/crypto.rb +79 -0
- data/opal/browser/css/declaration.rb +1 -6
- 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 +94 -0
- data/opal/browser/dom/attribute.rb +16 -9
- data/opal/browser/dom/builder.rb +35 -25
- data/opal/browser/dom/character_data.rb +43 -7
- data/opal/browser/dom/document.rb +171 -37
- 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 +25 -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 +32 -10
- data/opal/browser/dom/element/position.rb +11 -2
- data/opal/browser/dom/element/scroll.rb +139 -20
- data/opal/browser/dom/element/select.rb +42 -0
- data/opal/browser/dom/element/size.rb +46 -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 +496 -168
- data/opal/browser/dom/mutation_observer.rb +69 -9
- data/opal/browser/dom/node.rb +270 -83
- data/opal/browser/dom/node_set.rb +74 -41
- data/opal/browser/dom/shadow_root.rb +12 -0
- data/opal/browser/dom/text.rb +18 -3
- data/opal/browser/dom.rb +40 -18
- data/opal/browser/effects.rb +180 -3
- data/opal/browser/event/all.rb +26 -0
- data/opal/browser/event/animation.rb +40 -0
- data/opal/browser/{dom/event → event}/audio_processing.rb +10 -6
- data/opal/browser/event/base.rb +461 -0
- data/opal/browser/event/before_unload.rb +17 -0
- data/opal/browser/event/clipboard.rb +37 -0
- data/opal/browser/event/close.rb +49 -0
- data/opal/browser/event/composition.rb +52 -0
- data/opal/browser/event/custom.rb +65 -0
- data/opal/browser/event/data_transfer.rb +95 -0
- data/opal/browser/event/device_light.rb +25 -0
- data/opal/browser/{dom/event → event}/device_motion.rb +21 -6
- data/opal/browser/event/device_orientation.rb +50 -0
- data/opal/browser/{dom/event → event}/device_proximity.rb +10 -6
- data/opal/browser/event/drag.rb +123 -0
- data/opal/browser/event/focus.rb +41 -0
- data/opal/browser/event/gamepad.rb +62 -0
- data/opal/browser/{dom/event → event}/hash_change.rb +10 -6
- data/opal/browser/event/keyboard.rb +128 -0
- data/opal/browser/event/message.rb +72 -0
- data/opal/browser/{dom/event → event}/mouse.rb +37 -32
- data/opal/browser/event/page_transition.rb +25 -0
- data/opal/browser/event/pop_state.rb +35 -0
- data/opal/browser/event/progress.rb +45 -0
- data/opal/browser/event/sensor.rb +17 -0
- data/opal/browser/{dom/event → event}/storage.rb +10 -6
- data/opal/browser/{dom/event → event}/touch.rb +14 -21
- data/opal/browser/event/ui.rb +38 -0
- data/opal/browser/{dom/event → event}/wheel.rb +6 -4
- data/opal/browser/event.rb +163 -0
- data/opal/browser/event_source.rb +7 -4
- data/opal/browser/form_data.rb +225 -0
- data/opal/browser/history.rb +53 -21
- data/opal/browser/http/binary.rb +1 -0
- data/opal/browser/http/headers.rb +21 -2
- data/opal/browser/http/request.rb +83 -55
- data/opal/browser/http/response.rb +5 -1
- data/opal/browser/http.rb +47 -9
- data/opal/browser/immediate.rb +128 -10
- data/opal/browser/interval.rb +41 -23
- data/opal/browser/location.rb +20 -4
- data/opal/browser/navigator.rb +136 -13
- data/opal/browser/polyfill/visual_viewport.rb +216 -0
- data/opal/browser/screen.rb +34 -8
- 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 +16 -8
- data/opal/browser/storage.rb +155 -52
- data/opal/browser/support.rb +299 -0
- data/opal/browser/utils.rb +116 -18
- data/opal/browser/version.rb +1 -1
- data/opal/browser/visual_viewport.rb +39 -0
- data/opal/browser/window/size.rb +47 -9
- data/opal/browser/window/view.rb +37 -4
- data/opal/browser/window.rb +46 -26
- data/opal/browser.rb +1 -10
- data/opal/opal-browser.rb +1 -0
- data/opal-browser.gemspec +10 -12
- 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 +36 -19
- data/spec/dom/document_spec.rb +28 -6
- 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 +184 -7
- data/spec/dom/mutation_observer_spec.rb +13 -9
- data/spec/dom/node_set_spec.rb +44 -0
- data/spec/dom/node_spec.rb +87 -27
- data/spec/dom_spec.rb +19 -9
- data/spec/event_source_spec.rb +18 -15
- data/spec/{dom/event_spec.rb → event_spec.rb} +55 -26
- data/spec/history_spec.rb +32 -19
- data/spec/http_spec.rb +25 -36
- data/spec/immediate_spec.rb +10 -7
- data/spec/interval_spec.rb +59 -0
- data/spec/native_cached_wrapper_spec.rb +46 -0
- data/spec/runner.rb +107 -0
- data/spec/socket_spec.rb +18 -14
- data/spec/spec_helper.rb +2 -4
- data/spec/spec_helper_promise.rb.erb +25 -0
- data/spec/storage_spec.rb +7 -7
- data/spec/wgxpath.install.js +49 -0
- data/spec/window_spec.rb +2 -2
- metadata +181 -93
- data/opal/browser/compatibility/animation_frame.rb +0 -93
- data/opal/browser/compatibility/dom/document/window.rb +0 -15
- data/opal/browser/compatibility/dom/element/css.rb +0 -15
- data/opal/browser/compatibility/dom/element/matches.rb +0 -31
- data/opal/browser/compatibility/dom/element/offset.rb +0 -20
- data/opal/browser/compatibility/dom/element/scroll.rb +0 -25
- data/opal/browser/compatibility/dom/element/style.rb +0 -15
- data/opal/browser/compatibility/dom/mutation_observer.rb +0 -47
- data/opal/browser/compatibility/http/request.rb +0 -15
- data/opal/browser/compatibility/immediate.rb +0 -107
- data/opal/browser/compatibility/window/scroll.rb +0 -27
- data/opal/browser/compatibility/window/size.rb +0 -13
- data/opal/browser/compatibility/window/view.rb +0 -13
- data/opal/browser/compatibility.rb +0 -59
- data/opal/browser/dom/compatibility.rb +0 -8
- data/opal/browser/dom/event/animation.rb +0 -26
- data/opal/browser/dom/event/base.rb +0 -207
- data/opal/browser/dom/event/before_unload.rb +0 -13
- data/opal/browser/dom/event/clipboard.rb +0 -26
- data/opal/browser/dom/event/close.rb +0 -35
- data/opal/browser/dom/event/composition.rb +0 -38
- data/opal/browser/dom/event/custom.rb +0 -30
- data/opal/browser/dom/event/device_light.rb +0 -21
- data/opal/browser/dom/event/device_orientation.rb +0 -36
- data/opal/browser/dom/event/drag.rb +0 -113
- data/opal/browser/dom/event/focus.rb +0 -23
- data/opal/browser/dom/event/gamepad.rb +0 -47
- data/opal/browser/dom/event/keyboard.rb +0 -93
- data/opal/browser/dom/event/message.rb +0 -50
- data/opal/browser/dom/event/page_transition.rb +0 -21
- data/opal/browser/dom/event/pop_state.rb +0 -21
- data/opal/browser/dom/event/progress.rb +0 -31
- data/opal/browser/dom/event/sensor.rb +0 -13
- data/opal/browser/dom/event/ui.rb +0 -22
- data/opal/browser/dom/event.rb +0 -240
- data/opal/browser/http/compatibility.rb +0 -1
- data/opal/browser/http/parameters.rb +0 -8
- data/opal/browser/timeout.rb +0 -60
- data/opal/browser/window/compatibility.rb +0 -3
- data/opal/browser/window/scroll.rb +0 -49
data/opal/browser/http.rb
CHANGED
@@ -1,20 +1,25 @@
|
|
1
|
-
require 'promise'
|
2
|
-
|
3
1
|
require 'browser/http/binary'
|
4
2
|
require 'browser/http/headers'
|
5
3
|
require 'browser/http/request'
|
6
4
|
require 'browser/http/response'
|
7
|
-
require 'browser/http/compatibility'
|
8
5
|
|
9
6
|
module Browser
|
10
7
|
|
11
8
|
module HTTP
|
9
|
+
# Check if HTTP requests are supported.
|
10
|
+
def self.supported?
|
11
|
+
Browser.supports?('XHR') || Browser.supports?('ActiveXObject')
|
12
|
+
end
|
13
|
+
|
12
14
|
# Send an asynchronous request.
|
13
15
|
#
|
14
16
|
# @param method [Symbol] the HTTP method to use
|
15
17
|
# @param url [String] the URL to request
|
16
18
|
# @param data [String, Hash] the data to send
|
17
|
-
#
|
19
|
+
#
|
20
|
+
# @yieldparam request [Request] the request to configure
|
21
|
+
#
|
22
|
+
# @return [Promise] a promise that will be resolved with the response
|
18
23
|
def self.send(method, url, data = nil, &block)
|
19
24
|
Promise.new.tap {|promise|
|
20
25
|
Request.new(&block).tap {|req|
|
@@ -32,7 +37,10 @@ module HTTP
|
|
32
37
|
# Send an asynchronous GET request.
|
33
38
|
#
|
34
39
|
# @param url [String] the URL to request
|
35
|
-
#
|
40
|
+
#
|
41
|
+
# @yieldparam request [Request] the request to configure
|
42
|
+
#
|
43
|
+
# @return [Promise] a promise that will be resolved with the response
|
36
44
|
def self.get(url, &block)
|
37
45
|
send(:get, url, &block)
|
38
46
|
end
|
@@ -40,7 +48,10 @@ module HTTP
|
|
40
48
|
# Send an asynchronous HEAD request.
|
41
49
|
#
|
42
50
|
# @param url [String] the URL to request
|
43
|
-
#
|
51
|
+
#
|
52
|
+
# @yieldparam request [Request] the request to configure
|
53
|
+
#
|
54
|
+
# @return [Promise] a promise that will be resolved with the response
|
44
55
|
def self.head(url, &block)
|
45
56
|
send(:head, url, &block)
|
46
57
|
end
|
@@ -49,7 +60,10 @@ module HTTP
|
|
49
60
|
#
|
50
61
|
# @param url [String] the URL to request
|
51
62
|
# @param data [String, Hash] the data to send
|
52
|
-
#
|
63
|
+
#
|
64
|
+
# @yieldparam request [Request] the request to configure
|
65
|
+
#
|
66
|
+
# @return [Promise] a promise that will be resolved with the response
|
53
67
|
def self.post(url, data = nil, &block)
|
54
68
|
send(:post, url, data, &block)
|
55
69
|
end
|
@@ -58,7 +72,10 @@ module HTTP
|
|
58
72
|
#
|
59
73
|
# @param url [String] the URL to request
|
60
74
|
# @param data [String, Hash] the data to send
|
61
|
-
#
|
75
|
+
#
|
76
|
+
# @yieldparam request [Request] the request to configure
|
77
|
+
#
|
78
|
+
# @return [Promise] a promise that will be resolved with the response
|
62
79
|
def self.put(url, data = nil, &block)
|
63
80
|
send(:put, url, data, &block)
|
64
81
|
end
|
@@ -67,7 +84,10 @@ module HTTP
|
|
67
84
|
#
|
68
85
|
# @param url [String] the URL to request
|
69
86
|
# @param data [String, Hash] the data to send
|
70
|
-
#
|
87
|
+
#
|
88
|
+
# @yieldparam request [Request] the request to configure
|
89
|
+
#
|
90
|
+
# @return [Promise] a promise that will be resolved with the response
|
71
91
|
def self.delete(url, data = nil, &block)
|
72
92
|
send(:delete, url, data, &block)
|
73
93
|
end
|
@@ -77,6 +97,9 @@ module HTTP
|
|
77
97
|
# @param method [Symbol] the HTTP method to use
|
78
98
|
# @param url [String] the URL to request
|
79
99
|
# @param data [String, Hash] the data to send
|
100
|
+
#
|
101
|
+
# @yieldparam request [Request] the request to configure
|
102
|
+
#
|
80
103
|
# @return [Response] the response
|
81
104
|
def self.send!(method, url, data = nil, &block)
|
82
105
|
Request.new(&block).open(method, url, false).send(data)
|
@@ -85,6 +108,9 @@ module HTTP
|
|
85
108
|
# Send a synchronous GET request.
|
86
109
|
#
|
87
110
|
# @param url [String] the URL to request
|
111
|
+
#
|
112
|
+
# @yieldparam request [Request] the request to configure
|
113
|
+
#
|
88
114
|
# @return [Response] the response
|
89
115
|
def self.get!(url, &block)
|
90
116
|
send!(:get, url, &block)
|
@@ -93,6 +119,9 @@ module HTTP
|
|
93
119
|
# Send a synchronous HEAD request.
|
94
120
|
#
|
95
121
|
# @param url [String] the URL to request
|
122
|
+
#
|
123
|
+
# @yieldparam request [Request] the request to configure
|
124
|
+
#
|
96
125
|
# @return [Response] the response
|
97
126
|
def self.head!(url, &block)
|
98
127
|
send!(:head, url, &block)
|
@@ -102,6 +131,9 @@ module HTTP
|
|
102
131
|
#
|
103
132
|
# @param url [String] the URL to request
|
104
133
|
# @param data [String, Hash] the data to send
|
134
|
+
#
|
135
|
+
# @yieldparam request [Request] the request to configure
|
136
|
+
#
|
105
137
|
# @return [Response] the response
|
106
138
|
def self.post!(url, data = nil, &block)
|
107
139
|
send!(:post, url, data, &block)
|
@@ -111,6 +143,9 @@ module HTTP
|
|
111
143
|
#
|
112
144
|
# @param url [String] the URL to request
|
113
145
|
# @param data [String, Hash] the data to send
|
146
|
+
#
|
147
|
+
# @yieldparam request [Request] the request to configure
|
148
|
+
#
|
114
149
|
# @return [Response] the response
|
115
150
|
def self.put!(url, data = nil, &block)
|
116
151
|
send!(:put, url, data, &block)
|
@@ -120,6 +155,9 @@ module HTTP
|
|
120
155
|
#
|
121
156
|
# @param url [String] the URL to request
|
122
157
|
# @param data [String, Hash] the data to send
|
158
|
+
#
|
159
|
+
# @yieldparam request [Request] the request to configure
|
160
|
+
#
|
123
161
|
# @return [Response] the response
|
124
162
|
def self.delete!(url, data = nil, &block)
|
125
163
|
send!(:delete, url, data, &block)
|
data/opal/browser/immediate.rb
CHANGED
@@ -1,9 +1,28 @@
|
|
1
|
-
require 'browser/compatibility/immediate'
|
2
|
-
|
3
1
|
module Browser
|
4
2
|
|
5
|
-
#
|
3
|
+
# Class to easily create and dispatch an immediate call.
|
4
|
+
#
|
5
|
+
# Immediate calls are deferred function calls that happen as soon as they can
|
6
|
+
# be scheduled.
|
7
|
+
#
|
8
|
+
# Compatibility
|
9
|
+
# -------------
|
10
|
+
# The compatibility layer will try various implementations in the following
|
11
|
+
# order.
|
12
|
+
#
|
13
|
+
# + [setImmediate](https://developer.mozilla.org/en-US/docs/Web/API/Window.setImmediate)
|
14
|
+
# + [postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage)
|
15
|
+
# + [readystatechange](https://developer.mozilla.org/en-US/docs/Web/Reference/Events/readystatechange)
|
16
|
+
# + [setTimeout](https://developer.mozilla.org/en/docs/Web/API/window.setTimeout)
|
17
|
+
#
|
18
|
+
# The order has been chosen from best to worst for both performance and
|
19
|
+
# preemptiveness.
|
6
20
|
class Immediate
|
21
|
+
# Create an immediate for the given function which will be called with the
|
22
|
+
# arguments and block.
|
23
|
+
#
|
24
|
+
# @param func [Proc] the function to call
|
25
|
+
# @param args [Array] the arguments to call it with
|
7
26
|
def initialize(func, args, &block)
|
8
27
|
@aborted = false
|
9
28
|
@function = func
|
@@ -11,14 +30,88 @@ class Immediate
|
|
11
30
|
@block = block
|
12
31
|
end
|
13
32
|
|
14
|
-
|
15
|
-
|
16
|
-
|
33
|
+
# @!method dispatch
|
34
|
+
# Dispatch the immediate.
|
35
|
+
|
36
|
+
# @!method prevent
|
37
|
+
# Prevent the immediate from being called once scheduled.
|
38
|
+
if Browser.supports? 'Immediate'
|
39
|
+
def dispatch
|
40
|
+
@id = `window.setImmediate(function() {
|
41
|
+
#{@function.call(*@arguments, &@block)};
|
42
|
+
})`
|
43
|
+
end
|
44
|
+
|
45
|
+
def prevent
|
46
|
+
`window.clearImmediate(#@id)`
|
47
|
+
end
|
48
|
+
elsif Browser.supports? 'Immediate (Internet Explorer)'
|
49
|
+
def dispatch
|
50
|
+
@id = `window.msSetImmediate(function() {
|
51
|
+
#{@function.call(*@arguments, &@block)};
|
52
|
+
})`
|
53
|
+
end
|
54
|
+
|
55
|
+
def prevent
|
56
|
+
`window.msClearImmediate(#@id)`
|
57
|
+
end
|
58
|
+
elsif Browser.supports? 'Window.send (Asynchronous)'
|
59
|
+
# @private
|
60
|
+
@@tasks = {}
|
61
|
+
|
62
|
+
# @private
|
63
|
+
@@prefix = "opal.browser.immediate.#{rand(1_000_000)}."
|
64
|
+
|
65
|
+
$window.on :message do |e|
|
66
|
+
if String === e.data && e.data.start_with?(@@prefix)
|
67
|
+
if task = @@tasks.delete(e.data[@@prefix.length .. -1])
|
68
|
+
task[0].call(*task[1], &task[2])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def dispatch
|
74
|
+
@id = rand(1_000_000).to_s
|
75
|
+
@@tasks[@id] = [@function, @arguments, @block]
|
76
|
+
|
77
|
+
$window.send "#{@@prefix}#{@id}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def prevent
|
81
|
+
@@tasks.delete(@id)
|
82
|
+
end
|
83
|
+
elsif Browser.supports? 'Event.readystatechange'
|
84
|
+
def dispatch
|
85
|
+
%x{
|
86
|
+
var script = document.createElement("script");
|
87
|
+
|
88
|
+
script.onreadystatechange = function() {
|
89
|
+
if (!#{aborted?}) {
|
90
|
+
#{@function.call(*@arguments, &@block)};
|
91
|
+
}
|
92
|
+
|
93
|
+
script.onreadystatechange = null;
|
94
|
+
script.parentNode.removeChild(script);
|
95
|
+
};
|
17
96
|
|
18
|
-
|
19
|
-
|
20
|
-
|
97
|
+
document.documentElement.appendChild(script);
|
98
|
+
}
|
99
|
+
end
|
21
100
|
|
101
|
+
def prevent; end
|
102
|
+
else
|
103
|
+
def dispatch
|
104
|
+
@id = `window.setTimeout(function() {
|
105
|
+
#{@function.call(*@arguments, &@block)};
|
106
|
+
}, 0)`
|
107
|
+
end
|
108
|
+
|
109
|
+
def prevent
|
110
|
+
`window.clearTimeout(#@id)`
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Abort the immediate.
|
22
115
|
def abort
|
23
116
|
return if aborted?
|
24
117
|
|
@@ -28,6 +121,7 @@ class Immediate
|
|
28
121
|
self
|
29
122
|
end
|
30
123
|
|
124
|
+
# Check if the immediate has been aborted.
|
31
125
|
def aborted?
|
32
126
|
@aborted
|
33
127
|
end
|
@@ -35,9 +129,33 @@ end
|
|
35
129
|
|
36
130
|
end
|
37
131
|
|
132
|
+
module Kernel
|
133
|
+
# (see Immediate.new)
|
134
|
+
def defer(*args, &block)
|
135
|
+
Browser::Immediate.new(block, args).tap(&:dispatch)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
38
139
|
class Proc
|
39
|
-
#
|
140
|
+
# (see Immediate.new)
|
40
141
|
def defer(*args, &block)
|
41
142
|
Browser::Immediate.new(self, args, &block).tap(&:dispatch)
|
42
143
|
end
|
43
144
|
end
|
145
|
+
|
146
|
+
class Promise
|
147
|
+
# Create a promise which will be resolved with the result of the immediate.
|
148
|
+
#
|
149
|
+
# @param args [Array] the arguments the block will be called with
|
150
|
+
def self.defer(*args, &block)
|
151
|
+
new.tap {|promise|
|
152
|
+
proc {
|
153
|
+
begin
|
154
|
+
promise.resolve(block.call(*args))
|
155
|
+
rescue Exception => e
|
156
|
+
promise.reject(e)
|
157
|
+
end
|
158
|
+
}.defer
|
159
|
+
}
|
160
|
+
end
|
161
|
+
end
|
data/opal/browser/interval.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
module Browser
|
2
2
|
|
3
|
-
#
|
3
|
+
# Allows you to create an interval that executes the function every given
|
4
|
+
# seconds.
|
5
|
+
#
|
6
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval
|
4
7
|
class Interval
|
5
8
|
# @!attribute [r] every
|
6
|
-
# @return [
|
9
|
+
# @return [Float] the seconds every which the block is called
|
7
10
|
attr_reader :every
|
8
11
|
|
9
12
|
# Create and start an interval.
|
10
13
|
#
|
11
14
|
# @param window [Window] the window to start the interval on
|
12
|
-
# @param time [
|
15
|
+
# @param time [Float] seconds every which to call the block
|
13
16
|
def initialize(window, time, &block)
|
14
17
|
@window = Native.convert(window)
|
15
18
|
@every = time
|
16
19
|
@block = block
|
17
20
|
|
18
21
|
@aborted = false
|
19
|
-
@stopped = true
|
20
|
-
|
21
|
-
start
|
22
22
|
end
|
23
23
|
|
24
24
|
# Check if the interval has been stopped.
|
25
25
|
def stopped?
|
26
|
-
@
|
26
|
+
@id.nil?
|
27
27
|
end
|
28
28
|
|
29
29
|
# Check if the interval has been aborted.
|
@@ -32,21 +32,17 @@ class Interval
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# Abort the interval, it won't be possible to start it again.
|
35
|
-
#
|
36
|
-
# @return [self]
|
37
35
|
def abort
|
38
36
|
`#@window.clearInterval(#@id)`
|
39
37
|
|
40
38
|
@aborted = true
|
41
39
|
@id = nil
|
42
|
-
|
43
|
-
self
|
44
40
|
end
|
45
41
|
|
46
42
|
# Stop the interval, it will be possible to start it again.
|
47
|
-
#
|
48
|
-
# @return [self]
|
49
43
|
def stop
|
44
|
+
return if stopped?
|
45
|
+
|
50
46
|
`#@window.clearInterval(#@id)`
|
51
47
|
|
52
48
|
@stopped = true
|
@@ -54,16 +50,16 @@ class Interval
|
|
54
50
|
end
|
55
51
|
|
56
52
|
# Start the interval if it has been stopped.
|
57
|
-
#
|
58
|
-
# @return [self]
|
59
53
|
def start
|
60
54
|
raise "the interval has been aborted" if aborted?
|
61
|
-
|
62
55
|
return unless stopped?
|
63
56
|
|
64
|
-
@id = `#@window.setInterval(
|
57
|
+
@id = `#@window.setInterval(#@block, #@every * 1000)`
|
58
|
+
end
|
65
59
|
|
66
|
-
|
60
|
+
# Call the [Interval] block.
|
61
|
+
def call
|
62
|
+
@block.call
|
67
63
|
end
|
68
64
|
end
|
69
65
|
|
@@ -71,23 +67,45 @@ class Window
|
|
71
67
|
# Execute the block every given seconds.
|
72
68
|
#
|
73
69
|
# @param time [Float] the seconds between every call
|
70
|
+
#
|
74
71
|
# @return [Interval] the object representing the interval
|
75
72
|
def every(time, &block)
|
73
|
+
Interval.new(@native, time, &block).tap(&:start)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Execute the block every given seconds, you have to call [#start] on it
|
77
|
+
# yourself.
|
78
|
+
#
|
79
|
+
# @param time [Float] the seconds between every call
|
80
|
+
#
|
81
|
+
# @return [Interval] the object representing the interval
|
82
|
+
def every!(time, &block)
|
76
83
|
Interval.new(@native, time, &block)
|
77
84
|
end
|
78
85
|
end
|
79
86
|
|
80
87
|
end
|
81
88
|
|
89
|
+
module Kernel
|
90
|
+
# (see Browser::Window#every)
|
91
|
+
def every(time, &block)
|
92
|
+
$window.every(time, &block)
|
93
|
+
end
|
94
|
+
|
95
|
+
# (see Browser::Window#every!)
|
96
|
+
def every!(time, &block)
|
97
|
+
$window.every!(time, &block)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
82
101
|
class Proc
|
102
|
+
# (see Browser::Window#every)
|
83
103
|
def every(time)
|
84
104
|
$window.every(time, &self)
|
85
105
|
end
|
86
|
-
end
|
87
106
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
$window.every(time, &block)
|
107
|
+
# (see Browser::Window#every!)
|
108
|
+
def every!(time)
|
109
|
+
$window.every!(time, &self)
|
92
110
|
end
|
93
111
|
end
|
data/opal/browser/location.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
module Browser
|
2
2
|
|
3
|
+
# Allows manipulation of a location, usually from {Window} and {DOM::Document}.
|
4
|
+
#
|
5
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Location
|
3
6
|
class Location
|
4
|
-
include
|
7
|
+
include Browser::NativeCachedWrapper
|
5
8
|
|
6
9
|
# Change the location.
|
7
10
|
#
|
@@ -63,12 +66,25 @@ class Location
|
|
63
66
|
# @return [String] the query part of the location URI
|
64
67
|
alias_native :query, :search
|
65
68
|
alias_native :query=, :search=
|
69
|
+
|
70
|
+
# Returns the full path of the location URI, including
|
71
|
+
# the query string and fragment, eg. /site?a=b#c
|
72
|
+
def full_path
|
73
|
+
path + query + fragment
|
74
|
+
end
|
66
75
|
end
|
67
76
|
|
68
77
|
class Window
|
69
|
-
#
|
70
|
-
#
|
71
|
-
|
78
|
+
# @!attribute [r] location
|
79
|
+
# @return [Location] the location for the window
|
80
|
+
def location
|
81
|
+
Location.new(`#@native.location`) if `#@native.location`
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class DOM::Document < DOM::Element
|
86
|
+
# @!attribute [r] location
|
87
|
+
# @return [Location] the location for the document
|
72
88
|
def location
|
73
89
|
Location.new(`#@native.location`) if `#@native.location`
|
74
90
|
end
|
data/opal/browser/navigator.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
module Browser
|
2
2
|
|
3
|
-
#
|
3
|
+
# Representation of the navigator application.
|
4
|
+
#
|
5
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator
|
4
6
|
class Navigator
|
5
|
-
include
|
7
|
+
include Browser::NativeCachedWrapper
|
6
8
|
|
7
9
|
Version = Struct.new(:major, :minor, :build)
|
8
10
|
Product = Struct.new(:name, :version)
|
9
11
|
Vendor = Struct.new(:name, :version)
|
10
12
|
|
11
|
-
#
|
13
|
+
# Representation of a MIME type.
|
12
14
|
class MimeType
|
13
|
-
include
|
15
|
+
include Browser::NativeCachedWrapper
|
14
16
|
|
15
17
|
# @!attribute [r] plugin
|
16
18
|
# @return [Plugin] the plugin for the MIME type
|
@@ -33,7 +35,9 @@ class Navigator
|
|
33
35
|
alias_native :type
|
34
36
|
end
|
35
37
|
|
36
|
-
#
|
38
|
+
# Representation of a navigator plugin.
|
39
|
+
#
|
40
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Plugin
|
37
41
|
class Plugin < Native::Array
|
38
42
|
def initialize(plugin)
|
39
43
|
super plugin do |m|
|
@@ -58,6 +62,27 @@ class Navigator
|
|
58
62
|
alias_native :version
|
59
63
|
end
|
60
64
|
|
65
|
+
# Representation for the array of plugins.
|
66
|
+
#
|
67
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/NavigatorPlugins
|
68
|
+
class Plugins < Native::Array
|
69
|
+
def initialize(plugins)
|
70
|
+
super plugins do |p|
|
71
|
+
Plugin.new(p)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Reload all browser plugins.
|
76
|
+
def refresh
|
77
|
+
`#@native.refresh(false)`
|
78
|
+
end
|
79
|
+
|
80
|
+
# Reload all browser plugins reloading pages that contain `<embed>`s.
|
81
|
+
def refresh!
|
82
|
+
`#@native.refresh(true)`
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
61
86
|
# @!attribute [r] code
|
62
87
|
# @return [String] the browser code name
|
63
88
|
alias_native :code, :appCodeName
|
@@ -108,11 +133,9 @@ class Navigator
|
|
108
133
|
alias_native :platform
|
109
134
|
|
110
135
|
# @!attribute [r] plugins
|
111
|
-
# @return [
|
136
|
+
# @return [Plugins] the enabled plugins
|
112
137
|
def plugins
|
113
|
-
|
114
|
-
Plugin.new(p)
|
115
|
-
end
|
138
|
+
Plugins.new(`#@native.plugins`)
|
116
139
|
end
|
117
140
|
|
118
141
|
# @!attribute [r] product
|
@@ -137,14 +160,114 @@ class Navigator
|
|
137
160
|
rescue
|
138
161
|
false
|
139
162
|
end
|
163
|
+
|
164
|
+
# Representation of user location based on Geolocation API
|
165
|
+
#
|
166
|
+
# Example usage:
|
167
|
+
# ```
|
168
|
+
# $window.navigator.geolocate.then do |pos|
|
169
|
+
# puts "#{pos.coords.latitude}, #{pos.coords.longitude}, #{pos.coords.accuracy}"
|
170
|
+
# end
|
171
|
+
# ```
|
172
|
+
#
|
173
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Position
|
174
|
+
class Position
|
175
|
+
include Browser::NativeCachedWrapper
|
176
|
+
|
177
|
+
class Coords
|
178
|
+
include Native::Wrapper
|
179
|
+
|
180
|
+
# @!attribute [r] latitude
|
181
|
+
alias_native :latitude
|
182
|
+
# @!attribute [r] longitude
|
183
|
+
alias_native :longitude
|
184
|
+
# @!attribute [r] altitude
|
185
|
+
alias_native :altitude
|
186
|
+
# @!attribute [r] accuracy
|
187
|
+
alias_native :accuracy
|
188
|
+
# @!attribute [r] altitude_accuracy
|
189
|
+
alias_native :altitude_accuracy, :altitudeAccuracy
|
190
|
+
# @!attribute [r] heading
|
191
|
+
alias_native :heading
|
192
|
+
# @!attribute [r] speed
|
193
|
+
alias_native :speed
|
194
|
+
end
|
195
|
+
|
196
|
+
# @!attribute [r] timestamp
|
197
|
+
alias_native :timestamp
|
198
|
+
|
199
|
+
def coords
|
200
|
+
@coords ||= Coords.new(`#@native.coords`)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Geolocates the user once
|
205
|
+
#
|
206
|
+
# @return [Promise] promise that resolves to the {Position} object
|
207
|
+
def geolocate(max_age: 0, timeout: Float::INFINITY, high_accuracy: false)
|
208
|
+
promise = Promise.new
|
209
|
+
succ = proc { |i| promise.resolve(Position.new(i)) }
|
210
|
+
fail = proc { |i| promise.reject(Native(i)) }
|
211
|
+
opts = {maxAge: max_age, timeout: timeout, enableHighAccuracy: high_accuracy}
|
212
|
+
`#@native.geolocation.getCurrentPosition(#{succ.to_n}, #{fail.to_n}, #{opts.to_n})`
|
213
|
+
promise
|
214
|
+
end
|
215
|
+
|
216
|
+
# Geolocates the user multiple times and calls a block with his location
|
217
|
+
# until #stop_tracking is called with a returned id. Calls a proc named error
|
218
|
+
# if error happens.
|
219
|
+
#
|
220
|
+
# @return [Integer] an ID that can be used as an argument to #stop_tracking
|
221
|
+
def track(max_age: 0, timeout: Float::INFINITY, high_accuracy: false, error: proc{|i|}, &block)
|
222
|
+
opts = {maxAge: max_age, timeout: timeout, enableHighAccuracy: high_accuracy}
|
223
|
+
succ = proc { |i| block.call(Position.new(i)) }
|
224
|
+
fail = proc { |i| error.call(Native(i)) }
|
225
|
+
`#@native.geolocation.watchPosition(#{succ.to_n}, #{fail.to_n}, #{opts.to_n})`
|
226
|
+
end
|
227
|
+
|
228
|
+
def stop_tracking(id)
|
229
|
+
`#@native.geolocation.clearWatch(#{id})`
|
230
|
+
end
|
231
|
+
|
232
|
+
# Triggers a vibration on a device. A pattern can be either a number of
|
233
|
+
# miliseconds for a vibration length, or an array of lengths (in
|
234
|
+
# miliseconds) which describes a vibration pattern - first element of said
|
235
|
+
# array describes how long the device should vibrate, second - how long to
|
236
|
+
# stop for and so on.
|
237
|
+
def vibrate(pattern)
|
238
|
+
`#@native.vibrate(#{pattern.to_n})`
|
239
|
+
end
|
240
|
+
|
241
|
+
# Check a battery status of user device. This API is deprecated in the browser
|
242
|
+
# context and usable mainly in privileged contexts.
|
243
|
+
#
|
244
|
+
# @return [Promise] a promise that resolves with a battery status
|
245
|
+
#
|
246
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getBattery
|
247
|
+
def get_battery
|
248
|
+
promise = Promise.new
|
249
|
+
yes = proc { |r| promise.resolve(Native(r)) }
|
250
|
+
no = proc { |r| promise.reject(Native(r)) }
|
251
|
+
`#@native.getBattery().then(#{yes.to_n}).catch(#{no.to_n})`
|
252
|
+
promise
|
253
|
+
end
|
254
|
+
|
255
|
+
# Queue to send a small amount of data to a server.
|
256
|
+
#
|
257
|
+
# @param url [String] url to trigger
|
258
|
+
# @param payload [String, Blob, FormData, Hash] data to send
|
259
|
+
#
|
260
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
|
261
|
+
def send_beacon(url, payload=nil)
|
262
|
+
`#@native.sendBeacon(#{url}, #{payload.to_n})`
|
263
|
+
end
|
140
264
|
end
|
141
265
|
|
142
266
|
class Window
|
143
|
-
#
|
144
|
-
#
|
145
|
-
# @return [Navigator]
|
267
|
+
# @!attribute [r] navigator
|
268
|
+
# @return [Navigator] the navigator
|
146
269
|
def navigator
|
147
|
-
Navigator.new(`#@native.navigator`) if `#@native.navigator`
|
270
|
+
@navigator ||= Navigator.new(`#@native.navigator`) if `#@native.navigator`
|
148
271
|
end
|
149
272
|
end
|
150
273
|
|