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.
- data/README +131 -0
- data/Rakefile +65 -0
- data/bin/rubyjs +144 -0
- data/rubyjs.gemspec +112 -0
- data/src/rubyjs.rb +3 -0
- data/src/rubyjs/code_generator.rb +474 -0
- data/src/rubyjs/compiler.rb +2061 -0
- data/src/rubyjs/debug_name_generator.rb +95 -0
- data/src/rubyjs/encoder.rb +171 -0
- data/src/rubyjs/eval_into.rb +59 -0
- data/src/rubyjs/lib/core.rb +1016 -0
- data/src/rubyjs/lib/dom_element.rb +66 -0
- data/src/rubyjs/lib/json.rb +101 -0
- data/src/rubyjs/lib/microunit.rb +188 -0
- data/src/rubyjs/model.rb +293 -0
- data/src/rubyjs/name_generator.rb +71 -0
- data/src/rwt/AbsolutePanel.rb +161 -0
- data/src/rwt/DOM.Konqueror.rb +89 -0
- data/src/rwt/DOM.Opera.rb +65 -0
- data/src/rwt/DOM.rb +1044 -0
- data/src/rwt/Event.Opera.rb +35 -0
- data/src/rwt/Event.rb +429 -0
- data/src/rwt/HTTPRequest.IE6.rb +5 -0
- data/src/rwt/HTTPRequest.rb +74 -0
- data/src/rwt/Label.rb +164 -0
- data/src/rwt/Panel.rb +90 -0
- data/src/rwt/RootPanel.rb +16 -0
- data/src/rwt/UIObject.rb +495 -0
- data/src/rwt/Widget.rb +193 -0
- data/src/rwt/ported-from/AbsolutePanel.java +158 -0
- data/src/rwt/ported-from/DOM.java +571 -0
- data/src/rwt/ported-from/DOMImpl.java +426 -0
- data/src/rwt/ported-from/DOMImplOpera.java +82 -0
- data/src/rwt/ported-from/DOMImplStandard.java +234 -0
- data/src/rwt/ported-from/HTTPRequest.java +81 -0
- data/src/rwt/ported-from/HTTPRequestImpl.java +103 -0
- data/src/rwt/ported-from/Label.java +163 -0
- data/src/rwt/ported-from/Panel.java +99 -0
- data/src/rwt/ported-from/UIObject.java +614 -0
- data/src/rwt/ported-from/Widget.java +221 -0
- data/test/benchmark/bm_vm1_block.rb +15 -0
- data/test/benchmark/bm_vm1_const.rb +13 -0
- data/test/benchmark/bm_vm1_ensure.rb +15 -0
- data/test/benchmark/common.rb +5 -0
- data/test/benchmark/params.yaml +7 -0
- data/test/common.Browser.rb +13 -0
- data/test/common.rb +8 -0
- data/test/gen_browser_test_suite.rb +129 -0
- data/test/gen_test_suite.rb +41 -0
- data/test/run_benchs.rb +58 -0
- data/test/run_tests.rb +22 -0
- data/test/test_args.rb +24 -0
- data/test/test_array.rb +22 -0
- data/test/test_case.rb +35 -0
- data/test/test_class.rb +55 -0
- data/test/test_eql.rb +9 -0
- data/test/test_exception.rb +61 -0
- data/test/test_expr.rb +12 -0
- data/test/test_hash.rb +29 -0
- data/test/test_hot_ruby.rb +146 -0
- data/test/test_if.rb +28 -0
- data/test/test_insertion_sort.rb +25 -0
- data/test/test_inspect.rb +10 -0
- data/test/test_lebewesen.rb +39 -0
- data/test/test_massign.rb +66 -0
- data/test/test_new.rb +12 -0
- data/test/test_range.rb +70 -0
- data/test/test_regexp.rb +22 -0
- data/test/test_send.rb +65 -0
- data/test/test_simple_output.rb +5 -0
- data/test/test_splat.rb +21 -0
- data/test/test_string.rb +51 -0
- data/test/test_test.rb +17 -0
- data/test/test_yield.rb +154 -0
- data/utils/js/Makefile +9 -0
- data/utils/js/RunScript.class +0 -0
- data/utils/js/RunScript.java +73 -0
- data/utils/js/js.jar +0 -0
- data/utils/js/run.sh +3 -0
- data/utils/jsc/Makefile +7 -0
- data/utils/jsc/README +3 -0
- data/utils/jsc/RunScript.c +93 -0
- data/utils/jsc/run.sh +15 -0
- data/utils/yuicompressor/README +1 -0
- data/utils/yuicompressor/yuicompressor-2.2.5.jar +0 -0
- 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
|
data/src/rwt/DOM.rb
ADDED
@@ -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
|