opal-browser 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/build.yml +95 -0
- data/.gitignore +2 -0
- data/Gemfile +17 -3
- data/LICENSE +2 -1
- data/README.md +116 -54
- data/Rakefile +29 -1
- data/config.ru +20 -3
- data/docs/polyfills.md +24 -0
- data/examples/2048/Gemfile +7 -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 +7 -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 +7 -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 +7 -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 +8 -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 +9 -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 +8 -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 +4 -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 +4 -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 +5 -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 +7 -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 +5 -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 +16 -7
- 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 +193 -48
- data/opal/browser/dom/mutation_observer.rb +2 -2
- data/opal/browser/dom/node.rb +53 -13
- data/opal/browser/dom/node_set.rb +11 -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 +13 -1
- 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 +119 -16
- data/.travis.yml +0 -74
- data/opal/browser/window/scroll.rb +0 -59
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Browser; class Canvas
|
|
2
2
|
|
|
3
3
|
class StyleObject
|
|
4
|
-
include Native
|
|
4
|
+
include Native::Wrapper
|
|
5
5
|
|
|
6
6
|
attr_reader :context
|
|
7
7
|
|
|
@@ -56,10 +56,12 @@ class Style < StyleObject
|
|
|
56
56
|
|
|
57
57
|
def smooth!
|
|
58
58
|
`#@native.mozImageSmoothingEnabled = #{@smooth = true}`
|
|
59
|
+
`#@native.imageSmoothingEnabled = #{@smooth = true}`
|
|
59
60
|
end
|
|
60
61
|
|
|
61
62
|
def no_smooth!
|
|
62
63
|
`#@native.mozImageSmoothingEnabled = #{@smooth = false}`
|
|
64
|
+
`#@native.imageSmoothingEnabled = #{@smooth = false}`
|
|
63
65
|
end
|
|
64
66
|
end
|
|
65
67
|
|
data/opal/browser/canvas/text.rb
CHANGED
data/opal/browser/canvas.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'promise'
|
|
2
|
-
|
|
3
1
|
require 'browser/canvas/style'
|
|
4
2
|
require 'browser/canvas/text'
|
|
5
3
|
require 'browser/canvas/data'
|
|
@@ -8,7 +6,7 @@ require 'browser/canvas/gradient'
|
|
|
8
6
|
module Browser
|
|
9
7
|
|
|
10
8
|
class Canvas
|
|
11
|
-
include Native
|
|
9
|
+
include Native::Wrapper
|
|
12
10
|
|
|
13
11
|
attr_reader :element, :style, :text
|
|
14
12
|
|
|
@@ -59,6 +57,14 @@ class Canvas
|
|
|
59
57
|
@element[:height].to_i
|
|
60
58
|
end
|
|
61
59
|
|
|
60
|
+
def width=(new_width)
|
|
61
|
+
@element[:width] = new_width.to_i
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def height=(new_height)
|
|
65
|
+
@element[:height] = new_height.to_i
|
|
66
|
+
end
|
|
67
|
+
|
|
62
68
|
def append_to(parent)
|
|
63
69
|
@element.append_to(parent)
|
|
64
70
|
end
|
|
@@ -312,6 +318,14 @@ class Canvas
|
|
|
312
318
|
def to_data(type = undefined)
|
|
313
319
|
`#{@element.to_n}.toDataUrl(type)`
|
|
314
320
|
end
|
|
321
|
+
|
|
322
|
+
def to_dom(*)
|
|
323
|
+
@element
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def on(*args, &block); @element.on(*args, &block); end
|
|
327
|
+
def one(*args, &block); @element.one(*args, &block); end
|
|
328
|
+
def off(*args, &block); @element.off(*args, &block); end
|
|
315
329
|
end
|
|
316
330
|
|
|
317
331
|
Browser::DOM::Builder.for Canvas do |b, item|
|
data/opal/browser/console.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
warn "`console' has been moved to Opal's stdlib, please `require 'console'` instead." if RUBY_ENGINE_VERSION.to_f >= 0.9
|
|
2
|
+
|
|
1
3
|
module Browser
|
|
2
4
|
|
|
3
5
|
# Manipulate the browser console.
|
|
4
6
|
#
|
|
5
7
|
# @see https://developer.mozilla.org/en-US/docs/Web/API/console
|
|
6
8
|
class Console
|
|
7
|
-
include
|
|
9
|
+
include Browser::NativeCachedWrapper
|
|
8
10
|
|
|
9
11
|
# Clear the console.
|
|
10
12
|
def clear
|
data/opal/browser/cookies.rb
CHANGED
|
@@ -5,10 +5,17 @@ module Browser
|
|
|
5
5
|
# Allows manipulation of browser cookies.
|
|
6
6
|
#
|
|
7
7
|
# @see https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
#
|
|
11
|
+
# cookies = Browser::Cookies.new(`document`)
|
|
12
|
+
# cookies["my-cookie"] = "monster"
|
|
13
|
+
# cookies.delete("my-cookie")
|
|
14
|
+
#
|
|
8
15
|
class Cookies
|
|
9
16
|
# Default cookie options.
|
|
10
17
|
DEFAULT = {
|
|
11
|
-
expires: Time.now +
|
|
18
|
+
expires: Time.now + 60 * 60 * 24,
|
|
12
19
|
secure: false
|
|
13
20
|
}
|
|
14
21
|
|
|
@@ -30,12 +37,12 @@ class Cookies
|
|
|
30
37
|
#
|
|
31
38
|
# @return [Object]
|
|
32
39
|
def [](name)
|
|
33
|
-
matches = `#@document.cookie`.scan(/#{Regexp.escape(name
|
|
40
|
+
matches = `#@document.cookie`.scan(/#{Regexp.escape(FormData.encode(name))}=([^;]*)/)
|
|
34
41
|
|
|
35
42
|
return if matches.empty?
|
|
36
43
|
|
|
37
|
-
result = matches.map {|
|
|
38
|
-
JSON.parse(
|
|
44
|
+
result = matches.flatten.map {|value|
|
|
45
|
+
JSON.parse(FormData.decode(value))
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
result.length == 1 ? result.first : result
|
|
@@ -53,7 +60,9 @@ class Cookies
|
|
|
53
60
|
# @option options [String] :domain the domain the cookie is valid on
|
|
54
61
|
# @option options [Boolean] :secure whether the cookie is secure or not
|
|
55
62
|
def []=(name, value, options = {})
|
|
56
|
-
|
|
63
|
+
string = value.is_a?(String) ? value : JSON.dump(value)
|
|
64
|
+
encoded_value = encode(name, string, @options.merge(options))
|
|
65
|
+
`#@document.cookie = #{encoded_value}`
|
|
57
66
|
end
|
|
58
67
|
|
|
59
68
|
# Delete a cookie.
|
|
@@ -110,10 +119,10 @@ protected
|
|
|
110
119
|
def encode(key, value, options = {})
|
|
111
120
|
io = StringIO.new
|
|
112
121
|
|
|
113
|
-
io << key
|
|
122
|
+
io << FormData.encode(key) << ?= << FormData.encode(value) << '; '
|
|
114
123
|
|
|
115
124
|
io << 'max-age=' << options[:max_age] << '; ' if options[:max_age]
|
|
116
|
-
io << 'expires=' << options[:expires].
|
|
125
|
+
io << 'expires=' << options[:expires].utc << '; ' if options[:expires]
|
|
117
126
|
io << 'path=' << options[:path] << '; ' if options[:path]
|
|
118
127
|
io << 'domain=' << options[:domain] << '; ' if options[:domain]
|
|
119
128
|
io << 'secure' if options[:secure]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Browser
|
|
2
|
+
|
|
3
|
+
# Implements (parts of) the web crypto interface
|
|
4
|
+
#
|
|
5
|
+
# https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API
|
|
6
|
+
class Crypto
|
|
7
|
+
include NativeCachedWrapper
|
|
8
|
+
|
|
9
|
+
class Digest
|
|
10
|
+
def initialize(buf)
|
|
11
|
+
@buffer = Buffer.new(buf)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attr_reader :buffer
|
|
15
|
+
|
|
16
|
+
# Convert a digest to a hexadecimal string
|
|
17
|
+
def to_hex
|
|
18
|
+
buffer.to_a.map { |i| "%02x" % i }.join
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Convert a digest to a binary string
|
|
22
|
+
def to_s
|
|
23
|
+
buffer.to_a.map { |i| "%c" % i }.join
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Convert a digest to a Base64-encoded string
|
|
27
|
+
#
|
|
28
|
+
# You will need to `require "base64"`
|
|
29
|
+
def to_b64
|
|
30
|
+
Base64.strict_encode64(to_s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Convert a digest to a urlsafe Base64-encoded string
|
|
34
|
+
#
|
|
35
|
+
# You will need to `require "base64"`
|
|
36
|
+
def to_u64(padding: false)
|
|
37
|
+
Base64.urlsafe_encode64(to_s, padding: padding)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Compute a cryptographic digest of data (a Buffer). If block is given,
|
|
42
|
+
# it will call a block, otherwise it will return a Promise that will
|
|
43
|
+
# return once a digest is computed.
|
|
44
|
+
#
|
|
45
|
+
# Allowed values for algo: SHA-1, SHA-256 (default), SHA-368, SHA-512.
|
|
46
|
+
#
|
|
47
|
+
# The block/promise will be given an argument of type {Digest} which can
|
|
48
|
+
# be used to format a digest.
|
|
49
|
+
#
|
|
50
|
+
# Example:
|
|
51
|
+
# ```
|
|
52
|
+
# Browser::Blob.new(['test']).buffer.then { |b|
|
|
53
|
+
# $window.crypto.digest(b)
|
|
54
|
+
# }.then { |d|
|
|
55
|
+
# puts d.to_hex
|
|
56
|
+
# }
|
|
57
|
+
# ```
|
|
58
|
+
def digest data, algo = 'SHA-256', &block
|
|
59
|
+
promise = nil
|
|
60
|
+
unless block_given?
|
|
61
|
+
promise = Promise.new
|
|
62
|
+
block = proc { |i| promise.resolve(i) }
|
|
63
|
+
end
|
|
64
|
+
resblock = proc { |i| block.call(Digest.new(i)) }
|
|
65
|
+
|
|
66
|
+
`#@native.subtle.digest(algo, #{Native.convert(data)}).then(#{resblock.to_n})`
|
|
67
|
+
promise
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class Window
|
|
72
|
+
# @!attribute [r] crypto
|
|
73
|
+
# @return [Crypto] the crypto interface of this window
|
|
74
|
+
def crypto
|
|
75
|
+
@crypto ||= Crypto.new(`#@native.crypto`)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
data/opal/browser/css/rule.rb
CHANGED
data/opal/browser/css.rb
CHANGED
|
@@ -4,19 +4,35 @@ require 'browser/css/rule'
|
|
|
4
4
|
require 'browser/css/rule/style'
|
|
5
5
|
|
|
6
6
|
module Kernel
|
|
7
|
-
#
|
|
8
|
-
# {Browser::CSS::Builder} DSL.
|
|
7
|
+
# @overload CSS(document = $document, &block)
|
|
9
8
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
# Create a `<style>` element from a {Paggio::CSS} DSL.
|
|
10
|
+
#
|
|
11
|
+
# @param document [Browser::DOM::Document] the document instance
|
|
12
|
+
# we intend to use
|
|
13
|
+
#
|
|
14
|
+
# @return [Browser::DOM::Element] the created `<style>` element
|
|
15
|
+
#
|
|
16
|
+
# @overload CSS(string, document = $document)
|
|
17
|
+
#
|
|
18
|
+
# Create a `<style>` element from a string.
|
|
19
|
+
#
|
|
20
|
+
# @param document [Browser::DOM::Document] the document instance
|
|
21
|
+
# we intend to use
|
|
22
|
+
#
|
|
23
|
+
# @return [Browser::DOM::Element] the created `<style>` element
|
|
24
|
+
def CSS(*args, &block)
|
|
25
|
+
document = if args.length > 1 || block_given?
|
|
26
|
+
args.pop
|
|
27
|
+
end || $document
|
|
28
|
+
|
|
29
|
+
style = document.create_element(:style)
|
|
14
30
|
style[:type] = 'text/css'
|
|
15
31
|
|
|
16
32
|
if block
|
|
17
33
|
style.inner_text = Paggio.css(&block)
|
|
18
34
|
else
|
|
19
|
-
style.inner_text =
|
|
35
|
+
style.inner_text = args.join("")
|
|
20
36
|
end
|
|
21
37
|
|
|
22
38
|
style
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require 'promise'
|
|
2
1
|
require 'ostruct'
|
|
3
2
|
|
|
4
3
|
module Browser; module Database
|
|
@@ -27,7 +26,7 @@ class SQL
|
|
|
27
26
|
Timeout = Class.new(self)
|
|
28
27
|
end
|
|
29
28
|
|
|
30
|
-
include Native
|
|
29
|
+
include Native::Wrapper
|
|
31
30
|
|
|
32
31
|
# @return [String] the name of the database
|
|
33
32
|
attr_reader :name
|
|
@@ -73,7 +72,7 @@ class SQL
|
|
|
73
72
|
return `#@native.version` unless block
|
|
74
73
|
|
|
75
74
|
`#@native.changeVersion(#{from}, #{to},
|
|
76
|
-
#{->
|
|
75
|
+
#{->(t) { block.call(Transaction.new(self, t)) }})`
|
|
77
76
|
end
|
|
78
77
|
|
|
79
78
|
# Start a transaction on the database.
|
|
@@ -82,12 +81,12 @@ class SQL
|
|
|
82
81
|
def transaction(&block)
|
|
83
82
|
raise ArgumentError, 'no block given' unless block
|
|
84
83
|
|
|
85
|
-
`#@native.transaction(#{->
|
|
84
|
+
`#@native.transaction(#{->(t) { block.call(Transaction.new(self, t)) }})`
|
|
86
85
|
end
|
|
87
86
|
|
|
88
87
|
# Allows you to make changes to the database or read data from it.
|
|
89
88
|
class Transaction
|
|
90
|
-
include Native
|
|
89
|
+
include Native::Wrapper
|
|
91
90
|
|
|
92
91
|
# @return [Database] the database the transaction has been created from
|
|
93
92
|
attr_reader :database
|
|
@@ -109,8 +108,8 @@ class SQL
|
|
|
109
108
|
promise = Promise.new
|
|
110
109
|
|
|
111
110
|
`#@native.executeSql(#{query}, #{parameters},
|
|
112
|
-
#{->
|
|
113
|
-
#{->
|
|
111
|
+
#{->(_, r) { promise.resolve(Result.new(self, r)) }},
|
|
112
|
+
#{->(_, e) { promise.reject(Error.new(e)) }})`
|
|
114
113
|
|
|
115
114
|
promise
|
|
116
115
|
end
|
|
@@ -129,7 +128,7 @@ class SQL
|
|
|
129
128
|
end
|
|
130
129
|
|
|
131
130
|
class Result
|
|
132
|
-
include Native
|
|
131
|
+
include Native::Wrapper
|
|
133
132
|
|
|
134
133
|
# @return [Transaction] the transaction the result came from
|
|
135
134
|
attr_reader :transaction
|
data/opal/browser/delay.rb
CHANGED
|
@@ -49,6 +49,17 @@ class Window
|
|
|
49
49
|
def after!(time, &block)
|
|
50
50
|
Delay.new(@native, time, &block)
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
# Returns a promise that will resolve after the given seconds.
|
|
54
|
+
#
|
|
55
|
+
# @param time [Float] the seconds after it gets called
|
|
56
|
+
#
|
|
57
|
+
# @return [Promise] the promise that will resolve after timeout happens
|
|
58
|
+
def resolve_after(time)
|
|
59
|
+
promise = Promise.new
|
|
60
|
+
Delay.new(@native, time) { promise.resolve }.start
|
|
61
|
+
promise
|
|
62
|
+
end
|
|
52
63
|
end
|
|
53
64
|
|
|
54
65
|
end
|
|
@@ -63,6 +74,11 @@ module Kernel
|
|
|
63
74
|
def after!(time, &block)
|
|
64
75
|
$window.after!(time, &block)
|
|
65
76
|
end
|
|
77
|
+
|
|
78
|
+
# (see Browser::Window#resolve_after)
|
|
79
|
+
def resolve_after(time)
|
|
80
|
+
$window.resolve_after(time)
|
|
81
|
+
end
|
|
66
82
|
end
|
|
67
83
|
|
|
68
84
|
class Proc
|
data/opal/browser/dom/builder.rb
CHANGED
|
@@ -38,10 +38,32 @@ class Builder
|
|
|
38
38
|
|
|
39
39
|
attr_reader :document, :element
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
NEW_PAGGIO = (Paggio::HTML.instance_method(:build!) rescue false)
|
|
42
|
+
|
|
43
|
+
def initialize(document, builder=nil, &block)
|
|
42
44
|
@document = document
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
|
|
46
|
+
# Compatibility issue due to an unreleased Paggio gem.
|
|
47
|
+
# Let's try to support both versions. When Paggio is released,
|
|
48
|
+
# we may remove it.
|
|
49
|
+
|
|
50
|
+
if NEW_PAGGIO
|
|
51
|
+
@builder = Paggio::HTML.new(defer: true, &block)
|
|
52
|
+
|
|
53
|
+
build = proc do
|
|
54
|
+
@builder.build!(force_call: !!builder)
|
|
55
|
+
@roots = @builder.each.map { |e| Builder.build(self, e) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
if builder
|
|
59
|
+
builder.extend!(@builder, &build)
|
|
60
|
+
else
|
|
61
|
+
build.()
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
@builder = Paggio::HTML.new(&block)
|
|
65
|
+
@roots = @builder.each.map { |e| Builder.build(self, e) }
|
|
66
|
+
end
|
|
45
67
|
end
|
|
46
68
|
|
|
47
69
|
def to_a
|
|
@@ -54,15 +76,12 @@ Builder.for String do |b, item|
|
|
|
54
76
|
end
|
|
55
77
|
|
|
56
78
|
Builder.for Paggio::HTML::Element do |b, item|
|
|
57
|
-
|
|
79
|
+
options = {}
|
|
58
80
|
|
|
59
|
-
if Hash === `item.attributes`
|
|
60
|
-
|
|
61
|
-
end
|
|
81
|
+
options[:attrs] = `item.attributes` if Hash === `item.attributes`
|
|
82
|
+
options[:classes] = `item.class_names`
|
|
62
83
|
|
|
63
|
-
`item.
|
|
64
|
-
dom.add_class value
|
|
65
|
-
}
|
|
84
|
+
dom = b.document.create_element(`item.name`, **options)
|
|
66
85
|
|
|
67
86
|
if on = `item.on || nil`
|
|
68
87
|
on.each {|args, block|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
module Browser; module DOM
|
|
2
2
|
|
|
3
3
|
class Document < Element
|
|
4
|
+
include DocumentOrShadowRoot
|
|
5
|
+
|
|
4
6
|
# Get the first element matching the given ID, CSS selector or XPath.
|
|
5
7
|
#
|
|
6
8
|
# @param what [String] ID, CSS selector or XPath
|
|
@@ -24,20 +26,67 @@ class Document < Element
|
|
|
24
26
|
# @return [Element?] the body element of the document
|
|
25
27
|
def body
|
|
26
28
|
DOM(`#@native.body`)
|
|
29
|
+
rescue ArgumentError
|
|
30
|
+
raise '$document.body is not defined; try to wrap your code in $document.ready{}'
|
|
27
31
|
end
|
|
28
32
|
|
|
29
33
|
# Create a new element for the document.
|
|
30
34
|
#
|
|
31
35
|
# @param name [String] the node name
|
|
32
|
-
# @param
|
|
36
|
+
# @param builder [Browser::DOM::Builder] optional builder to append element to
|
|
37
|
+
# @param options [String] :namespace optional namespace name
|
|
38
|
+
# @param options [String] :is optional WebComponents is parameter
|
|
39
|
+
# @param options [String] :id optional id to set
|
|
40
|
+
# @param options [Array<String>] :classes optional classes to set
|
|
41
|
+
# @param options [Hash] :attrs optional attributes to set
|
|
33
42
|
#
|
|
34
43
|
# @return [Element]
|
|
35
|
-
def create_element(name, options
|
|
44
|
+
def create_element(name, builder=nil, **options, &block)
|
|
45
|
+
opts = {}
|
|
46
|
+
|
|
47
|
+
if options[:is] ||= (options.dig(:attrs, :is))
|
|
48
|
+
opts[:is] = options[:is]
|
|
49
|
+
end
|
|
50
|
+
|
|
36
51
|
if ns = options[:namespace]
|
|
37
|
-
|
|
52
|
+
elem = `#@native.createElementNS(#{ns}, #{name}, #{opts.to_n})`
|
|
38
53
|
else
|
|
39
|
-
|
|
54
|
+
elem = `#@native.createElement(name, #{opts.to_n})`
|
|
40
55
|
end
|
|
56
|
+
|
|
57
|
+
if options[:classes]
|
|
58
|
+
`#{elem}.className = #{Array(options[:classes]).join(" ")}`
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if options[:id]
|
|
62
|
+
`#{elem}.id = #{options[:id]}`
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if options[:attrs]
|
|
66
|
+
options[:attrs].each do |k,v|
|
|
67
|
+
next unless v
|
|
68
|
+
`#{elem}.setAttribute(#{k}, #{v})`
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
dom = DOM(elem)
|
|
73
|
+
|
|
74
|
+
if block_given?
|
|
75
|
+
dom.inner_dom(builder, &block)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if builder
|
|
79
|
+
builder << dom
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
dom
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Create a new document fragment.
|
|
86
|
+
#
|
|
87
|
+
# @return [DocumentFragment]
|
|
88
|
+
def create_document_fragment
|
|
89
|
+
DOM(`#@native.createDocumentFragment()`)
|
|
41
90
|
end
|
|
42
91
|
|
|
43
92
|
# Create a new text node for the document.
|
|
@@ -49,6 +98,15 @@ class Document < Element
|
|
|
49
98
|
DOM(`#@native.createTextNode(#{content})`)
|
|
50
99
|
end
|
|
51
100
|
|
|
101
|
+
# Create a new comment node for the document.
|
|
102
|
+
#
|
|
103
|
+
# @param content [String] the comment content
|
|
104
|
+
#
|
|
105
|
+
# @return [Comment]
|
|
106
|
+
def create_comment(content)
|
|
107
|
+
DOM(`#@native.createComment(#{content})`)
|
|
108
|
+
end
|
|
109
|
+
|
|
52
110
|
def document
|
|
53
111
|
self
|
|
54
112
|
end
|
|
@@ -98,7 +156,13 @@ class Document < Element
|
|
|
98
156
|
|
|
99
157
|
# Check if the document is ready.
|
|
100
158
|
def ready?
|
|
101
|
-
`#@native.readyState === "complete"`
|
|
159
|
+
`#@native.readyState === "complete" || #@native.readyState === "interactive"`
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# @!attribute referrer
|
|
163
|
+
# @return [String] the referring document, or empty string if direct access
|
|
164
|
+
def referrer
|
|
165
|
+
`#@native.referrer`
|
|
102
166
|
end
|
|
103
167
|
|
|
104
168
|
# @!attribute root
|
|
@@ -111,14 +175,6 @@ class Document < Element
|
|
|
111
175
|
`#@native.documentElement = #{Native.convert(element)}`
|
|
112
176
|
end
|
|
113
177
|
|
|
114
|
-
# @!attribute [r] style_sheets
|
|
115
|
-
# @return [Array<CSS::StyleSheet>] the style sheets for the document
|
|
116
|
-
def style_sheets
|
|
117
|
-
Native::Array.new(`#@native.styleSheets`) {|e|
|
|
118
|
-
CSS::StyleSheet.new(e)
|
|
119
|
-
}
|
|
120
|
-
end
|
|
121
|
-
|
|
122
178
|
# @!attribute title
|
|
123
179
|
# @return [String] the document title
|
|
124
180
|
def title
|
|
@@ -129,6 +185,18 @@ class Document < Element
|
|
|
129
185
|
`#@native.title = value`
|
|
130
186
|
end
|
|
131
187
|
|
|
188
|
+
# @!attribute [r] hidden?
|
|
189
|
+
# @return [Boolean] is the page considered hidden?
|
|
190
|
+
def hidden?
|
|
191
|
+
`#@native.hidden`
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# @!attribute [r] visibility
|
|
195
|
+
# @return [String] the visibility state of the document - prerender, hidden or visible
|
|
196
|
+
def visibility
|
|
197
|
+
`#@native.visibilityState`
|
|
198
|
+
end
|
|
199
|
+
|
|
132
200
|
if Browser.supports? 'Document.view'
|
|
133
201
|
def window
|
|
134
202
|
Window.new(`#@native.defaultView`)
|
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
module Browser; module DOM
|
|
2
2
|
|
|
3
|
+
# TODO: DocumentFragment is not a subclass of Element, but
|
|
4
|
+
# a subclass of Node. It implements a ParentNode.
|
|
5
|
+
#
|
|
6
|
+
# @see https://github.com/opal/opal-browser/pull/46
|
|
3
7
|
class DocumentFragment < Element
|
|
8
|
+
def self.new(node)
|
|
9
|
+
if self == DocumentFragment
|
|
10
|
+
if defined? `#{node}.mode`
|
|
11
|
+
ShadowRoot.new(node)
|
|
12
|
+
else
|
|
13
|
+
super
|
|
14
|
+
end
|
|
15
|
+
else
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
end
|
|
4
19
|
|
|
20
|
+
def self.create
|
|
21
|
+
$document.create_document_fragment
|
|
22
|
+
end
|
|
5
23
|
end
|
|
6
24
|
|
|
7
25
|
end; end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Browser; module DOM
|
|
2
|
+
|
|
3
|
+
# Document and ShadowRoot have some methods and properties in common.
|
|
4
|
+
# This solution mimics how it's done in DOM.
|
|
5
|
+
#
|
|
6
|
+
# @see https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot
|
|
7
|
+
module DocumentOrShadowRoot
|
|
8
|
+
# @!attribute [r] style_sheets
|
|
9
|
+
# @return [Array<CSS::StyleSheet>] the style sheets for the document
|
|
10
|
+
def style_sheets
|
|
11
|
+
Native::Array.new(`#@native.styleSheets`) {|e|
|
|
12
|
+
CSS::StyleSheet.new(e)
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
alias stylesheets style_sheets
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end; end
|