superchris-rubyjs 0.8.2

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 (86) hide show
  1. data/README +131 -0
  2. data/Rakefile +65 -0
  3. data/bin/rubyjs +144 -0
  4. data/rubyjs.gemspec +112 -0
  5. data/src/rubyjs.rb +3 -0
  6. data/src/rubyjs/code_generator.rb +474 -0
  7. data/src/rubyjs/compiler.rb +2061 -0
  8. data/src/rubyjs/debug_name_generator.rb +95 -0
  9. data/src/rubyjs/encoder.rb +171 -0
  10. data/src/rubyjs/eval_into.rb +59 -0
  11. data/src/rubyjs/lib/core.rb +1016 -0
  12. data/src/rubyjs/lib/dom_element.rb +66 -0
  13. data/src/rubyjs/lib/json.rb +101 -0
  14. data/src/rubyjs/lib/microunit.rb +188 -0
  15. data/src/rubyjs/model.rb +293 -0
  16. data/src/rubyjs/name_generator.rb +71 -0
  17. data/src/rwt/AbsolutePanel.rb +161 -0
  18. data/src/rwt/DOM.Konqueror.rb +89 -0
  19. data/src/rwt/DOM.Opera.rb +65 -0
  20. data/src/rwt/DOM.rb +1044 -0
  21. data/src/rwt/Event.Opera.rb +35 -0
  22. data/src/rwt/Event.rb +429 -0
  23. data/src/rwt/HTTPRequest.IE6.rb +5 -0
  24. data/src/rwt/HTTPRequest.rb +74 -0
  25. data/src/rwt/Label.rb +164 -0
  26. data/src/rwt/Panel.rb +90 -0
  27. data/src/rwt/RootPanel.rb +16 -0
  28. data/src/rwt/UIObject.rb +495 -0
  29. data/src/rwt/Widget.rb +193 -0
  30. data/src/rwt/ported-from/AbsolutePanel.java +158 -0
  31. data/src/rwt/ported-from/DOM.java +571 -0
  32. data/src/rwt/ported-from/DOMImpl.java +426 -0
  33. data/src/rwt/ported-from/DOMImplOpera.java +82 -0
  34. data/src/rwt/ported-from/DOMImplStandard.java +234 -0
  35. data/src/rwt/ported-from/HTTPRequest.java +81 -0
  36. data/src/rwt/ported-from/HTTPRequestImpl.java +103 -0
  37. data/src/rwt/ported-from/Label.java +163 -0
  38. data/src/rwt/ported-from/Panel.java +99 -0
  39. data/src/rwt/ported-from/UIObject.java +614 -0
  40. data/src/rwt/ported-from/Widget.java +221 -0
  41. data/test/benchmark/bm_vm1_block.rb +15 -0
  42. data/test/benchmark/bm_vm1_const.rb +13 -0
  43. data/test/benchmark/bm_vm1_ensure.rb +15 -0
  44. data/test/benchmark/common.rb +5 -0
  45. data/test/benchmark/params.yaml +7 -0
  46. data/test/common.Browser.rb +13 -0
  47. data/test/common.rb +8 -0
  48. data/test/gen_browser_test_suite.rb +129 -0
  49. data/test/gen_test_suite.rb +41 -0
  50. data/test/run_benchs.rb +58 -0
  51. data/test/run_tests.rb +22 -0
  52. data/test/test_args.rb +24 -0
  53. data/test/test_array.rb +22 -0
  54. data/test/test_case.rb +35 -0
  55. data/test/test_class.rb +55 -0
  56. data/test/test_eql.rb +9 -0
  57. data/test/test_exception.rb +61 -0
  58. data/test/test_expr.rb +12 -0
  59. data/test/test_hash.rb +29 -0
  60. data/test/test_hot_ruby.rb +146 -0
  61. data/test/test_if.rb +28 -0
  62. data/test/test_insertion_sort.rb +25 -0
  63. data/test/test_inspect.rb +10 -0
  64. data/test/test_lebewesen.rb +39 -0
  65. data/test/test_massign.rb +66 -0
  66. data/test/test_new.rb +12 -0
  67. data/test/test_range.rb +70 -0
  68. data/test/test_regexp.rb +22 -0
  69. data/test/test_send.rb +65 -0
  70. data/test/test_simple_output.rb +5 -0
  71. data/test/test_splat.rb +21 -0
  72. data/test/test_string.rb +51 -0
  73. data/test/test_test.rb +17 -0
  74. data/test/test_yield.rb +154 -0
  75. data/utils/js/Makefile +9 -0
  76. data/utils/js/RunScript.class +0 -0
  77. data/utils/js/RunScript.java +73 -0
  78. data/utils/js/js.jar +0 -0
  79. data/utils/js/run.sh +3 -0
  80. data/utils/jsc/Makefile +7 -0
  81. data/utils/jsc/README +3 -0
  82. data/utils/jsc/RunScript.c +93 -0
  83. data/utils/jsc/run.sh +15 -0
  84. data/utils/yuicompressor/README +1 -0
  85. data/utils/yuicompressor/yuicompressor-2.2.5.jar +0 -0
  86. metadata +157 -0
@@ -0,0 +1,71 @@
1
+ #
2
+ # Generate unique names from a (custom) alphabet.
3
+ #
4
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de).
5
+ # All rights reserved.
6
+ #
7
+
8
+ class NameGenerator
9
+
10
+ DEFAULT_ALPHABET = ('a' .. 'z').to_a + ('A' .. 'Z').to_a + ('0' .. '9').to_a + ['_', '$']
11
+ RESERVED_WORDS = %w(this self new break continue if then else while true false null undefined function document window)
12
+
13
+ def initialize(alphabet=DEFAULT_ALPHABET, reserved_words=RESERVED_WORDS)
14
+ @alphabet = alphabet
15
+ @reserved_words = reserved_words
16
+ @digits = [0]
17
+ @cache = {}
18
+ end
19
+
20
+ #
21
+ # We generate names using a g-adic development (where g=alphabet.size)
22
+ #
23
+ # The least significant digit is the first. If you think of it as a
24
+ # bit-string, then bit 0 would be @digits[0].
25
+ #
26
+ # In each call to next we try to increase the least significant digit.
27
+ # If it overflows, then we reset it to zero and increase the next digit.
28
+ # This continues up to the most significant digit. If this overflows,
29
+ # we introduce a new most significant digit and set this to "zero".
30
+ #
31
+
32
+ def fresh
33
+ loop do
34
+ value = @digits.reverse.map {|d| @alphabet[d] }.join("")
35
+ sz = @alphabet.size
36
+
37
+ i = 0
38
+ loop do
39
+ # increase or initialize with 0
40
+ @digits[i] = @digits[i] ? @digits[i]+1 : 0
41
+
42
+ if @digits[i] >= sz
43
+ @digits[i] = 0
44
+ i += 1
45
+ else
46
+ break
47
+ end
48
+ end
49
+
50
+ return value unless @reserved_words.include?(value)
51
+ end
52
+ end
53
+
54
+ #
55
+ # Generate a name for +name+. Return the same name for the same
56
+ # +name+.
57
+ #
58
+
59
+ def get(name)
60
+ raise unless name.is_a?(String)
61
+ @cache[name] ||= self.fresh
62
+ end
63
+
64
+ def reverse_lookup(encoded_name)
65
+ @cache.index(encoded_name)
66
+ end
67
+
68
+ def cache
69
+ @cache
70
+ end
71
+ end
@@ -0,0 +1,161 @@
1
+ #--
2
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de)
3
+ #
4
+ # Copyright 2007 Google Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+ #++
18
+
19
+ #
20
+ # An absolute panel positions all of its children absolutely, allowing them to
21
+ # overlap.
22
+ #
23
+ # Note that this panel will not automatically resize itself to allow enough
24
+ # room for its absolutely-positioned children. It must be explicitly sized in
25
+ # order to make room for them.
26
+ #
27
+ # Once a widget has been added to an absolute panel, the panel effectively
28
+ # "owns" the positioning of the widget. Any existing positioning attributes
29
+ # on the widget may be modified by the panel.
30
+ #
31
+ class AbsolutePanel < Panel
32
+
33
+ #
34
+ # Creates an empty absolute panel.
35
+ #
36
+ def initialize
37
+ @children = []
38
+
39
+ setElement(DOM.createDiv)
40
+
41
+ # Setting the panel's position style to 'relative' causes it to be treated
42
+ # as a new positioning context for its children.
43
+ DOM.setStyleAttribute(getElement(), "position", "relative");
44
+ DOM.setStyleAttribute(getElement(), "overflow", "hidden");
45
+ end
46
+
47
+ #
48
+ # Adds a child widget to this panel.
49
+ #
50
+ # w:: the child widget to be added
51
+ #
52
+ def add(w)
53
+ adopt(w, getElement())
54
+ @children << w if @children
55
+ end
56
+
57
+ def each(&block)
58
+ @children.each(&block)
59
+ end
60
+
61
+ #
62
+ # Adds a widget to the panel at the specified position.
63
+ #
64
+ # w:: the widget to be added
65
+ # left:: the widget's left pixel position
66
+ # top:: the widget's top pixel position
67
+ #
68
+ def addPositioned(w, left, top)
69
+ # In order to avoid the potential for a flicker effect, it is necessary
70
+ # to set the position of the widget before adding it to the AbsolutePanel.
71
+ # The Widget should be removed from its parent before any positional
72
+ # changes are made to prevent flickering.
73
+ w.removeFromParent
74
+ DOM.setAbsolutePixelPosition(w.getElement, left, top)
75
+ add(w)
76
+ end
77
+
78
+ #
79
+ # Adds a widget to the panel using a static position.
80
+ #
81
+ # w:: the widget to be added
82
+ #
83
+ def addStatic(w)
84
+ # In order to avoid the potential for a flicker effect, it is necessary
85
+ # to set the position of the widget before adding it to the AbsolutePanel.
86
+ # The Widget should be removed from its parent before any positional
87
+ # changes are made to prevent flickering.
88
+ w.removeFromParent
89
+ DOM.changeToStaticPositioning(w.getElement)
90
+ add(w)
91
+ end
92
+
93
+ #
94
+ # Gets the position of the left outer border edge of the widget relative to
95
+ # the left outer border edge of the panel.
96
+ #
97
+ # w:: the widget whose position is to be retrieved
98
+ # return:: the widget's left position
99
+ #
100
+ def getWidgetLeft(w)
101
+ checkWidgetParent(w)
102
+ return DOM.getAbsoluteLeft(w.getElement) - DOM.getAbsoluteLeft(getElement())
103
+ end
104
+
105
+ #
106
+ # Gets the position of the top outer border edge of the widget relative to
107
+ # the top outer border edge of the panel.
108
+ #
109
+ # w:: the widget whose position is to be retrieved
110
+ # return:: the widget's top position
111
+ #
112
+ def getWidgetTop(w)
113
+ checkWidgetParent(w)
114
+ return DOM.getAbsoluteTop(w.getElement) - DOM.getAbsoluteTop(getElement())
115
+ end
116
+
117
+ #
118
+ # Sets the position of the specified child widget.
119
+ #
120
+ # w:: the child widget to be positioned
121
+ # left:: the widget's left pixel position
122
+ # top:: the widget's top pixel position
123
+ #
124
+ def setWidgetPosition(w, left, top)
125
+ checkWidgetParent(w)
126
+ DOM.setAbsolutePixelPosition(w.getElement, left, top)
127
+ end
128
+
129
+ #
130
+ # Changes the positioning of the specified child widget to static
131
+ # positioning.
132
+ #
133
+ # w:: the child widget to be statically positioned
134
+ #
135
+ def setWidgetPositionToStatic(w)
136
+ checkWidgetParent(w)
137
+ DOM.changeToStaticPositioning(w.getElement)
138
+ end
139
+
140
+ protected
141
+
142
+ #
143
+ # Calls the superclass' +disown+ method, and sets the positioning of the
144
+ # widget to static. This is done so that any positioning changes to the
145
+ # widget that were done by the panel are undone when the widget is disowned
146
+ # from the panel.
147
+ #
148
+ # w:: the widget to be disowned
149
+ #
150
+ def disown(w)
151
+ super(w)
152
+ DOM.changeToStaticPositioning(w.getElement)
153
+ end
154
+
155
+ private
156
+
157
+ def checkWidgetParent(w)
158
+ raise "Widget must be a child of this panel" if w.getParent != self
159
+ end
160
+
161
+ end # class AbsolutePanel
@@ -0,0 +1,89 @@
1
+ #--
2
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de)
3
+ #++
4
+
5
+ class DOM
6
+
7
+ def self.appendChild(parent, child) `
8
+ if (#<child>.nodeType == 3)
9
+ {
10
+ #<parent>.appendChild(#<child>);
11
+ #<parent>.removeChild(#<child>);
12
+ }
13
+ #<parent>.appendChild(#<child>);
14
+ return #<nil>`
15
+ end
16
+
17
+ def self.insertChild(parent, child, index) `
18
+ var count = 0, child = #<parent>.firstChild, before = null;
19
+ while (child) {
20
+ if (child.nodeType == 1) {
21
+ if (count == #<index>) {
22
+ before = child;
23
+ break;
24
+ }
25
+ ++count;
26
+ }
27
+ child = child.nextSibling;
28
+ }
29
+
30
+ if (#<child>.nodeType == 3)
31
+ {
32
+ #<parent>.appendChild(#<child>);
33
+ #<parent>.removeChild(#<child>);
34
+ }
35
+ #<parent>.insertBefore(#<child>, before);
36
+ return #<nil>`
37
+ end
38
+
39
+ def self.insertBefore(parent, child, before) `
40
+ if (#<child>.nodeType == 3)
41
+ {
42
+ #<parent>.appendChild(#<child>);
43
+ #<parent>.removeChild(#<child>);
44
+ }
45
+ #<parent>.insertBefore(#<child>, #<before>);
46
+ return #<nil>`
47
+ end
48
+
49
+ def self.replace(elem, newElem) `
50
+ var p = #<elem>.parentNode;
51
+ if (!p) return;
52
+
53
+ if (#<newElem>.nodeType == 3)
54
+ {
55
+ p.appendChild(#<newElem>);
56
+ p.removeChild(#<newElem>);
57
+ }
58
+
59
+ p.insertBefore(#<newElem>, #<elem>);
60
+ p.removeChild(#<elem>);
61
+ return #<nil>`
62
+ end
63
+
64
+ def self.setInnerHTML(elem, html='') `
65
+ #<elem>.innerHTML = #<html>;
66
+ if (#<html>.search("<") == -1)
67
+ {
68
+ // contains no HTML, so we have to assign it twice
69
+ #<elem>.innerHTML = #<html>;
70
+ }
71
+ return #<nil>`
72
+ end
73
+
74
+ def self.setInnerText(elem, text) `
75
+ // Remove all children first.
76
+ while (#<elem>.firstChild) {
77
+ #<elem>.removeChild(#<elem>.firstChild);
78
+ }
79
+ // Add a new text node.
80
+ if (#<text> !== #<nil>) {
81
+ var n = document.createTextNode(#<text>);
82
+ #<elem>.appendChild(n);
83
+ #<elem>.removeChild(n);
84
+ #<elem>.appendChild(n);
85
+ }
86
+ return #<nil>`
87
+ end
88
+
89
+ end
@@ -0,0 +1,65 @@
1
+ #--
2
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de)
3
+ #
4
+ # Copyright 2007 Google Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+ #++
18
+
19
+ #
20
+ # Opera specific overrides.
21
+ #
22
+ class DOM
23
+
24
+ def self.getAbsoluteLeft(elem) `
25
+ var left = 0;
26
+ var curr = #<elem>.parentNode;
27
+ // This intentionally excludes body
28
+ while (curr != document.body) {
29
+ // see https://bugs.opera.com/show_bug.cgi?id=249965
30
+ // The net effect is that TR and TBODY elements report the scroll offsets
31
+ // of the BODY and HTML elements instead of 0.
32
+ if (curr.tagName != 'TR' && curr.tagName != 'TBODY') {
33
+ left -= curr.scrollLeft;
34
+ }
35
+ curr = curr.parentNode;
36
+ }
37
+
38
+ while (#<elem>) {
39
+ left += #<elem>.offsetLeft;
40
+ #<elem> = #<elem>.offsetParent;
41
+ }
42
+ return left`
43
+ end
44
+
45
+ def self.getAbsoluteTop(elem) `
46
+ var top = 0;
47
+
48
+ // This intentionally excludes body
49
+ var curr = #<elem>.parentNode;
50
+ while (curr != document.body) {
51
+ // see getAbsoluteLeft()
52
+ if (curr.tagName != 'TR' && curr.tagName != 'TBODY') {
53
+ top -= curr.scrollTop;
54
+ }
55
+ curr = curr.parentNode;
56
+ }
57
+
58
+ while (#<elem>) {
59
+ top += #<elem>.offsetTop;
60
+ #<elem> = #<elem>.offsetParent;
61
+ }
62
+ return top`
63
+ end
64
+
65
+ end
@@ -0,0 +1,1044 @@
1
+ #--
2
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de)
3
+ #
4
+ # Copyright 2007 Google Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+ #++
18
+
19
+ class DOM
20
+
21
+ #-------------------------------------------------------------------
22
+ # Element creation
23
+ #-------------------------------------------------------------------
24
+
25
+ #
26
+ # Creates an HTML element.
27
+ #
28
+ # tagName:: the HTML tag of the element to be created
29
+ # return:: the newly-created element
30
+ #
31
+ def self.createElement(tagName)
32
+ `return document.createElement(#<tagName>)`
33
+ end
34
+
35
+ #
36
+ # Creates an HTML A element.
37
+ #
38
+ # return:: the newly-created element
39
+ #
40
+ def self.createAnchor
41
+ createElement("A")
42
+ end
43
+
44
+ #
45
+ # Creates an HTML BUTTON element.
46
+ #
47
+ # return:: the newly-created element
48
+ #
49
+ def self.createButton()
50
+ createElement("button")
51
+ end
52
+
53
+ #
54
+ # Creates an HTML CAPTION element.
55
+ #
56
+ # return:: the newly-created element
57
+ #
58
+ def self.createCaption
59
+ createElement("caption")
60
+ end
61
+
62
+ #
63
+ # Creates an HTML COL element.
64
+ #
65
+ # return:: the newly-created element
66
+ #
67
+ def self.createCol
68
+ createElement("col")
69
+ end
70
+
71
+ #
72
+ # Creates an HTML COLGROUP element.
73
+ #
74
+ # return:: the newly-created element
75
+ #
76
+ def self.createColGroup
77
+ createElement("colgroup")
78
+ end
79
+
80
+ #
81
+ # Creates an HTML DIV element.
82
+ #
83
+ # return:: the newly-created element
84
+ #
85
+ def self.createDiv
86
+ createElement("div")
87
+ end
88
+
89
+ #
90
+ # Creates an HTML FIELDSET element.
91
+ #
92
+ # return:: the newly-created element
93
+ #
94
+ def self.createFieldSet
95
+ createElement("fieldset")
96
+ end
97
+
98
+ #
99
+ # Creates an HTML FORM element.
100
+ #
101
+ # return:: the newly-created element
102
+ #
103
+ def self.createForm
104
+ createElement("form")
105
+ end
106
+
107
+ #
108
+ # Creates an HTML IFRAME element.
109
+ #
110
+ # return:: the newly-created element
111
+ #
112
+ def self.createIFrame
113
+ createElement("iframe")
114
+ end
115
+
116
+ #
117
+ # Creates an HTML IMG element.
118
+ #
119
+ # return:: the newly-created element
120
+ #
121
+ def self.createImg
122
+ createElement("img")
123
+ end
124
+
125
+ #
126
+ # Creates an HTML LABEL element.
127
+ #
128
+ # return:: the newly-created element
129
+ #
130
+ def self.createLabel
131
+ createElement("label")
132
+ end
133
+
134
+ #
135
+ # Creates an HTML LEGEND element.
136
+ #
137
+ # return:: the newly-created element
138
+ #
139
+ def self.createLegend
140
+ createElement("legend")
141
+ end
142
+
143
+ #
144
+ # Creates an HTML OPTIONS element.
145
+ #
146
+ # return:: the newly-created element
147
+ #
148
+ def self.createOptions
149
+ createElement("options")
150
+ end
151
+
152
+ #
153
+ # Creates an HTML SELECT element.
154
+ #
155
+ # multiple:: +true+ if multiple selection of options is allowed
156
+ # (default +false+)
157
+ # return:: the newly-created element
158
+ #
159
+ def self.createSelect(multiple=false)
160
+ select = createElement("select")
161
+ setProperty(select, "multiple", true) if multiple
162
+ return select
163
+ end
164
+
165
+ #
166
+ # Creates an HTML SPAN element.
167
+ #
168
+ # return:: the newly-created element
169
+ #
170
+ def self.createSpan
171
+ createElement("span")
172
+ end
173
+
174
+ #
175
+ # Creates an HTML TABLE element.
176
+ #
177
+ # return:: the newly-created element
178
+ #
179
+ def self.createTable
180
+ createElement("table")
181
+ end
182
+
183
+ #
184
+ # Creates an HTML TBODY element.
185
+ #
186
+ # return:: the newly-created element
187
+ #
188
+ def self.createTBody
189
+ createElement("tbody")
190
+ end
191
+
192
+ #
193
+ # Creates an HTML TD element.
194
+ #
195
+ # return:: the newly-created element
196
+ #
197
+ def self.createTD
198
+ createElement("td")
199
+ end
200
+
201
+ #
202
+ # Creates an HTML TEXTAREA element.
203
+ #
204
+ # return:: the newly-created element
205
+ #
206
+ def self.createTextArea
207
+ createElement("textarea")
208
+ end
209
+
210
+ #
211
+ # Creates an HTML TFOOT element.
212
+ #
213
+ # return:: the newly-created element
214
+ #
215
+ def self.createTFoot
216
+ createElement("tfoot")
217
+ end
218
+
219
+ #
220
+ # Creates an HTML TH element.
221
+ #
222
+ # return:: the newly-created element
223
+ #
224
+ def self.createTH
225
+ createElement("th")
226
+ end
227
+
228
+ #
229
+ # Creates an HTML THEAD element.
230
+ #
231
+ # return:: the newly-created element
232
+ #
233
+ def self.createTHead
234
+ createElement("thead")
235
+ end
236
+
237
+ #
238
+ # Creates an HTML TR element.
239
+ #
240
+ # return:: the newly-created element
241
+ #
242
+ def self.createTR
243
+ createElement("tr")
244
+ end
245
+
246
+ #
247
+ # Creates an HTML INPUT element.
248
+ #
249
+ # type:: the value of the type attribute
250
+ # return:: the newly-created element
251
+ #
252
+ def self.createInput(type) `
253
+ var e = document.createElement("INPUT");
254
+ e.type = #<type>;
255
+ return e`
256
+ end
257
+
258
+ #
259
+ # Creates an HTML INPUT type='CHECK' element.
260
+ #
261
+ # return:: the newly-created element
262
+ #
263
+ def self.createInputCheck
264
+ createInput("checkbox")
265
+ end
266
+
267
+ #
268
+ # Creates an HTML INPUT type='PASSWORD' element.
269
+ #
270
+ # return:: the newly-created element
271
+ #
272
+ def self.createInputPassword
273
+ createInput("password")
274
+ end
275
+
276
+ #
277
+ # Creates an HTML INPUT type='TEXT' element.
278
+ #
279
+ # return:: the newly-created element
280
+ #
281
+ def self.createInputText
282
+ createInput("text")
283
+ end
284
+
285
+ #
286
+ # Creates an HTML INPUT type='RADIO' element.
287
+ #
288
+ # name:: the name of the group with which this radio button will be
289
+ # associated
290
+ # return:: the newly-created element
291
+ #
292
+ def self.createInputRadio(name) `
293
+ var e = document.createElement("INPUT");
294
+ e.type = 'radio';
295
+ e.name = #<name>;
296
+ return e`
297
+ end
298
+
299
+ #-------------------------------------------------------------------
300
+ # DOM manipulation
301
+ #-------------------------------------------------------------------
302
+
303
+ #
304
+ # Appends one element to another's list of children.
305
+ #
306
+ # parent:: the parent element
307
+ # child:: its new child
308
+ #
309
+ def self.appendChild(parent, child)
310
+ `#<parent>.appendChild(#<child>); return #<nil>`
311
+ end
312
+
313
+ #
314
+ # Inserts an element as a child of the given parent element.
315
+ #
316
+ # parent:: the parent element
317
+ # child:: the child element to add to +parent+
318
+ # index:: the index before which the child will be inserted (any value
319
+ # greater than the number of existing children will cause the child
320
+ # to be appended)
321
+ #
322
+ def self.insertChild(parent, child, index) `
323
+ var count = 0, child = #<parent>.firstChild, before = null;
324
+ while (child) {
325
+ if (child.nodeType == 1) {
326
+ if (count == #<index>) {
327
+ before = child;
328
+ break;
329
+ }
330
+ ++count;
331
+ }
332
+ child = child.nextSibling;
333
+ }
334
+
335
+ #<parent>.insertBefore(#<child>, before);
336
+ return #<nil>`
337
+ end
338
+
339
+ #
340
+ # Inserts an element as a child of the given parent element, before another
341
+ # child of that parent.
342
+ #
343
+ # parent:: the parent element
344
+ # child:: the child element to add to +parent+
345
+ # before:: an existing child element of +parent+ before
346
+ # which +child+ will be inserted
347
+ #
348
+ def self.insertBefore(parent, child, before)
349
+ `#<parent>.insertBefore(#<child>, #<before>); return #<nil>`
350
+ end
351
+
352
+ #
353
+ # Removes a child element from the given parent element.
354
+ #
355
+ # parent:: the parent element
356
+ # child:: the child element to be removed
357
+ #
358
+ def self.removeChild(parent, child)
359
+ `#<parent>.removeChild(#<child>); return #<nil>`
360
+ end
361
+
362
+ #
363
+ # Replaces +elem+ in the DOM tree with element +newElem+.
364
+ #
365
+ # elem:: the element to be replaced
366
+ # newElem:: the element that is used to replace +elem+ with.
367
+ #
368
+ def self.replace(elem, newElem) `
369
+ var p = #<elem>.parentNode;
370
+ if (!p) return;
371
+ p.insertBefore(#<newElem>, #<elem>);
372
+ p.removeChild(#<elem>);
373
+ return #<nil>`
374
+ end
375
+
376
+ #-------------------------------------------------------------------
377
+ # DOM navigation
378
+ #-------------------------------------------------------------------
379
+
380
+ #
381
+ # Gets the element associated with the given unique id within the entire
382
+ # document.
383
+ #
384
+ # id:: the id whose associated element is to be retrieved
385
+ # return:: the associated element, or +nil+ if none is found
386
+ #
387
+ def self.getElementById(id)
388
+ `return document.getElementById(#<id>) || #<nil>`
389
+ end
390
+
391
+ #
392
+ # Gets an element's n-th child element.
393
+ #
394
+ # parent:: the element whose child is to be retrieved
395
+ # index:: the index of the child element
396
+ # return:: the n-th child element
397
+ #
398
+ def self.getChild(parent, index) `
399
+ var count = 0, child = #<parent>.firstChild;
400
+ while (child) {
401
+ var next = child.nextSibling;
402
+ if (child.nodeType == 1) {
403
+ if (#<index> == count)
404
+ return child;
405
+ ++count;
406
+ }
407
+ child = next;
408
+ }
409
+
410
+ return #<nil>`
411
+ end
412
+
413
+ #
414
+ # Gets the number of child elements present in a given parent element.
415
+ #
416
+ # parent:: the element whose children are to be counted
417
+ # return:: the number of children
418
+ #
419
+ def self.getChildCount(parent) `
420
+ var count = 0, child = #<parent>.firstChild;
421
+ while (child) {
422
+ if (child.nodeType == 1)
423
+ ++count;
424
+ child = child.nextSibling;
425
+ }
426
+ return count`
427
+ end
428
+
429
+ #
430
+ # Gets the index of a given child element within its parent.
431
+ #
432
+ # parent:: the parent element
433
+ # child:: the child element
434
+ # return:: the child's index within its parent, or +nil+ if it is
435
+ # not a child of the given parent
436
+ #
437
+ def self.getChildIndex(parent, child) `
438
+ var count = 0, child = #<parent>.firstChild;
439
+ while (child) {
440
+ if (child == #<child>)
441
+ return count;
442
+ if (child.nodeType == 1)
443
+ ++count;
444
+ child = child.nextSibling;
445
+ }
446
+
447
+ return #<nil>`
448
+ end
449
+
450
+ #
451
+ # Gets the first child element of the given element.
452
+ #
453
+ # elem:: the element whose child is to be retrieved
454
+ # return:: the child element
455
+ #
456
+ def self.getFirstChild(elem) `
457
+ var child = #<elem>.firstChild;
458
+ while (child && child.nodeType != 1)
459
+ child = child.nextSibling;
460
+ return child || #<nil>`
461
+ end
462
+
463
+ #
464
+ # Gets an element's next sibling element.
465
+ #
466
+ # elem:: the element whose sibling is to be retrieved
467
+ # return:: the sibling element
468
+ #
469
+ def self.getNextSibling(elem) `
470
+ var sib = #<elem>.nextSibling;
471
+ while (sib && sib.nodeType != 1)
472
+ sib = sib.nextSibling;
473
+ return sib || #<nil>`
474
+ end
475
+
476
+ #
477
+ # Gets an element's parent element.
478
+ #
479
+ # elem:: the element whose parent is to be retrieved
480
+ # return:: the parent element
481
+ #
482
+ def self.getParent(elem) `
483
+ var parent = #<elem>.parentNode;
484
+ if(parent == null) {
485
+ return #<nil>;
486
+ }
487
+ if (parent.nodeType != 1)
488
+ parent = null;
489
+ return parent || #<nil>`
490
+ end
491
+
492
+ #-------------------------------------------------------------------
493
+ # Event related
494
+ #-------------------------------------------------------------------
495
+
496
+ #
497
+ # Sets the +EventListener+ to receive events for the given element.
498
+ # Only one such listener may exist for a single element.
499
+ #
500
+ # elem:: the element whose listener is to be set
501
+ # listener:: the listener to receive events
502
+ #
503
+ def self.setEventListener(elem, listener)
504
+ `#<elem>.#<attr:listener> = (#<listener> === #<nil>) ? null : #<listener>; return #<nil>`
505
+ end
506
+
507
+ def self.removeEventListener(elem)
508
+ `#<elem>.#<attr:listener> = null; return #<nil>`
509
+ end
510
+
511
+ #
512
+ # Gets the current set of events sunk by a given element.
513
+ #
514
+ # elem:: the element whose events are to be retrieved
515
+ # return:: a bitfield describing the events sunk on this element (its possible
516
+ # values are described in +Event+)
517
+ #
518
+ def self.getEventsSunk(elem)
519
+ `return #<elem>.#<attr:eventBits> || 0`
520
+ end
521
+
522
+ #
523
+ # Sets the current set of events sunk by a given element. These events will
524
+ # be fired to the nearest +EventListener+ specified on any of the
525
+ # element's parents.
526
+ #
527
+ # elem:: the element whose events are to be retrieved
528
+ # eventBits:: a bitfield describing the events sunk on this element (its
529
+ # possible values are described in +Event+)
530
+ #
531
+ def self.sinkEvents(elem, eventBits) `
532
+ #<elem>.#<attr:eventBits> = #<eventBits>;
533
+
534
+ #<elem>.onclick = (#<eventBits> & 0x00001) ? window.#<attr:dispatch> : null;
535
+ #<elem>.ondblclick = (#<eventBits> & 0x00002) ? window.#<attr:dispatch> : null;
536
+ #<elem>.onmousedown = (#<eventBits> & 0x00004) ? window.#<attr:dispatch> : null;
537
+ #<elem>.onmouseup = (#<eventBits> & 0x00008) ? window.#<attr:dispatch> : null;
538
+ #<elem>.onmouseover = (#<eventBits> & 0x00010) ? window.#<attr:dispatch> : null;
539
+ #<elem>.onmouseout = (#<eventBits> & 0x00020) ? window.#<attr:dispatch> : null;
540
+ #<elem>.onmousemove = (#<eventBits> & 0x00040) ? window.#<attr:dispatch> : null;
541
+ #<elem>.onkeydown = (#<eventBits> & 0x00080) ? window.#<attr:dispatch> : null;
542
+ #<elem>.onkeypress = (#<eventBits> & 0x00100) ? window.#<attr:dispatch> : null;
543
+ #<elem>.onkeyup = (#<eventBits> & 0x00200) ? window.#<attr:dispatch> : null;
544
+ #<elem>.onchange = (#<eventBits> & 0x00400) ? window.#<attr:dispatch> : null;
545
+ #<elem>.onfocus = (#<eventBits> & 0x00800) ? window.#<attr:dispatch> : null;
546
+ #<elem>.onblur = (#<eventBits> & 0x01000) ? window.#<attr:dispatch> : null;
547
+ #<elem>.onlosecapture = (#<eventBits> & 0x02000) ? window.#<attr:dispatch> : null;
548
+ #<elem>.onscroll = (#<eventBits> & 0x04000) ? window.#<attr:dispatch> : null;
549
+ #<elem>.onload = (#<eventBits> & 0x08000) ? window.#<attr:dispatch> : null;
550
+ #<elem>.onerror = (#<eventBits> & 0x10000) ? window.#<attr:dispatch> : null;
551
+ #<elem>.onmousewheel = (#<eventBits> & 0x20000) ? window.#<attr:dispatch> : null;
552
+
553
+ return #<nil>`
554
+ end
555
+
556
+ #-------------------------------------------------------------------
557
+ # Attribute related
558
+ #-------------------------------------------------------------------
559
+
560
+ #
561
+ # Gets the named attribute from the element.
562
+ #
563
+ # elem:: the element whose property is to be retrieved
564
+ # attr:: the name of the attribute
565
+ # return:: the value of the attribute
566
+ #
567
+ def self.getAttribute(elem, attr) `
568
+ var ret = #<elem>.getAttribute(#<attr>);
569
+ return (ret == null) ? #<nil> : ret`
570
+ end
571
+
572
+ #
573
+ # Sets an attribute on a given element.
574
+ #
575
+ # elem:: element whose attribute is to be set
576
+ # attr:: the name of the attribute
577
+ # value:: the value to which the attribute should be set
578
+ #
579
+ def self.setAttribute(elem, attr, value)
580
+ `#<elem>.setAttribute(#<attr>, #<value>); return #<nil>`
581
+ end
582
+
583
+ #
584
+ # Removes the named attribute from the given element.
585
+ #
586
+ # elem:: the element whose attribute is to be removed
587
+ # attr:: the name of the element to remove
588
+ #
589
+ def self.removeAttribute(elem, attr)
590
+ `#<elem>.removeAttribute(#<attr>); return #<nil>`
591
+ end
592
+
593
+ #-------------------------------------------------------------------
594
+ # Style Attribute related
595
+ #-------------------------------------------------------------------
596
+
597
+ #
598
+ # Gets an attribute of the given element's style.
599
+ #
600
+ # elem:: the element whose style attribute is to be retrieved
601
+ # attr:: the name of the style attribute to be retrieved
602
+ # return:: the style attribute's value
603
+ #
604
+ def self.getStyleAttribute(elem, attr) `
605
+ var ret = #<elem>.style[#<attr>];
606
+ return (ret == null) ? #<nil> : ret`
607
+ end
608
+
609
+ #
610
+ # Gets an integer attribute on a given element's style.
611
+ #
612
+ # elem:: the element whose style attribute is to be retrieved
613
+ # attr:: the name of the attribute to be retrieved
614
+ # return:: the style attribute's value as an integer
615
+ #
616
+ def self.getStyleAttributeInt(elem, attr) `
617
+ var i = parseInt(#<elem>.style[#<attr>]);
618
+ return ((!i) ? 0 : i)`
619
+ end
620
+
621
+ #
622
+ # Gets a boolean attribute on a given element's style.
623
+ #
624
+ # elem:: the element whose style attribute is to be retrieved
625
+ # attr:: the name of the attribute to be retrieved
626
+ # return:: the style attribute's value as a boolean
627
+ #
628
+ def self.getStyleAttributeBoolean(elem, attr)
629
+ `return !!#<elem>.style[#<attr>]`
630
+ end
631
+
632
+ #
633
+ # Sets an attribute on the given element's style.
634
+ #
635
+ # elem:: the element whose style attribute is to be set
636
+ # attr:: the name of the style attribute to be set
637
+ # value:: the style attribute's new value
638
+ #
639
+ def self.setStyleAttribute(elem, attr, value)
640
+ `#<elem>.style[#<attr>] = #<value>; return #<nil>`
641
+ end
642
+
643
+ #-------------------------------------------------------------------
644
+ # Property related
645
+ #-------------------------------------------------------------------
646
+
647
+ #
648
+ # Gets any named property from an element, as a string.
649
+ #
650
+ # elem:: the element whose property is to be retrieved
651
+ # prop:: the name of the property
652
+ # return:: the property's value
653
+ #
654
+ def self.getProperty(elem, prop) `
655
+ var ret = #<elem>[#<prop>];
656
+ return (ret == null) ? #<nil> : String(ret)`
657
+ end
658
+
659
+ #
660
+ # Gets any named property from an element, as a boolean.
661
+ #
662
+ # param:: elem the element whose property is to be retrieved
663
+ # param:: prop the name of the property
664
+ # return:: the property's value as a boolean
665
+ #
666
+ def self.getPropertyBoolean(elem, prop)
667
+ `return !!#<elem>[#<prop>]`
668
+ end
669
+
670
+ #
671
+ # Gets any named property from an element, as an int.
672
+ #
673
+ # elem:: the element whose property is to be retrieved
674
+ # prop:: the name of the property
675
+ # return:: the property's value as an int
676
+ #
677
+ def self.getPropertyInt(elem, prop) `
678
+ var i = parseInt(#<elem>[#<prop>]);
679
+ return ((!i) ? 0 : i)`
680
+ end
681
+
682
+ #
683
+ # Sets a property on the given element.
684
+ #
685
+ # elem:: the element whose property is to be set
686
+ # prop:: the name of the property to be set
687
+ # value:: the new property value
688
+ #
689
+ def self.setProperty(elem, prop, value)
690
+ `#<elem>[#<prop>] = #<value>; return #<nil>`
691
+ end
692
+
693
+ #-------------------------------------------------------------------
694
+ # Misc
695
+ #-------------------------------------------------------------------
696
+
697
+ #
698
+ # Compares two elements for equality (note that reference equality is not
699
+ # sufficient to determine equality among elements on most browsers).
700
+ #
701
+ # elem1:: the first element to be compared
702
+ # elem2:: the second element to be compared
703
+ # return:: +true+ if they are in fact the same element
704
+ #
705
+ # See #isOrHasChild.
706
+ #
707
+ def self.compare(elem1, elem2)
708
+ `return (#<elem1> == #<elem2>)`
709
+ end
710
+
711
+ #
712
+ # Determine whether one element is equal to, or the child of, another.
713
+ #
714
+ # parent:: the potential parent element
715
+ # child:: the potential child element
716
+ # return:: +true+ if the relationship holds
717
+ #
718
+ # See #compare.
719
+ #
720
+ def self.isOrHasChild(parent, child) `
721
+ while (#<child>) {
722
+ if (#<parent> == #<child>) {
723
+ return true;
724
+ }
725
+ #<child> = #<child>.parentNode;
726
+ if (#<child> && (#<child>.nodeType != 1)) {
727
+ #<child> = null;
728
+ }
729
+ }
730
+ return false`
731
+ end
732
+
733
+ #
734
+ # Gets an element's absolute left coordinate in the document's coordinate
735
+ # system.
736
+ #
737
+ # elem:: the element to be measured
738
+ # return:: the element's absolute left coordinate
739
+ #
740
+ def self.getAbsoluteLeft(elem) `
741
+ var left = 0;
742
+ var curr = #<elem>;
743
+ // This intentionally excludes body which has a null offsetParent.
744
+ while (curr.offsetParent) {
745
+ left -= curr.scrollLeft;
746
+ curr = curr.parentNode;
747
+ }
748
+ while (#<elem>) {
749
+ left += #<elem>.offsetLeft;
750
+ #<elem> = #<elem>.offsetParent;
751
+ }
752
+ return left`
753
+ end
754
+
755
+ #
756
+ # Gets an element's absolute top coordinate in the document's coordinate
757
+ # system.
758
+ #
759
+ # elem:: the element to be measured
760
+ # return:: the element's absolute top coordinate
761
+ #
762
+ def self.getAbsoluteTop(elem) `
763
+ var top = 0;
764
+ var curr = #<elem>;
765
+ // This intentionally excludes body which has a null offsetParent.
766
+ while (curr.offsetParent) {
767
+ top -= curr.scrollTop;
768
+ curr = curr.parentNode;
769
+ }
770
+ while (#<elem>) {
771
+ top += #<elem>.offsetTop;
772
+ #<elem> = #<elem>.offsetParent;
773
+ }
774
+ return top`
775
+ end
776
+
777
+ #
778
+ # Gets the element that currently has mouse capture.
779
+ #
780
+ # return:: a handle to the capture element, or +nil+ if none exists
781
+ #
782
+ def self.getCapture
783
+ return @sCaptureElem
784
+ end
785
+
786
+ #
787
+ # Releases mouse capture on the given element. Calling this method has no
788
+ # effect if the element does not currently have mouse capture.
789
+ #
790
+ # elem:: the element to release capture
791
+ #
792
+ # See #setCapture.
793
+ #
794
+ def self.releaseCapture(elem)
795
+ @sCaptureElem = nil if @sCaptureElem and compare(elem, @sCaptureElem)
796
+ `if (#<elem> == window.#<attr:captureElem>) window.#<attr:captureElem> = null;`
797
+ return nil
798
+ end
799
+
800
+ #
801
+ # Sets mouse-capture on the given element. This element will directly receive
802
+ # all mouse events until {@link #releaseCapture(Element)} is called on it.
803
+ #
804
+ # elem:: the element on which to set mouse capture
805
+ #
806
+ def self.setCapture(elem)
807
+ @sCaptureElem = elem
808
+ `window.#<attr:captureElem> = #<elem>;`
809
+ return nil
810
+ end
811
+
812
+ #
813
+ # Gets the src attribute of an img element. This method is paired with
814
+ # #setImgSrc so that it always returns the correct url.
815
+ #
816
+ # img:: a non-nil img whose src attribute is to be read.
817
+ # return:: the src url of the img
818
+ #
819
+ def self.getImgSrc(img) `
820
+ var ret = #<img>.src;
821
+ return (ret == null) ? #<nil> : ret`
822
+ end
823
+
824
+ #
825
+ # Sets the src attribute of an img element. This method ensures that imgs
826
+ # only ever have their contents requested one single time from the server.
827
+ #
828
+ # img:: a non-nil img whose src attribute will be set.
829
+ # src:: a non-nil url for the img
830
+ #
831
+ def self.setImgSrc(img, src)
832
+ `#<img>.src = #<src>; return #<nil>`
833
+ end
834
+
835
+ #
836
+ # Gets an HTML representation (as String) of an element's children.
837
+ #
838
+ # elem:: the element whose HTML is to be retrieved
839
+ # return:: the HTML representation of the element's children
840
+ #
841
+ def self.getInnerHTML(elem) `
842
+ var ret = #<elem>.innerHTML;
843
+ return (ret == null) ? #<nil> : ret`
844
+ end
845
+
846
+ #
847
+ # Sets the HTML contained within an element.
848
+ #
849
+ # elem:: the element whose inner HTML is to be set
850
+ # html:: the new html
851
+ #
852
+ def self.setInnerHTML(elem, html='') `
853
+ #<elem>.innerHTML = #<html>;
854
+ return #<nil>`
855
+ end
856
+
857
+ #
858
+ # Gets the text contained within an element. If the element has child
859
+ # elements, only the text between them will be retrieved.
860
+ #
861
+ # elem:: the element whose inner text is to be retrieved
862
+ # return:: the text inside this element
863
+ #
864
+ def self.getInnerText(elem) `
865
+ // To mimic IEs +innerText+ property in the W3C DOM, we need to recursively
866
+ // concatenate all child text nodes (depth first).
867
+ var text = '', child = #<elem>.firstChild;
868
+ while (child) {
869
+ // 1 == Element node
870
+ if (child.nodeType == 1) {
871
+ text += this.#<m:getInnerText>(#<nil>, child);
872
+ } else if (child.nodeValue) {
873
+ text += child.nodeValue;
874
+ }
875
+ child = child.nextSibling;
876
+ }
877
+ return text`
878
+ end
879
+
880
+ #
881
+ # Sets the text contained within an element. If the element already has
882
+ # children, they will be destroyed.
883
+ #
884
+ # elem:: the element whose inner text is to be set
885
+ # text:: the new text
886
+ #
887
+ def self.setInnerText(elem, text) `
888
+ // Remove all children first.
889
+ while (#<elem>.firstChild) {
890
+ #<elem>.removeChild(#<elem>.firstChild);
891
+ }
892
+ // Add a new text node.
893
+ if (#<text> !== #<nil>) {
894
+ #<elem>.appendChild(document.createTextNode(#<text>));
895
+ }
896
+ return #<nil>`
897
+ end
898
+
899
+ #
900
+ # Sets the option text of the given select object.
901
+ #
902
+ # select:: the select object whose option text is being set
903
+ # text:: the text to set
904
+ # index:: the index of the option whose text should be set
905
+ #
906
+ def self.setOptionText(select, text, index)
907
+ # IE doesnt properly update the screen when you use
908
+ # setAttribute('option', text), so we instead directly assign to the
909
+ # 'option' property, which works correctly on all browsers.
910
+ `var option = #<select>.options[#<index>];
911
+ option.text = #<text>;
912
+ return #<nil>`
913
+ end
914
+
915
+ #
916
+ # Returns a stringized version of the element. This string is for debugging
917
+ # purposes and will NOT be consistent on different browsers.
918
+ #
919
+ # elem:: the element to stringize
920
+ # return:: a string form of the element
921
+ #
922
+ def self.to_s(elem)
923
+ `return #<elem>.outerHTML`
924
+ end
925
+
926
+ #
927
+ # Checks whether the element is visible or not.
928
+ #
929
+ # elem:: the element to check for visibility
930
+ # return:: +true+ if element is visible, +false+ otherwise
931
+ #
932
+ def self.isVisible(elem)
933
+ `return (#<elem>.style.display != 'none')`
934
+ end
935
+
936
+ #
937
+ # Shows or hides an element.
938
+ #
939
+ # elem:: the element to show/hide
940
+ # visible:: if +true+ (default), show element, otherwise hide it
941
+ #
942
+
943
+ def self.setVisible(elem, visible=true)
944
+ if visible
945
+ `#<elem>.style.display = ''`
946
+ else
947
+ `#<elem>.style.display = 'none'`
948
+ end
949
+ return nil
950
+ end
951
+
952
+ #
953
+ # Changes a DOM element's positioning to static.
954
+ #
955
+ # elem:: the DOM element
956
+ #
957
+ def self.changeToStaticPositioning(elem)
958
+ setStyleAttribute(elem, "left", "");
959
+ setStyleAttribute(elem, "top", "");
960
+ setStyleAttribute(elem, "position", "static");
961
+ end
962
+
963
+ #
964
+ # TODO: write documentation
965
+ #
966
+ def self.setAbsolutePixelPosition(elem, left, top)
967
+ setStyleAttribute(elem, "position", "absolute");
968
+ setStyleAttribute(elem, "left", left + "px");
969
+ setStyleAttribute(elem, "top", top + "px");
970
+ end
971
+
972
+ #
973
+ # Gets the height of the browser window's client area excluding the
974
+ # scroll bar.
975
+ #
976
+ # return:: the window's client height
977
+ #
978
+ def self.windowGetClientHeight
979
+ `return document.body.clientHeight`
980
+ end
981
+
982
+ #
983
+ # Gets the width of the browser window's client area excluding the
984
+ # vertical scroll bar.
985
+ #
986
+ # return:: the window's client width
987
+ #
988
+ def self.windowGetClientWidth
989
+ `return document.body.clientWidth`
990
+ end
991
+
992
+ #
993
+ # Scrolls the given element into view.
994
+ #
995
+ # This method crawls up the DOM hierarchy, adjusting the scrollLeft and
996
+ # scrollTop properties of each scrollable element to ensure that the
997
+ # specified element is completely in view. It adjusts each scroll position by
998
+ # the minimum amount necessary.
999
+ #
1000
+ # elem:: the element to be made visible
1001
+ #
1002
+ def self.scrollIntoView(elem) `
1003
+ var left = #<elem>.offsetLeft, top = #<elem>.offsetTop;
1004
+ var width = #<elem>.offsetWidth, height = #<elem>.offsetHeight;
1005
+
1006
+ if (#<elem>.parentNode != #<elem>.offsetParent) {
1007
+ left -= #<elem>.parentNode.offsetLeft;
1008
+ top -= #<elem>.parentNode.offsetTop;
1009
+ }
1010
+
1011
+ var cur = #<elem>.parentNode;
1012
+ while (cur && (cur.nodeType == 1)) {
1013
+ // body tags are implicitly scrollable
1014
+ if ((cur.style.overflow == 'auto') || (cur.style.overflow == 'scroll') ||
1015
+ (cur.tagName == 'BODY')) {
1016
+
1017
+ if (left < cur.scrollLeft) {
1018
+ cur.scrollLeft = left;
1019
+ }
1020
+ if (left + width > cur.scrollLeft + cur.clientWidth) {
1021
+ cur.scrollLeft = (left + width) - cur.clientWidth;
1022
+ }
1023
+ if (top < cur.scrollTop) {
1024
+ cur.scrollTop = top;
1025
+ }
1026
+ if (top + height > cur.scrollTop + cur.clientHeight) {
1027
+ cur.scrollTop = (top + height) - cur.clientHeight;
1028
+ }
1029
+ }
1030
+
1031
+ var offsetLeft = cur.offsetLeft, offsetTop = cur.offsetTop;
1032
+ if (cur.parentNode != cur.offsetParent) {
1033
+ offsetLeft -= cur.parentNode.offsetLeft;
1034
+ offsetTop -= cur.parentNode.offsetTop;
1035
+ }
1036
+
1037
+ left += offsetLeft - cur.scrollLeft;
1038
+ top += offsetTop - cur.scrollTop;
1039
+ cur = cur.parentNode;
1040
+ }
1041
+ return #<nil>`
1042
+ end
1043
+
1044
+ end