opal-browser 0.1.0.beta1 → 0.2.0.beta1

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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +60 -0
  3. data/.yardopts +1 -1
  4. data/Gemfile +7 -2
  5. data/LICENSE +19 -0
  6. data/README.md +74 -10
  7. data/config.ru +2 -1
  8. data/index.html.erb +22 -0
  9. data/opal-browser.gemspec +9 -11
  10. data/opal/browser.rb +1 -1
  11. data/opal/browser/animation_frame.rb +66 -9
  12. data/opal/browser/canvas.rb +72 -18
  13. data/opal/browser/canvas/data.rb +1 -1
  14. data/opal/browser/console.rb +3 -37
  15. data/opal/browser/cookies.rb +80 -24
  16. data/opal/browser/css/declaration.rb +0 -5
  17. data/opal/browser/{timeout.rb → delay.rb} +13 -13
  18. data/opal/browser/dom.rb +0 -2
  19. data/opal/browser/dom/attribute.rb +6 -0
  20. data/opal/browser/dom/builder.rb +4 -8
  21. data/opal/browser/dom/character_data.rb +43 -7
  22. data/opal/browser/dom/document.rb +13 -11
  23. data/opal/browser/dom/element.rb +127 -29
  24. data/opal/browser/dom/element/image.rb +23 -0
  25. data/opal/browser/dom/element/offset.rb +27 -10
  26. data/opal/browser/dom/element/scroll.rb +32 -12
  27. data/opal/browser/dom/element/size.rb +29 -0
  28. data/opal/browser/dom/event.rb +88 -75
  29. data/opal/browser/dom/event/animation.rb +16 -4
  30. data/opal/browser/dom/event/audio_processing.rb +6 -4
  31. data/opal/browser/dom/event/base.rb +229 -64
  32. data/opal/browser/dom/event/before_unload.rb +6 -4
  33. data/opal/browser/dom/event/clipboard.rb +6 -4
  34. data/opal/browser/dom/event/close.rb +16 -4
  35. data/opal/browser/dom/event/composition.rb +16 -4
  36. data/opal/browser/dom/event/custom.rb +43 -8
  37. data/opal/browser/dom/event/device_light.rb +6 -4
  38. data/opal/browser/dom/event/device_motion.rb +17 -4
  39. data/opal/browser/dom/event/device_orientation.rb +16 -4
  40. data/opal/browser/dom/event/device_proximity.rb +6 -4
  41. data/opal/browser/dom/event/drag.rb +34 -28
  42. data/opal/browser/dom/event/focus.rb +21 -5
  43. data/opal/browser/dom/event/gamepad.rb +33 -20
  44. data/opal/browser/dom/event/hash_change.rb +6 -4
  45. data/opal/browser/dom/event/keyboard.rb +45 -23
  46. data/opal/browser/dom/event/message.rb +28 -8
  47. data/opal/browser/dom/event/mouse.rb +26 -25
  48. data/opal/browser/dom/event/page_transition.rb +6 -4
  49. data/opal/browser/dom/event/pop_state.rb +16 -4
  50. data/opal/browser/dom/event/progress.rb +16 -4
  51. data/opal/browser/dom/event/sensor.rb +6 -4
  52. data/opal/browser/dom/event/storage.rb +6 -4
  53. data/opal/browser/dom/event/touch.rb +10 -19
  54. data/opal/browser/dom/event/ui.rb +19 -3
  55. data/opal/browser/dom/event/wheel.rb +2 -2
  56. data/opal/browser/dom/mutation_observer.rb +65 -5
  57. data/opal/browser/dom/node.rb +164 -59
  58. data/opal/browser/dom/node_set.rb +4 -0
  59. data/opal/browser/dom/text.rb +16 -1
  60. data/opal/browser/event_source.rb +5 -2
  61. data/opal/browser/history.rb +51 -15
  62. data/opal/browser/http.rb +22 -7
  63. data/opal/browser/http/headers.rb +5 -0
  64. data/opal/browser/http/request.rb +40 -10
  65. data/opal/browser/immediate.rb +123 -9
  66. data/opal/browser/interval.rb +8 -13
  67. data/opal/browser/location.rb +13 -3
  68. data/opal/browser/navigator.rb +9 -6
  69. data/opal/browser/screen.rb +31 -5
  70. data/opal/browser/socket.rb +8 -4
  71. data/opal/browser/storage.rb +118 -33
  72. data/opal/browser/support.rb +232 -0
  73. data/opal/browser/utils.rb +24 -6
  74. data/opal/browser/version.rb +1 -1
  75. data/opal/browser/window.rb +1 -2
  76. data/opal/browser/window/scroll.rb +21 -11
  77. data/opal/browser/window/size.rb +16 -6
  78. data/opal/browser/window/view.rb +23 -5
  79. data/spec/dom/builder_spec.rb +19 -19
  80. data/spec/dom/document_spec.rb +6 -6
  81. data/spec/dom/element_spec.rb +5 -5
  82. data/spec/dom/event_spec.rb +20 -20
  83. data/spec/dom/mutation_observer_spec.rb +5 -5
  84. data/spec/dom/node_spec.rb +39 -27
  85. data/spec/dom_spec.rb +10 -8
  86. data/spec/event_source_spec.rb +12 -12
  87. data/spec/history_spec.rb +24 -15
  88. data/spec/http_spec.rb +18 -17
  89. data/spec/immediate_spec.rb +9 -7
  90. data/spec/runner.rb +114 -0
  91. data/spec/socket_spec.rb +8 -8
  92. data/spec/spec_helper.rb +1 -0
  93. data/spec/storage_spec.rb +6 -6
  94. data/spec/wgxpath.install.js +49 -0
  95. data/spec/window_spec.rb +2 -2
  96. metadata +21 -54
  97. data/opal/browser/compatibility.rb +0 -59
  98. data/opal/browser/compatibility/animation_frame.rb +0 -93
  99. data/opal/browser/compatibility/dom/document/window.rb +0 -15
  100. data/opal/browser/compatibility/dom/element/css.rb +0 -15
  101. data/opal/browser/compatibility/dom/element/matches.rb +0 -31
  102. data/opal/browser/compatibility/dom/element/offset.rb +0 -20
  103. data/opal/browser/compatibility/dom/element/scroll.rb +0 -25
  104. data/opal/browser/compatibility/dom/element/style.rb +0 -15
  105. data/opal/browser/compatibility/dom/mutation_observer.rb +0 -47
  106. data/opal/browser/compatibility/http/request.rb +0 -15
  107. data/opal/browser/compatibility/immediate.rb +0 -107
  108. data/opal/browser/compatibility/window/scroll.rb +0 -27
  109. data/opal/browser/compatibility/window/size.rb +0 -13
  110. data/opal/browser/compatibility/window/view.rb +0 -13
  111. data/opal/browser/dom/compatibility.rb +0 -8
  112. data/opal/browser/http/compatibility.rb +0 -1
  113. data/opal/browser/window/compatibility.rb +0 -3
@@ -1,15 +1,18 @@
1
1
  module Browser
2
2
 
3
- # This class wraps `setInterval`.
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 [Number] the seconds every which the block is called
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 [Number] seconds every which to call the block
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
@@ -32,20 +35,14 @@ class Interval
32
35
  end
33
36
 
34
37
  # Abort the interval, it won't be possible to start it again.
35
- #
36
- # @return [self]
37
38
  def abort
38
39
  `#@window.clearInterval(#@id)`
39
40
 
40
41
  @aborted = true
41
42
  @id = nil
42
-
43
- self
44
43
  end
45
44
 
46
45
  # Stop the interval, it will be possible to start it again.
47
- #
48
- # @return [self]
49
46
  def stop
50
47
  `#@window.clearInterval(#@id)`
51
48
 
@@ -54,16 +51,12 @@ class Interval
54
51
  end
55
52
 
56
53
  # Start the interval if it has been stopped.
57
- #
58
- # @return [self]
59
54
  def start
60
55
  raise "the interval has been aborted" if aborted?
61
56
 
62
57
  return unless stopped?
63
58
 
64
59
  @id = `#@window.setInterval(#{@block.to_n}, #@every * 1000)`
65
-
66
- self
67
60
  end
68
61
  end
69
62
 
@@ -71,6 +64,7 @@ class Window
71
64
  # Execute the block every given seconds.
72
65
  #
73
66
  # @param time [Float] the seconds between every call
67
+ #
74
68
  # @return [Interval] the object representing the interval
75
69
  def every(time, &block)
76
70
  Interval.new(@native, time, &block)
@@ -80,6 +74,7 @@ end
80
74
  end
81
75
 
82
76
  class Proc
77
+ # (see Browser::Window#every)
83
78
  def every(time)
84
79
  $window.every(time, &self)
85
80
  end
@@ -1,5 +1,8 @@
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
7
  include Native
5
8
 
@@ -66,9 +69,16 @@ class Location
66
69
  end
67
70
 
68
71
  class Window
69
- # Get the {Location} object for this window.
70
- #
71
- # @return [Location]
72
+ # @!attribute [r] location
73
+ # @return [Location] the location for the window
74
+ def location
75
+ Location.new(`#@native.location`) if `#@native.location`
76
+ end
77
+ end
78
+
79
+ class DOM::Document < DOM::Element
80
+ # @!attribute [r] location
81
+ # @return [Location] the location for the document
72
82
  def location
73
83
  Location.new(`#@native.location`) if `#@native.location`
74
84
  end
@@ -1,6 +1,8 @@
1
1
  module Browser
2
2
 
3
- # Class that represents the browser attributes.
3
+ # Representation of the navigator application.
4
+ #
5
+ # @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator
4
6
  class Navigator
5
7
  include Native
6
8
 
@@ -8,7 +10,7 @@ class Navigator
8
10
  Product = Struct.new(:name, :version)
9
11
  Vendor = Struct.new(:name, :version)
10
12
 
11
- # Class that represents a MIME type.
13
+ # Representation of a MIME type.
12
14
  class MimeType
13
15
  include Native
14
16
 
@@ -33,7 +35,9 @@ class Navigator
33
35
  alias_native :type
34
36
  end
35
37
 
36
- # Class to represent a browser plugin.
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|
@@ -140,9 +144,8 @@ class Navigator
140
144
  end
141
145
 
142
146
  class Window
143
- # Get the {Navigator} object for this window.
144
- #
145
- # @return [Navigator]
147
+ # @!attribute [r] navigator
148
+ # @return [Navigator] the navigator
146
149
  def navigator
147
150
  Navigator.new(`#@native.navigator`) if `#@native.navigator`
148
151
  end
@@ -1,5 +1,8 @@
1
1
  module Browser
2
2
 
3
+ # Representation of the screen the window is being rendered on.
4
+ #
5
+ # @see https://developer.mozilla.org/en-US/docs/Web/API/Window.screen
3
6
  class Screen
4
7
  include Native
5
8
  include DOM::Event::Target
@@ -8,30 +11,53 @@ class Screen
8
11
  Screen.new(value) if Native.is_a?(value, `window.Screen`)
9
12
  }
10
13
 
14
+ Depth = Struct.new(:color, :pixel)
15
+
16
+ # @!attribute [r] width
17
+ # @return [Integer] the width of the screen in pixels
11
18
  alias_native :width
19
+
20
+ # @!attribute [r] height
21
+ # @return [Integer] the height of the screen in pixels
12
22
  alias_native :height
13
23
 
24
+ # @!attribute [r] size
25
+ # @return [Size] the size in pixels
14
26
  def size
15
27
  Size.new(width, height)
16
28
  end
17
29
 
30
+ # @!attribute [r] x
31
+ # @return [Integer] the offset from the top left corner of the screen in
32
+ # pixels
18
33
  alias_native :x, :top
34
+
35
+ # @!attribute [r] y
36
+ # @return [Integer] the offset from the top left corner of the screen in
37
+ # pixels
19
38
  alias_native :y, :left
20
39
 
40
+ # @!attribute [r] position
41
+ # @return [Position] the offset from the top left corner of the screen in
42
+ # pixels
21
43
  def position
22
44
  Position.new(x, y)
23
45
  end
24
46
 
25
- alias_native :color_depth, :colorDepth
26
- alias_native :pixel_depth, :pixelDepth
47
+ # @!attribute [r] depth
48
+ # @return [Depth] the screen depth
49
+ def depth
50
+ Depth.new(`#@native.colorDepth`, `#@native.pixelDepth`)
51
+ end
27
52
 
53
+ # @!attribute [r] orientation
54
+ # @return [String] the orientation of the screen
28
55
  alias_native :orientation
29
56
  end
30
57
 
31
58
  class Window
32
- # Get the {Screen} for this window.
33
- #
34
- # @return [Screen]
59
+ # @!attribute [r] screen
60
+ # @return [Screen] the screen for the window
35
61
  def screen
36
62
  Screen.new(`#@native.screen`)
37
63
  end
@@ -1,9 +1,12 @@
1
1
  module Browser
2
2
 
3
- # This class wraps `WebSocket`.
3
+ # A {Socket} allows the browser and a server to have a bidirectional data
4
+ # connection.
5
+ #
6
+ # @see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
4
7
  class Socket
5
8
  def self.supported?
6
- defined? `window.WebSocket`
9
+ Browser.supports? :WebSocket
7
10
  end
8
11
 
9
12
  include Native
@@ -18,8 +21,9 @@ class Socket
18
21
  #
19
22
  # @param url [String] the URL to connect to
20
23
  # @param protocol [String] the protocol to use
21
- # @yield if the block has no parameters it's instance_exec'd, otherwise it's
22
- # called with self
24
+ #
25
+ # @yield if the block has no parameters it's `instance_exec`d, otherwise it's
26
+ # called with `self`
23
27
  def initialize(url, protocol = nil, &block)
24
28
  if native?(url)
25
29
  super(url)
@@ -1,19 +1,24 @@
1
- #--
2
- # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
- # Version 2, December 2004
4
- #
5
- # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
- # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
- #
8
- # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
- #++
10
-
11
1
  require 'json'
12
2
  require 'stringio'
13
3
 
14
4
  module Browser
15
5
 
16
- class Storage < Hash
6
+ # A {Storage} allows you to store data across page loads and browser
7
+ # restarts.
8
+ #
9
+ # Compatibility
10
+ # -------------
11
+ # The compatibility layer will try various implementations in the following
12
+ # order.
13
+ #
14
+ # + [window.localStorage](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#localStorage)
15
+ # + [window.globalStorage](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#globalStorage)
16
+ # + [document.body.addBehavior](http://msdn.microsoft.com/en-us/library/ms531424(VS.85).aspx)
17
+ # + [document.cookie](https://developer.mozilla.org/en-US/docs/Web/API/document.cookie)
18
+ #
19
+ # @see https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage
20
+ # @todo remove method_defined? checks when require order is fixed
21
+ class Storage
17
22
  def self.json_create(data)
18
23
  data.delete(JSON.create_id)
19
24
 
@@ -22,47 +27,106 @@ class Storage < Hash
22
27
  }]
23
28
  end
24
29
 
30
+ include Enumerable
31
+
32
+ # @!attribute [r] name
33
+ # @return [String] the name of the storage
25
34
  attr_reader :name
26
35
 
36
+ # Create a new storage on the given window with the given name.
37
+ #
38
+ # @param window [native] the window to save the storage to
39
+ # @param name [String] the name to use to discern different storages
27
40
  def initialize(window, name)
28
41
  super()
29
42
 
30
43
  @window = window
31
44
  @name = name
45
+ @data = {}
32
46
 
33
47
  autosave!
34
-
35
- init if respond_to? :init
48
+ init
36
49
  end
37
50
 
51
+ # @!attribute [r] encoded_name
52
+ # @return [String] the generated name
38
53
  def encoded_name
39
- "$opal.storage.#{@name}"
54
+ "$opal.storage.#@name"
40
55
  end
41
56
 
42
- def autosave?; @autosave; end
43
- def autosave!; @autosave = true; end
44
- def no_autosave!; @autosave = false; end
57
+ # Check if autosaving is enabled.
58
+ #
59
+ # When autosaving is enabled the {Storage} is saved every time a change is
60
+ # made, otherwise you'll have to save it manually yourself.
61
+ def autosave?
62
+ @autosave
63
+ end
64
+
65
+ # Enable autosaving.
66
+ def autosave!
67
+ @autosave = true
68
+ end
69
+
70
+ # Disable autosaving.
71
+ def no_autosave!
72
+ @autosave = false
73
+ end
74
+
75
+ # Iterate over the (key, value) pairs in the storage.
76
+ #
77
+ # @yield [key, value]
78
+ def each(&block)
79
+ return enum_for :each unless block
80
+
81
+ @data.each(&block)
82
+
83
+ self
84
+ end
45
85
 
46
- def replace(what)
47
- if what.is_a?(String)
48
- super JSON.parse(what)
86
+ # Get a value in the storage.
87
+ def [](key)
88
+ @data[key]
89
+ end
90
+
91
+ # Set a value in the storage.
92
+ def []=(key, value)
93
+ @data[key] = value
94
+
95
+ save if autosave?
96
+ end
97
+
98
+ # Delete a value from the storage.
99
+ def delete(key)
100
+ @data.delete(key).tap {
101
+ save if autosave
102
+ }
103
+ end
104
+
105
+ # Clear the storage.
106
+ def clear
107
+ @data.clear.tap {
108
+ save if autosave?
109
+ }
110
+ end
111
+
112
+ # Replace the current storage with the given one.
113
+ #
114
+ # @param new [Hash, String] if new is a {String} it will be parsed as JSON
115
+ def replace(new)
116
+ if String === new
117
+ @data.replace(JSON.parse(new))
49
118
  else
50
- super
119
+ @data.replace(new)
51
120
  end
52
121
  end
53
122
 
54
- %w([]= delete clear).each {|name|
55
- define_method name do |*args|
56
- # FIXME: remove the application when it's fixed
57
- super(*args).tap {
58
- save if autosave?
59
- }
60
- end
61
- }
123
+ # @!method init
124
+ # @private
62
125
 
63
- def save; end
126
+ # @!method save
127
+ # Persist the current state to the storage.
64
128
 
65
- if `window.localStorage`
129
+ if Browser.supports? 'Storage.local'
66
130
  def init
67
131
  replace `#@window.localStorage[#{encoded_name}] || '{}'`
68
132
  end
@@ -70,7 +134,7 @@ class Storage < Hash
70
134
  def save
71
135
  `#@window.localStorage[#{encoded_name}] = #{JSON.dump(self)}`
72
136
  end
73
- elsif `window.globalStorage`
137
+ elsif Browser.supports? 'Storage.global'
74
138
  def init
75
139
  replace `#@window.globalStorage[#@window.location.hostname][#{encoded_name}] || '{}'`
76
140
  end
@@ -78,7 +142,7 @@ class Storage < Hash
78
142
  def save
79
143
  `#@window.globalStorage[#@window.location.hostname][#{encoded_name}] = #{JSON.dump(self)}`
80
144
  end
81
- elsif `document.body.addBehavior`
145
+ elsif Browser.supports? 'Element.addBehavior'
82
146
  def init
83
147
  %x{
84
148
  #@element = #@window.document.createElement('link');
@@ -110,6 +174,9 @@ class Storage < Hash
110
174
  end
111
175
  end
112
176
 
177
+ # Convert the storage to JSON.
178
+ #
179
+ # @return [String] the JSON representation
113
180
  def to_json
114
181
  io = StringIO.new("{")
115
182
 
@@ -126,7 +193,15 @@ class Storage < Hash
126
193
  end
127
194
  end
128
195
 
196
+ # A {SessionStorage} allows you to store data across page reloads, as long as the session
197
+ # is active.
198
+ #
199
+ # @see https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage#sessionStorage
129
200
  class SessionStorage < Storage
201
+ def self.supported?
202
+ Browser.supports? 'Storage.session'
203
+ end
204
+
130
205
  def init
131
206
  replace `#@window.sessionStorage[#{encoded_name}] || '{}'`
132
207
  end
@@ -137,10 +212,20 @@ class SessionStorage < Storage
137
212
  end
138
213
 
139
214
  class Window
215
+ # Get a storage with the given name.
216
+ #
217
+ # @param name [Symbol] the name of the storage
218
+ #
219
+ # @return [Storage]
140
220
  def storage(name = :default)
141
221
  Storage.new(to_n, name)
142
222
  end
143
223
 
224
+ # Get a session storage with the given name.
225
+ #
226
+ # @param name [Symbol] the name of the storage
227
+ #
228
+ # @return [SessionStorage]
144
229
  def session_storage(name = :default)
145
230
  SessionStorage.new(to_n, name)
146
231
  end