opal-browser 0.2.0.beta1 → 0.2.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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +22 -8
  3. data/Gemfile +1 -1
  4. data/README.md +59 -5
  5. data/index.html.erb +7 -4
  6. data/lib/opal-browser.rb +1 -0
  7. data/opal-browser.gemspec +1 -1
  8. data/opal/browser.rb +1 -0
  9. data/opal/browser/animation_frame.rb +26 -1
  10. data/opal/browser/canvas.rb +0 -10
  11. data/opal/browser/canvas/data.rb +0 -10
  12. data/opal/browser/canvas/gradient.rb +0 -10
  13. data/opal/browser/canvas/style.rb +0 -10
  14. data/opal/browser/canvas/text.rb +0 -10
  15. data/opal/browser/cookies.rb +6 -8
  16. data/opal/browser/database/sql.rb +194 -0
  17. data/opal/browser/delay.rb +25 -7
  18. data/opal/browser/dom.rb +2 -11
  19. data/opal/browser/dom/attribute.rb +12 -11
  20. data/opal/browser/dom/builder.rb +4 -9
  21. data/opal/browser/dom/document.rb +105 -41
  22. data/opal/browser/dom/element.rb +317 -231
  23. data/opal/browser/dom/element/attributes.rb +87 -0
  24. data/opal/browser/dom/element/data.rb +67 -0
  25. data/opal/browser/dom/element/input.rb +12 -1
  26. data/opal/browser/dom/element/offset.rb +5 -0
  27. data/opal/browser/dom/element/position.rb +11 -2
  28. data/opal/browser/dom/element/scroll.rb +77 -10
  29. data/opal/browser/dom/element/select.rb +36 -0
  30. data/opal/browser/dom/element/size.rb +5 -0
  31. data/opal/browser/dom/element/template.rb +9 -0
  32. data/opal/browser/dom/element/textarea.rb +24 -0
  33. data/opal/browser/dom/mutation_observer.rb +2 -2
  34. data/opal/browser/dom/node.rb +93 -51
  35. data/opal/browser/dom/node_set.rb +66 -48
  36. data/opal/browser/effects.rb +11 -0
  37. data/opal/browser/{dom/event.rb → event.rb} +32 -32
  38. data/opal/browser/{dom/event → event}/animation.rb +2 -2
  39. data/opal/browser/{dom/event → event}/audio_processing.rb +2 -2
  40. data/opal/browser/{dom/event → event}/base.rb +65 -7
  41. data/opal/browser/{dom/event → event}/before_unload.rb +2 -2
  42. data/opal/browser/{dom/event → event}/clipboard.rb +2 -2
  43. data/opal/browser/{dom/event → event}/close.rb +2 -2
  44. data/opal/browser/{dom/event → event}/composition.rb +2 -2
  45. data/opal/browser/{dom/event → event}/custom.rb +2 -2
  46. data/opal/browser/{dom/event → event}/device_light.rb +2 -2
  47. data/opal/browser/{dom/event → event}/device_motion.rb +2 -2
  48. data/opal/browser/{dom/event → event}/device_orientation.rb +2 -2
  49. data/opal/browser/{dom/event → event}/device_proximity.rb +2 -2
  50. data/opal/browser/{dom/event → event}/drag.rb +2 -2
  51. data/opal/browser/{dom/event → event}/focus.rb +2 -2
  52. data/opal/browser/{dom/event → event}/gamepad.rb +2 -2
  53. data/opal/browser/{dom/event → event}/hash_change.rb +2 -2
  54. data/opal/browser/{dom/event → event}/keyboard.rb +2 -2
  55. data/opal/browser/{dom/event → event}/message.rb +2 -2
  56. data/opal/browser/{dom/event → event}/mouse.rb +2 -2
  57. data/opal/browser/{dom/event → event}/page_transition.rb +2 -2
  58. data/opal/browser/{dom/event → event}/pop_state.rb +2 -2
  59. data/opal/browser/{dom/event → event}/progress.rb +2 -2
  60. data/opal/browser/{dom/event → event}/sensor.rb +2 -2
  61. data/opal/browser/{dom/event → event}/storage.rb +2 -2
  62. data/opal/browser/{dom/event → event}/touch.rb +2 -2
  63. data/opal/browser/{dom/event → event}/ui.rb +2 -2
  64. data/opal/browser/{dom/event → event}/wheel.rb +2 -2
  65. data/opal/browser/event_source.rb +1 -1
  66. data/opal/browser/http.rb +25 -0
  67. data/opal/browser/http/binary.rb +1 -0
  68. data/opal/browser/http/headers.rb +16 -2
  69. data/opal/browser/http/request.rb +14 -38
  70. data/opal/browser/immediate.rb +9 -3
  71. data/opal/browser/interval.rb +34 -11
  72. data/opal/browser/navigator.rb +23 -4
  73. data/opal/browser/screen.rb +1 -1
  74. data/opal/browser/socket.rb +5 -1
  75. data/opal/browser/storage.rb +51 -33
  76. data/opal/browser/support.rb +59 -4
  77. data/opal/browser/version.rb +1 -1
  78. data/opal/browser/window.rb +17 -9
  79. data/opal/browser/window/size.rb +17 -3
  80. data/opal/opal-browser.rb +1 -0
  81. data/spec/database/sql_spec.rb +131 -0
  82. data/spec/delay_spec.rb +38 -0
  83. data/spec/dom/attribute_spec.rb +49 -0
  84. data/spec/dom/builder_spec.rb +25 -8
  85. data/spec/dom/document_spec.rb +20 -0
  86. data/spec/dom/element/attributes_spec.rb +52 -0
  87. data/spec/dom/element_spec.rb +139 -4
  88. data/spec/dom/node_set_spec.rb +44 -0
  89. data/spec/interval_spec.rb +50 -0
  90. data/spec/runner.rb +46 -28
  91. data/spec/socket_spec.rb +1 -0
  92. data/spec/spec_helper.rb +0 -4
  93. data/spec/storage_spec.rb +1 -1
  94. metadata +57 -39
  95. data/opal/browser/http/parameters.rb +0 -8
@@ -0,0 +1,9 @@
1
+ module Browser; module DOM; class Element < Node
2
+
3
+ class Template < Element
4
+ def content
5
+ DOM(`#@native.content`)
6
+ end
7
+ end
8
+
9
+ end; end; end
@@ -0,0 +1,24 @@
1
+ module Browser; module DOM; class Element < Node
2
+
3
+ class Textarea < Element
4
+ def value
5
+ %x{
6
+ if (#@native.value == "") {
7
+ return nil;
8
+ }
9
+ else {
10
+ return #@native.value;
11
+ }
12
+ }
13
+ end
14
+
15
+ def value=(value)
16
+ `#@native.value = #{value}`
17
+ end
18
+
19
+ def clear
20
+ `#@native.value = ''`
21
+ end
22
+ end
23
+
24
+ end; end; end
@@ -49,7 +49,7 @@ class MutationObserver
49
49
  []
50
50
  end
51
51
 
52
- NodeSet.new($document, array)
52
+ NodeSet[array]
53
53
  end
54
54
 
55
55
  # @!attribute [r] removed
@@ -61,7 +61,7 @@ class MutationObserver
61
61
  []
62
62
  end
63
63
 
64
- NodeSet.new($document, array)
64
+ NodeSet[array]
65
65
  end
66
66
 
67
67
  # @!attribute [r] target
@@ -42,16 +42,7 @@ class Node
42
42
  #
43
43
  # @return [Boolean]
44
44
  def ==(other)
45
- `#@native === #{Native.try_convert(other)}`
46
- end
47
-
48
- # Return true if the node name matches the given name case-insensitively.
49
- #
50
- # @param name [String] the name to match with
51
- #
52
- # @return [Boolean]
53
- def =~(name)
54
- self.name.downcase == name.downcase
45
+ `#@native === #{Native.convert(other)}`
55
46
  end
56
47
 
57
48
  # Append a child to the node.
@@ -65,36 +56,74 @@ class Node
65
56
  #
66
57
  # @return [self]
67
58
  def <<(node)
68
- if native?(node)
59
+ if Opal.respond_to? node, :each
60
+ node.each { |n| self << n }
61
+ return self
62
+ end
63
+
64
+ unless native?(node)
65
+ if String === node
66
+ node = `#@native.ownerDocument.createTextNode(node)`
67
+ else
68
+ node = Native.convert(node)
69
+ end
70
+ end
71
+
72
+ `#@native.appendChild(node)`
73
+
74
+ self
75
+ end
76
+
77
+ def >>(node)
78
+ if Opal.respond_to? node, :each
79
+ node.each { |n| self >> n }
80
+ return self
81
+ end
82
+
83
+ unless native?(node)
84
+ if String === node
85
+ node = `#@native.ownerDocument.createTextNode(node)`
86
+ else
87
+ node = Native.convert(node)
88
+ end
89
+ end
90
+
91
+ if `#@native.firstChild == null`
69
92
  `#@native.appendChild(node)`
70
- elsif node.respond_to? :each
71
- node.each { |n| add_child(n) }
72
- elsif String === node
73
- `#@native.appendChild(#@native.ownerDocument.createTextNode(node))`
74
93
  else
75
- `#@native.appendChild(#{Native.convert(node)})`
94
+ `#@native.insertBefore(node, #@native.firstChild)`
76
95
  end
77
96
 
78
97
  self
79
98
  end
80
99
 
81
- alias add_child <<
100
+ def add_child(node = nil, &block)
101
+ unless node
102
+ node = DOM(&block)
103
+ end
104
+
105
+ self << node
106
+ end
82
107
 
83
108
  # Add the passed node after this one.
84
109
  #
85
110
  # When passing a {String} a text node will be created.
86
111
  #
87
112
  # @param node [String, Node, #to_n] the node to add
88
- def add_next_sibling(node)
89
- if native?(node)
90
- `#@native.parentNode.insertBefore(node, #@native.nextSibling)`
91
- elsif String === node
92
- `#@native.parentNode.insertBefore(
93
- #@native.ownerDocument.createTextNode(node), #@native.nextSibling)`
94
- else
95
- `#@native.parentNode.insertBefore(#{Native.convert(node)},
96
- #@native.nextSibling)`
113
+ def add_next_sibling(node = nil, &block)
114
+ unless node
115
+ node = DOM(&block)
116
+ end
117
+
118
+ unless native?(node)
119
+ if String === node
120
+ node = `#@native.ownerDocument.createTextNode(node)`
121
+ else
122
+ node = Native.convert(node)
123
+ end
97
124
  end
125
+
126
+ `#@native.parentNode.insertBefore(node, #@native.nextSibling)`
98
127
  end
99
128
 
100
129
  # Add the passed node before this one.
@@ -102,15 +131,20 @@ class Node
102
131
  # When passing a {String} a text node will be created.
103
132
  #
104
133
  # @param node [String, Node, #to_n] the node to add
105
- def add_previous_sibling(node)
106
- if native?(node)
107
- `#@native.parentNode.insertBefore(node, #@native)`
108
- elsif String === node
109
- `#@native.parentNode.insertBefore(
110
- #@native.ownerDocument.createTextNode(node), #@native)`
111
- else
112
- `#@native.parentNode.insertBefore(#{Native.convert(node)}, #@native)`
134
+ def add_previous_sibling(node = nil, &block)
135
+ unless node
136
+ node = DOM(&block)
137
+ end
138
+
139
+ unless native?(node)
140
+ if String === node
141
+ node = `#@native.ownerDocument.createTextNode(node)`
142
+ else
143
+ node = Native.convert(node)
144
+ end
113
145
  end
146
+
147
+ `#@native.parentNode.insertBefore(node, #@native)`
114
148
  end
115
149
 
116
150
  alias after add_next_sibling
@@ -119,7 +153,7 @@ class Node
119
153
  #
120
154
  # @param node [Node] the node to append to
121
155
  def append_to(node)
122
- node.add_child(self)
156
+ node << self
123
157
  end
124
158
 
125
159
  # Get an array of ancestors.
@@ -130,7 +164,7 @@ class Node
130
164
  #
131
165
  # @return [NodeSet]
132
166
  def ancestors(expression = nil)
133
- return NodeSet.new(document) unless parent
167
+ return NodeSet[] unless parent
134
168
 
135
169
  parents = [parent]
136
170
 
@@ -143,12 +177,10 @@ class Node
143
177
  end
144
178
 
145
179
  if expression
146
- parents.select! {|p|
147
- p.matches? expression
148
- }
180
+ parents.select! { |p| p =~ expression }
149
181
  end
150
182
 
151
- NodeSet.new document, parents
183
+ NodeSet.new(parents)
152
184
  end
153
185
 
154
186
  alias before add_previous_sibling
@@ -160,7 +192,7 @@ class Node
160
192
 
161
193
  # Remove all the children of the node.
162
194
  def clear
163
- children.each(&:remove)
195
+ children.remove
164
196
  end
165
197
 
166
198
  # @!attribute content
@@ -209,7 +241,7 @@ class Node
209
241
  # @!attribute children
210
242
  # @return [NodeSet] the children of the node
211
243
  def children
212
- NodeSet.new(document, Native::Array.new(`#@native.childNodes`))
244
+ NodeSet[Native::Array.new(`#@native.childNodes`)]
213
245
  end
214
246
 
215
247
  def children=(node)
@@ -277,13 +309,6 @@ class Node
277
309
  element_children.last
278
310
  end
279
311
 
280
- # Check if the node matches the given CSS selector.
281
- #
282
- # @param expression [String] the CSS selector
283
- def matches?(expression)
284
- false
285
- end
286
-
287
312
  # @!attribute name
288
313
  # @return [String] the name of the node
289
314
  def name
@@ -339,7 +364,7 @@ class Node
339
364
  end
340
365
 
341
366
  def parent=(node)
342
- `#@native.parentNode = #{Native.try_convert(node)}`
367
+ `#@native.parentNode = #{Native.convert(node)}`
343
368
  end
344
369
 
345
370
  def parse(text, options = {})
@@ -350,6 +375,13 @@ class Node
350
375
  raise NotImplementedError
351
376
  end
352
377
 
378
+ # Prepend the node to the passed one.
379
+ #
380
+ # @param node [Node] the node to prepend to
381
+ def prepend_to(node)
382
+ node >> self
383
+ end
384
+
353
385
  # @!attribute previous
354
386
  # @return [Node?] the previous sibling of the node
355
387
  def previous
@@ -384,11 +416,21 @@ class Node
384
416
  # @param node [Node] the node to replace with
385
417
  # @return [Node] the passed node
386
418
  def replace(node)
387
- `#@native.parentNode.replaceChild(#@native, #{Native.try_convert(node)})`
419
+ unless native?(node)
420
+ if String === node
421
+ node = `#@native.ownerDocument.createTextNode(node)`
422
+ else
423
+ node = Native.convert(node)
424
+ end
425
+ end
426
+
427
+ `#@native.parentNode.replaceChild(node, #@native)`
388
428
 
389
429
  node
390
430
  end
391
431
 
432
+ alias replace_with replace
433
+
392
434
  alias text content
393
435
  alias text= content=
394
436
 
@@ -1,25 +1,20 @@
1
1
  module Browser; module DOM
2
2
 
3
+ # Allows manipulation of a set of {Node}s.
3
4
  class NodeSet
4
- attr_reader :document
5
-
6
- def initialize(document, list = [])
7
- @document = document
8
- @literal = []
9
-
10
- list.each {|el|
11
- if NodeSet === el
12
- @literal.concat(el.to_a)
13
- else
14
- @literal.push DOM(Native.convert(el))
15
- end
16
- }
5
+ # Create a new {NodeSet} from the given nodes.
6
+ #
7
+ # Note that the nodes are flattened and converted with DOM automatically,
8
+ # this means you can pass {NodeSet}s and {Native::Array}s as well.
9
+ def self.[](*nodes)
10
+ new(nodes.flatten.map { |x| DOM(Native.convert(x)) }.uniq)
17
11
  end
18
12
 
19
- def respond_to_missing?(name)
20
- @literal.respond_to?(name)
13
+ def initialize(literal)
14
+ @literal = literal
21
15
  end
22
16
 
17
+ # Any other method will be called on every node in the set.
23
18
  def method_missing(name, *args, &block)
24
19
  unless @literal.respond_to? name
25
20
  each {|el|
@@ -34,58 +29,81 @@ class NodeSet
34
29
  if `result === #@literal`
35
30
  self
36
31
  elsif Array === result
37
- NodeSet.new(@document, result)
32
+ NodeSet.new(result)
38
33
  else
39
34
  result
40
35
  end
41
36
  end
42
37
 
43
- def dup
44
- NodeSet.new(document, to_ary.dup)
45
- end
46
-
47
- def filter(expression)
48
- NodeSet.new(document, @literal.select { |node| node.matches?(expression) })
49
- end
50
-
51
- def after(node)
52
- last.after node
53
- end
54
-
55
- def at(path)
56
- raise NotImplementedError
57
- end
58
-
38
+ # Get the first node matching the given CSS selectors.
39
+ #
40
+ # @param rules [Array<String>] the CSS selectors to match with
41
+ #
42
+ # @return [Node?]
59
43
  def at_css(*rules)
60
- raise NotImplementedError
44
+ each {|node|
45
+ if node = node.at_css(*rules)
46
+ return node
47
+ end
48
+ }
49
+
50
+ nil
61
51
  end
62
52
 
53
+ # Get the first node matching the given XPath.
54
+ #
55
+ # @param paths [Array<String>] the XPath to match with
56
+ #
57
+ # @return [Node?]
63
58
  def at_xpath(*paths)
64
- raise NotImplementedError
65
- end
59
+ each {|node|
60
+ if node = node.at_xpath(*paths)
61
+ return node
62
+ end
63
+ }
66
64
 
67
- def before
68
- first.before
65
+ nil
69
66
  end
70
67
 
71
- def children
72
- result = NodeSet.new(document)
73
-
74
- each { |n| result.concat(n.children) }
75
-
76
- result
68
+ # Query for children matching the given CSS selector.
69
+ #
70
+ # @param selector [String] the CSS selector
71
+ #
72
+ # @return [NodeSet]
73
+ def css(path)
74
+ NodeSet[@literal.map {|node|
75
+ node.css(path)
76
+ }]
77
77
  end
78
78
 
79
- def css(*paths)
80
- raise NotImplementedError
79
+ # Create another {NodeSet} with all the nodes that match the given
80
+ # expression.
81
+ #
82
+ # @param expression [String] a CSS selector
83
+ #
84
+ # @return [NodeSet] the new {NodeSet} with the matching nodes
85
+ def filter(expression)
86
+ @literal.select { |node| node =~ expression }
81
87
  end
82
88
 
89
+ # Search for multiple selectors
83
90
  def search(*what)
84
- map { |n| n.search(*what) }.flatten.uniq
91
+ NodeSet[@literal.map { |node| node.search(*what) }]
92
+ end
93
+
94
+ # Query for children matching the given XPath.
95
+ #
96
+ # @param path [String] the XPath
97
+ #
98
+ # @return [NodeSet]
99
+ def xpath(path)
100
+ NodeSet[@literal.map {|node|
101
+ node.xpath(path)
102
+ }]
85
103
  end
86
104
 
87
- def inspect
88
- "#<DOM::NodeSet: #{@literal.inspect[1 .. -2]}"
105
+ def to_ary
106
+ @literal
89
107
  end
90
108
  end
91
109
 
@@ -1,20 +1,28 @@
1
1
  module Browser; module DOM
2
2
 
3
3
  class Document < Element
4
+ # @!attribute [r] active_element
5
+ # @return [Element] the element with focus
4
6
  def active_element
5
7
  DOM(`#@native.activeElement`)
6
8
  end
7
9
  end
8
10
 
9
11
  class Element
12
+ # Show the element.
13
+ #
14
+ # @param what [Symbol] how to display it
10
15
  def show(what = :block)
11
16
  style[:display] = what
12
17
  end
13
18
 
19
+ # Hide the element.
14
20
  def hide
15
21
  style[:display] = :none
16
22
  end
17
23
 
24
+ # Toggle the visibility of the element, hide it if it's shown, show it if
25
+ # it's hidden.
18
26
  def toggle
19
27
  if style![:display] == :none
20
28
  show
@@ -23,14 +31,17 @@ class Element
23
31
  end
24
32
  end
25
33
 
34
+ # Set the focus on the element.
26
35
  def focus
27
36
  `#@native.focus()`
28
37
  end
29
38
 
39
+ # Blur the focus from the element.
30
40
  def blur
31
41
  `#@native.blur()`
32
42
  end
33
43
 
44
+ # Check if the element is focused.
34
45
  def focused?
35
46
  `#@native.hasFocus`
36
47
  end