superchris-rubyjs 0.8.2

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