opal-browser 0.1.0.beta1 → 0.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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