opal-browser 0.2.0.beta1 → 0.2.0

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