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
@@ -0,0 +1,232 @@
1
+ BROWSER_ENGINE = `/MSIE|WebKit|Presto|Gecko/.exec(navigator.userAgent)[0]`.downcase rescue :unknown
2
+
3
+ module Browser
4
+ # @private
5
+ @support = `{}`
6
+
7
+ def self.supports?(feature)
8
+ if defined?(`#@support[#{feature}]`)
9
+ return `#@support[#{feature}]`
10
+ end
11
+
12
+ support = case feature
13
+ when 'MutationObserver'
14
+ defined?(`window.MutationObserver`)
15
+
16
+ when 'WebSocket'
17
+ defined?(`window.WebSocket`)
18
+
19
+ when 'EventSource'
20
+ defined?(`window.EventSource`)
21
+
22
+ when 'XHR'
23
+ defined?(`window.XMLHttpRequest`)
24
+
25
+ when 'ActiveX'
26
+ defined?(`window.ActiveXObject`)
27
+
28
+ when 'Query.css'
29
+ defined?(`Element.prototype.querySelectorAll`)
30
+
31
+ when 'Query.xpath'
32
+ defined?(`document.evaluate`)
33
+
34
+ when 'Storage.local'
35
+ defined?(`window.localStorage`)
36
+
37
+ when 'Storage.global'
38
+ defined?(`window.globalStorage`)
39
+
40
+ when 'Storage.session'
41
+ defined?(`window.sessionStorage`)
42
+
43
+ when 'Immediate'
44
+ defined?(`window.setImmediate`)
45
+
46
+ when 'Immediate (Internet Explorer)'
47
+ defined?(`window.msSetImmediate`)
48
+
49
+ when 'Immediate (Firefox)'
50
+ defined?(`window.mozSetImmediate`)
51
+
52
+ when 'Immediate (Opera)'
53
+ defined?(`window.oSetImmediate`)
54
+
55
+ when 'Immediate (Chrome)', 'setImmediate (Safari)'
56
+ defined?(`window.webkitSetImmediate`)
57
+
58
+ when 'CSS.computed'
59
+ defined?(`window.getComputedStyle`)
60
+
61
+ when 'CSS.current'
62
+ defined?(`document.documentElement.currentStyle`)
63
+
64
+ when 'Window.send'
65
+ if defined?(`window.postMessage`) && !defined?(`window.importScripts`)
66
+ %x{
67
+ var ok = true,
68
+ old = window.onmessage;
69
+
70
+ window.onmessage = function() { ok = false; };
71
+ window.postMessage("", "*")
72
+ window.onmessage = old;
73
+ }
74
+
75
+ `ok`
76
+ end
77
+
78
+ when 'Window.innerSize'
79
+ defined?(`window.innerHeight`)
80
+
81
+ when 'Window.outerSize'
82
+ defined?(`window.outerHeight`)
83
+
84
+ when 'Window.scroll'
85
+ defined?(`document.documentElement.scrollLeft`)
86
+
87
+ when 'Window.pageOffset'
88
+ defined?(`window.pageXOffset`)
89
+
90
+ when 'Element.addBehavior'
91
+ defined?(`document.body.addBehavior`)
92
+
93
+ when 'Element.clientSize'
94
+ defined?(`document.documentElement.clientHeight`)
95
+
96
+ when 'Element.scroll'
97
+ defined?(`document.documentElement.scrollLeft`)
98
+
99
+ when 'Element.textContent'
100
+ defined?(`document.documentElement.textContent`)
101
+
102
+ when 'Element.innerText'
103
+ defined?(`document.documentElement.innerText`)
104
+
105
+ when 'Element.matches'
106
+ defined?(`document.documentElement.matches`)
107
+
108
+ when 'Element.matches (Internet Explorer)'
109
+ defined?(`document.documentElement.msMatchesSelector`)
110
+
111
+ when 'Element.matches (Firefox)'
112
+ defined?(`document.documentElement.mozMatchesSelector`)
113
+
114
+ when 'Element.matches (Opera)'
115
+ defined?(`document.documentElement.oMatchesSelector`)
116
+
117
+ when 'Element.matches (Chrome)', 'Element.matches (Safari)'
118
+ defined?(`document.documentElement.webkitMatchesSelector`)
119
+
120
+ when 'Element.getBoundingClientRect'
121
+ defined?(`document.documentElement.getBoundingClientRect`)
122
+
123
+ when 'Event.readystatechange'
124
+ `"onreadystatechange" in window.document.createElement("script")`
125
+
126
+ when 'Event.constructor'
127
+ begin
128
+ `new MouseEvent("click")`
129
+
130
+ true
131
+ rescue
132
+ false
133
+ end
134
+
135
+ when 'Event.create'
136
+ defined?(`document.createEvent`)
137
+
138
+ when 'Event.createObject'
139
+ defined?(`document.createEventObject`)
140
+
141
+ when 'Event.addListener'
142
+ defined?(`document.addEventListener`)
143
+
144
+ when 'Event.attach'
145
+ defined?(`document.attachEvent`)
146
+
147
+ when 'Event.removeListener'
148
+ defined?(`document.removeEventListener`)
149
+
150
+ when 'Event.detach'
151
+ defined?(`document.detachEvent`)
152
+
153
+ when 'Event.dispatch'
154
+ defined?(`document.dispatchEvent`)
155
+
156
+ when 'Event.fire'
157
+ defined?(`document.fireEvent`)
158
+
159
+ when /^Event\.([A-Z].*?)$/
160
+ `(#{$1} + "Event") in window`
161
+
162
+ when 'Document.view'
163
+ defined?(`document.defaultView`)
164
+
165
+ when 'Document.window'
166
+ defined?(`document.parentWindow`)
167
+
168
+ when 'History'
169
+ defined?(`window.history.pushState`)
170
+
171
+ when 'History.state'
172
+ defined?(`window.history.state`)
173
+
174
+ when 'Animation.request'
175
+ defined?(`window.requestAnimationFrame`)
176
+
177
+ when 'Animation.request (Internet Explorer)'
178
+ defined?(`window.msRequestAnimationFrame`)
179
+
180
+ when 'Animation.request (Firefox)'
181
+ defined?(`window.mozRequestAnimationFrame`)
182
+
183
+ when 'Animation.request (Opera)'
184
+ defined?(`window.oRequestAnimationFrame`)
185
+
186
+ when 'Animation.request (Chrome)', 'Animation.request (Safari)'
187
+ defined?(`window.webkitRequestAnimationFrame`)
188
+
189
+ when 'Animation.cancel'
190
+ defined?(`window.cancelAnimationFrame`)
191
+
192
+ when 'Animation.cancel (Internet Explorer)'
193
+ defined?(`window.msCancelAnimationFrame`)
194
+
195
+ when 'Animation.cancel (Firefox)'
196
+ defined?(`window.mozCancelAnimationFrame`)
197
+
198
+ when 'Animation.cancel (Opera)'
199
+ defined?(`window.oCancelAnimationFrame`)
200
+
201
+ when 'Animation.cancel (Chrome)', 'Animation.cancel (Safari)'
202
+ defined?(`window.webkitCancelAnimationFrame`)
203
+
204
+ when 'Animation.cancelRequest'
205
+ defined?(`window.cancelRequestAnimationFrame`)
206
+
207
+ when 'Animation.cancelRequest (Internet Explorer)'
208
+ defined?(`window.msCancelRequestAnimationFrame`)
209
+
210
+ when 'Animation.cancelRequest (Firefox)'
211
+ defined?(`window.mozCancelRequestAnimationFrame`)
212
+
213
+ when 'Animation.cancelRequest (Opera)'
214
+ defined?(`window.oCancelRequestAnimationFrame`)
215
+
216
+ when 'Animation.cancelRequest (Chrome)', 'Animation.cancelRequest (Safari)'
217
+ defined?(`window.webkitCancelRequestAnimationFrame`)
218
+ end
219
+
220
+ `#@support[#{feature}] = #{support}`
221
+ end
222
+
223
+ def self.loaded?(name)
224
+ case name
225
+ when 'Sizzle'
226
+ defined?(`window.Sizzle`)
227
+
228
+ when 'wicked-good-xpath'
229
+ defined?(`window.wgxpath`)
230
+ end
231
+ end
232
+ end
@@ -3,6 +3,22 @@ module Browser
3
3
  Position = Struct.new(:x, :y)
4
4
  end
5
5
 
6
+ class Object
7
+ # Encode as URI.
8
+ #
9
+ # @return [String] the {Object#to_s} encoded for usage as URI
10
+ def encode_uri
11
+ to_s.encode_uri
12
+ end
13
+
14
+ # Encode as URI component.
15
+ #
16
+ # @return [String] the {Object#to_s} encoded for usage as URI component
17
+ def encode_uri_component
18
+ to_s.encode_uri_component
19
+ end
20
+ end
21
+
6
22
  class String
7
23
  # Encode as URI component.
8
24
  #
@@ -34,6 +50,11 @@ class String
34
50
  end
35
51
 
36
52
  class Hash
53
+ # Decode an URL encoded form to a {Hash}.
54
+ #
55
+ # @param string [String] the URL encoded form
56
+ #
57
+ # @return [Hash]
37
58
  def self.decode_uri(string)
38
59
  self[string.split(?&).map {|part|
39
60
  name, value = part.split(?=)
@@ -42,15 +63,12 @@ class Hash
42
63
  }]
43
64
  end
44
65
 
66
+ # Encode the Hash to an URL form.
67
+ #
68
+ # @return [String] the URL encoded form
45
69
  def encode_uri
46
70
  map {|name, value|
47
71
  "#{name.to_s.encode_uri_component}=#{value.to_s.encode_uri_component}"
48
72
  }.join(?&)
49
73
  end
50
74
  end
51
-
52
- class Object
53
- def encode_uri
54
- to_s.encode_uri
55
- end
56
- end
@@ -1,3 +1,3 @@
1
1
  module Browser
2
- VERSION = '0.1.0.beta1'
2
+ VERSION = '0.2.0.beta1'
3
3
  end
@@ -1,10 +1,9 @@
1
1
  require 'browser/interval'
2
- require 'browser/timeout'
2
+ require 'browser/delay'
3
3
 
4
4
  require 'browser/window/view'
5
5
  require 'browser/window/size'
6
6
  require 'browser/window/scroll'
7
- require 'browser/window/compatibility'
8
7
 
9
8
  module Browser
10
9
 
@@ -6,17 +6,27 @@ class Scroll
6
6
  @native = window.to_n
7
7
  end
8
8
 
9
- def position
10
- %x{
11
- var doc = #@native.document,
12
- root = doc.documentElement,
13
- body = doc.body;
14
-
15
- var x = root.scrollLeft || body.scrollLeft,
16
- y = root.scrollTop || body.scrollTop;
17
- }
18
-
19
- Position.new(`x`, `y`)
9
+ if Browser.supports? 'Window.scroll'
10
+ def position
11
+ %x{
12
+ var doc = #@native.document,
13
+ root = doc.documentElement,
14
+ body = doc.body;
15
+
16
+ var x = root.scrollLeft || body.scrollLeft,
17
+ y = root.scrollTop || body.scrollTop;
18
+ }
19
+
20
+ Position.new(`x`, `y`)
21
+ end
22
+ elsif Browser.supports? 'Window.pageOffset'
23
+ def position
24
+ Position.new(`#@native.pageXOffset`, `#@native.pageYOffset`)
25
+ end
26
+ else
27
+ def position
28
+ raise NotImplementedError, 'window scroll unsupported'
29
+ end
20
30
  end
21
31
 
22
32
  def x
@@ -15,18 +15,28 @@ class Size
15
15
  self
16
16
  end
17
17
 
18
- def width
19
- `#@native.outerWidth`
18
+ if Browser.supports? 'Window.outerSize'
19
+ def width
20
+ `#@native.outerWidth`
21
+ end
22
+
23
+ def height
24
+ `#@native.outerHeight`
25
+ end
26
+ else
27
+ def width
28
+ raise NotImplementedError, 'window outer size not supported'
29
+ end
30
+
31
+ def height
32
+ raise NotImplementedError, 'window outer size not supported'
33
+ end
20
34
  end
21
35
 
22
36
  def width=(value)
23
37
  set(width: value)
24
38
  end
25
39
 
26
- def height
27
- `#@native.outerHeight`
28
- end
29
-
30
40
  def height=(value)
31
41
  set(height: value)
32
42
  end
@@ -6,12 +6,30 @@ class View
6
6
  @native = window.to_n
7
7
  end
8
8
 
9
- def width
10
- `#@native.innerWidth`
11
- end
9
+ if Browser.supports? 'Window.innerSize'
10
+ def width
11
+ `#@native.innerWidth`
12
+ end
13
+
14
+ def height
15
+ `#@native.innerHeight`
16
+ end
17
+ elsif Browser.supports? 'Element.clientSize'
18
+ def height
19
+ `#@native.document.documentElement.clientHeight`
20
+ end
21
+
22
+ def width
23
+ `#@native.document.documentElement.clientWidth`
24
+ end
25
+ else
26
+ def width
27
+ raise NotImplementedError, 'window size unsupported'
28
+ end
12
29
 
13
- def height
14
- `#@native.innerHeight`
30
+ def height
31
+ raise NotImplementedError, 'window size unsupported'
32
+ end
15
33
  end
16
34
  end
17
35
 
@@ -2,27 +2,27 @@ require 'spec_helper'
2
2
 
3
3
  describe Browser::DOM::Builder do
4
4
  it 'builds an element' do
5
- DOM {
5
+ expect(DOM {
6
6
  div
7
- }.name.should == 'DIV'
7
+ }.name).to eq('DIV')
8
8
  end
9
9
 
10
10
  it 'builds an element with text content' do
11
- DOM {
11
+ expect(DOM {
12
12
  div "foo bar"
13
- }.text.should == "foo bar"
13
+ }.text).to eq('foo bar')
14
14
 
15
- DOM {
15
+ expect(DOM {
16
16
  div {
17
17
  "foo bar"
18
18
  }
19
- }.text.should == "foo bar"
19
+ }.text).to eq('foo bar')
20
20
  end
21
21
 
22
22
  it 'builds an element with attributes' do
23
- DOM {
23
+ expect(DOM {
24
24
  div class: :wut
25
- }.class_name.should == :wut
25
+ }.class_name).to eq(:wut)
26
26
  end
27
27
 
28
28
  it 'builds deeper trees' do
@@ -34,15 +34,15 @@ describe Browser::DOM::Builder do
34
34
  }
35
35
  }
36
36
 
37
- res.name.should == 'DIV'
38
- res.child.name.should == 'SPAN'
39
- res.child.text.should == 'wut'
37
+ expect(res.name).to eq('DIV')
38
+ expect(res.child.name).to eq('SPAN')
39
+ expect(res.child.text).to eq('wut')
40
40
  end
41
41
 
42
42
  it 'sets classes with methods' do
43
- DOM {
43
+ expect(DOM {
44
44
  div.nice.element
45
- }.class_names.should == %w[nice element]
45
+ }.class_names).to eq(%w[nice element])
46
46
  end
47
47
 
48
48
  it 'nests when setting classes' do
@@ -52,10 +52,10 @@ describe Browser::DOM::Builder do
52
52
  }
53
53
  }
54
54
 
55
- res.name.should == 'DIV'
56
- res.class_names.should == %w[nice element]
57
- res.child.name.should == 'SPAN'
58
- res.child.class_names.should == %w[nicer]
55
+ expect(res.name).to eq('DIV')
56
+ expect(res.class_names).to eq(%w[nice element])
57
+ expect(res.child.name).to eq('SPAN')
58
+ expect(res.child.class_names).to eq(%w[nicer])
59
59
  end
60
60
 
61
61
  it 'joins class name properly' do
@@ -63,7 +63,7 @@ describe Browser::DOM::Builder do
63
63
  i.icon[:legal]
64
64
  }
65
65
 
66
- res.name.should == 'I'
67
- res.class_names.should == %w[icon-legal]
66
+ expect(res.name).to eq('I')
67
+ expect(res.class_names).to eq(%w[icon-legal])
68
68
  end
69
69
  end