wee 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +96 -0
- data/README +2 -5
- data/examples/ObjectSpaceBrowser.rb +24 -42
- data/examples/ajax/ajax.js +444 -0
- data/examples/ajax/ajax.rb +31 -0
- data/examples/calculator.rb +1 -3
- data/examples/cc.rb +9 -29
- data/examples/live-update.rb +1 -1
- data/examples/test.rb +2 -2
- data/examples/window.rb +1 -1
- data/lib/wee.rb +1 -1
- data/lib/wee/abstractsession.rb +96 -0
- data/lib/wee/adaptors/fastcgi.rb +76 -0
- data/lib/wee/adaptors/webrick.rb +3 -3
- data/lib/wee/application.rb +7 -4
- data/lib/wee/core/callback.rb +2 -0
- data/lib/wee/core/component.rb +46 -24
- data/lib/wee/core/decoration.rb +5 -5
- data/lib/wee/core/presenter.rb +43 -27
- data/lib/wee/core/valueholder.rb +1 -1
- data/lib/wee/databases/og/scaffolder.rb +0 -1
- data/lib/wee/pageless/application.rb +8 -4
- data/lib/wee/pageless/request.rb +17 -5
- data/lib/wee/pageless/session.rb +38 -52
- data/lib/wee/renderer/html/brushes.rb +7 -1
- data/lib/wee/renderer/html/canvas.rb +1 -1
- data/lib/wee/request.rb +68 -7
- data/lib/wee/response.rb +2 -1
- data/lib/wee/session.rb +128 -129
- data/test/test_request.rb +31 -3
- metadata +30 -25
data/ChangeLog
CHANGED
@@ -1,3 +1,99 @@
|
|
1
|
+
Mon Apr 4 18:45:28 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
2
|
+
|
3
|
+
* examples/ajax/ajax.rb, examples/ajax/ajax.js,
|
4
|
+
lib/wee/core/presenter.rb, lib/wee/renderer/html/brushes.rb: Added minimal
|
5
|
+
Ajax update support.
|
6
|
+
|
7
|
+
Mon Apr 4 14:32:34 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
8
|
+
|
9
|
+
* lib/wee/abstractsession.rb, lib/wee/session.rb,
|
10
|
+
lib/wee/pageless/session.rb, examples/live-update.rb: refactored
|
11
|
+
Session classes.
|
12
|
+
|
13
|
+
* lib/wee/core/presenter.rb: added send_response method, to send a
|
14
|
+
premature response.
|
15
|
+
|
16
|
+
Mon Apr 4 13:03:08 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
17
|
+
|
18
|
+
* lib/wee/pageless/session.rb, lib/wee/pageless/application.rb: Remove
|
19
|
+
dependency of WEBrick::Cookie, use CGI::Cookie instead.
|
20
|
+
|
21
|
+
* lib/wee/adaptors/fastcgi.rb: Added preliminary FastCGI adaptor
|
22
|
+
(does not work yet with Pageless applications).
|
23
|
+
|
24
|
+
* lib/wee/adaptors/webrick.rb: reordered line
|
25
|
+
|
26
|
+
Sun Apr 3 13:24:04 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
27
|
+
|
28
|
+
* lib/wee/adaptors/webrick.rb: doc fix
|
29
|
+
|
30
|
+
Sun Apr 3 13:11:07 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
31
|
+
|
32
|
+
* lib/wee/core/presenter.rb, lib/wee/core/component.rb,
|
33
|
+
lib/wee/core/decoration.rb, lib/wee/session.rb,
|
34
|
+
lib/wee/pageless/session.rb, examples/window.rb, README:
|
35
|
+
Fixed a bug in processing the callbacks. It was not guaranteed that
|
36
|
+
all input callbacks are invoked before the final action callback.
|
37
|
+
This is now guaranteed! I've introduced two separate tree traversals
|
38
|
+
of process_callbacks to make this work. As a side effect, this also
|
39
|
+
has removed the dependency of Presenter/Component/Decoration classes
|
40
|
+
from the CallbackStream class. Instead of a CallbackStream, a code
|
41
|
+
block is now passed through the
|
42
|
+
process_callbacks/process_callbacks_chain traversal. The Session
|
43
|
+
class specifies how to invoke the callbacks.
|
44
|
+
|
45
|
+
Thu Mar 3 12:31:15 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
46
|
+
|
47
|
+
* wee/session.rb, wee/pageless/session.rb: new methods
|
48
|
+
pre_respond_hook, post_callbacks_hook, especially to make pretty-URLs
|
49
|
+
as suggested by Joao Pedrosa working.
|
50
|
+
|
51
|
+
Thu Mar 3 12:11:05 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
52
|
+
|
53
|
+
* wee/response.rb (Wee::Response): Use the passed mime_type as
|
54
|
+
content-type (bug fix).
|
55
|
+
|
56
|
+
* wee/request.rb: Made 'info' attribute writeable.
|
57
|
+
|
58
|
+
* wee/core/callback.rb: Added reader method for 'obj'
|
59
|
+
|
60
|
+
* wee/core/component.rb: Added #parent method, to retrieve the parent
|
61
|
+
component from a child if existent. The parent attribute will be set
|
62
|
+
during #add_child.
|
63
|
+
|
64
|
+
Thu Mar 3 11:38:21 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
65
|
+
|
66
|
+
* wee/application.rb, wee/pageless/application.rb
|
67
|
+
(request_handler_expired): Forward to an URL that includes the info
|
68
|
+
part but neither the request_handler_id nor the page_id.
|
69
|
+
|
70
|
+
Sat Feb 26 17:12:35 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
71
|
+
|
72
|
+
* wee/request.rb, test/test_request.rb, wee/pageless/request.rb,
|
73
|
+
wee/session.rb, wee/pageless/session.rb,
|
74
|
+
wee/renderer/html/canvas.rb, wee/renderer/html/brushes.rb:
|
75
|
+
|
76
|
+
- request delimeter changed to /___/ (looks nicer)
|
77
|
+
|
78
|
+
- refactored Request#build_url, which now takes a hash and
|
79
|
+
remembers already specified values
|
80
|
+
|
81
|
+
- A Request knows now itself whether it's a action or a render
|
82
|
+
request.
|
83
|
+
|
84
|
+
- added Request#info attribute. This is a part of the URL that you
|
85
|
+
can use for your own purposes. It is remembered across requests
|
86
|
+
unless you overwrite its value.
|
87
|
+
|
88
|
+
Sat Feb 26 14:22:34 CET 2005 Michael Neumann <mneumann@ntecs.de>
|
89
|
+
|
90
|
+
* wee/core/presenter.rb, wee/session.rb, wee/application.rb: renamed @properties to @__properties
|
91
|
+
|
92
|
+
* wee/core/component.rb: rename @children to @__children
|
93
|
+
|
94
|
+
* wee/core/component.rb, wee/core/valueholder.rb: rename @decoration
|
95
|
+
to @__decoration
|
96
|
+
|
1
97
|
--------------------------------------------------------------------
|
2
98
|
TAGGED 0.7.0
|
3
99
|
--------------------------------------------------------------------
|
data/README
CHANGED
@@ -237,11 +237,8 @@ called for the component itself. As such, <i>process_callbacks_chain</i>
|
|
237
237
|
is important to avoid entering an infinite loop (a method calling itself). What
|
238
238
|
decorations are, is discussed elsewhere.
|
239
239
|
|
240
|
-
|
241
|
-
callbacks
|
242
|
-
<i>process_callbacks_chain</i> for all of it's child components. This ensures,
|
243
|
-
that all input callbacks are triggered before the first action callback is
|
244
|
-
run. Finally, it invokes all of it's action callbacks.
|
240
|
+
There are two "process_callbacks" tree traversals. The first invokes all input
|
241
|
+
callbacks, the second the action callback.
|
245
242
|
|
246
243
|
=== Rendering Phase
|
247
244
|
|
@@ -1,9 +1,8 @@
|
|
1
1
|
$LOAD_PATH.unshift << "../lib"
|
2
2
|
require 'wee'
|
3
|
-
require 'wee/webrick'
|
4
|
-
require 'wee/utils
|
3
|
+
require 'wee/adaptors/webrick'
|
4
|
+
require 'wee/utils'
|
5
5
|
require 'cgi'
|
6
|
-
|
7
6
|
require 'enumerator'
|
8
7
|
|
9
8
|
module ObjectSpaceBrowser
|
@@ -15,7 +14,7 @@ module ObjectSpaceBrowser
|
|
15
14
|
end
|
16
15
|
|
17
16
|
def choose(klass)
|
18
|
-
call
|
17
|
+
call Klass.new(klass)
|
19
18
|
end
|
20
19
|
|
21
20
|
def render
|
@@ -23,7 +22,7 @@ module ObjectSpaceBrowser
|
|
23
22
|
|
24
23
|
r.ul {
|
25
24
|
klasses.each do |klass|
|
26
|
-
r.li { r.anchor.
|
25
|
+
r.li { r.anchor.callback(:choose, klass).with(klass.name) }
|
27
26
|
end
|
28
27
|
}
|
29
28
|
end
|
@@ -63,7 +62,7 @@ module ObjectSpaceBrowser
|
|
63
62
|
|
64
63
|
r.ul {
|
65
64
|
@instances.each do |instance|
|
66
|
-
r.li { r.anchor.
|
65
|
+
r.li { r.anchor.callback(:choose, instance).with("0x%x" % instance.object_id) }
|
67
66
|
end
|
68
67
|
}
|
69
68
|
end
|
@@ -86,7 +85,7 @@ module ObjectSpaceBrowser
|
|
86
85
|
end
|
87
86
|
|
88
87
|
def render
|
89
|
-
r.anchor.
|
88
|
+
r.anchor.callback(:back).with("back")
|
90
89
|
|
91
90
|
r.break
|
92
91
|
r.h1 "Instance 0x%x of #{@instance.class.name}" % @instance.object_id
|
@@ -97,7 +96,7 @@ module ObjectSpaceBrowser
|
|
97
96
|
r.break
|
98
97
|
r.ul do
|
99
98
|
@instance.each do |obj|
|
100
|
-
r.li { render_obj(obj
|
99
|
+
r.li { render_obj(obj) }
|
101
100
|
end
|
102
101
|
end
|
103
102
|
when Hash
|
@@ -111,8 +110,8 @@ module ObjectSpaceBrowser
|
|
111
110
|
|
112
111
|
@instance.each_pair do |k, v|
|
113
112
|
r.table_row do
|
114
|
-
r.table_data { render_obj(k
|
115
|
-
r.table_data { render_obj(v
|
113
|
+
r.table_data { render_obj(k) }
|
114
|
+
r.table_data { render_obj(v) }
|
116
115
|
end
|
117
116
|
end
|
118
117
|
end
|
@@ -124,31 +123,31 @@ module ObjectSpaceBrowser
|
|
124
123
|
return if @instance.instance_variables.empty?
|
125
124
|
r.break
|
126
125
|
|
127
|
-
render_instance_variables
|
126
|
+
render_instance_variables
|
128
127
|
end
|
129
128
|
|
130
|
-
def render_instance_variables
|
129
|
+
def render_instance_variables
|
131
130
|
r.table.border(1).with do
|
132
131
|
r.table_row do
|
133
132
|
r.table_data do r.bold("Instance Variable") end
|
134
133
|
r.table_data do r.bold("Object") end
|
135
134
|
end
|
136
|
-
@instance.instance_variables.each do |var| render_ivar_row(var
|
135
|
+
@instance.instance_variables.each do |var| render_ivar_row(var) end
|
137
136
|
end
|
138
137
|
end
|
139
138
|
|
140
|
-
def render_ivar_row(var
|
139
|
+
def render_ivar_row(var)
|
141
140
|
r.table_row do
|
142
141
|
r.table_data(var)
|
143
142
|
r.table_data do
|
144
143
|
v = @instance.instance_variable_get(var)
|
145
|
-
render_obj(v
|
144
|
+
render_obj(v)
|
146
145
|
end
|
147
146
|
end
|
148
147
|
end
|
149
148
|
|
150
|
-
def render_obj(obj
|
151
|
-
r.anchor.
|
149
|
+
def render_obj(obj)
|
150
|
+
r.anchor.callback(:choose, obj).with do
|
152
151
|
r.bold(obj.class.name)
|
153
152
|
r.space
|
154
153
|
r.text("(#{ obj.object_id })")
|
@@ -170,30 +169,13 @@ end # module ObjectSpaceBrowser
|
|
170
169
|
|
171
170
|
if $0 == __FILE__ then
|
172
171
|
|
173
|
-
OBJ = {
|
174
|
-
|
175
|
-
|
176
|
-
}
|
177
|
-
|
178
|
-
class MySession < Wee::Session
|
179
|
-
def initialize
|
180
|
-
super do
|
181
|
-
self.root_component = ObjectSpaceBrowser::Instance.new(OBJ)
|
182
|
-
self.page_store = Wee::Utils::LRUCache.new(10) # backtrack up to 10 pages
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
class MyApplication < Wee::Application
|
188
|
-
def shutdown
|
189
|
-
end
|
190
|
-
end
|
172
|
+
OBJ = {
|
173
|
+
"hello" => { [1,2,3] => [5,6,7], "test" => :super },
|
174
|
+
"other" => %w(a b c d e f)
|
175
|
+
}
|
191
176
|
|
192
|
-
Wee::
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
app.session_store = Wee::Utils::LRUCache.new(10)
|
197
|
-
app.dumpfile = ''
|
198
|
-
}.start
|
177
|
+
app = Wee::Utils.app_for {
|
178
|
+
ObjectSpaceBrowser::Instance.new(OBJ)
|
179
|
+
}
|
180
|
+
Wee::WEBrickAdaptor.register('/ob' => app).start
|
199
181
|
end
|
@@ -0,0 +1,444 @@
|
|
1
|
+
/* Prototype: an object-oriented Javascript library, version 1.1.0
|
2
|
+
* (c) 2005 Sam Stephenson <sam@conio.net>
|
3
|
+
*
|
4
|
+
* Prototype is freely distributable under the terms of an MIT-style license.
|
5
|
+
* For details, see http://prototype.conio.net/
|
6
|
+
*
|
7
|
+
* Changes by Michael Neumann.
|
8
|
+
*/
|
9
|
+
|
10
|
+
var Prototype = {
|
11
|
+
Version: '1.1.0'
|
12
|
+
}
|
13
|
+
|
14
|
+
var Class = {
|
15
|
+
create: function() {
|
16
|
+
return function() {
|
17
|
+
this.initialize.apply(this, arguments);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
var Abstract = new Object();
|
23
|
+
|
24
|
+
Object.prototype.extend = function(object) {
|
25
|
+
for (property in object) {
|
26
|
+
this[property] = object[property];
|
27
|
+
}
|
28
|
+
return this;
|
29
|
+
}
|
30
|
+
|
31
|
+
Function.prototype.bind = function(object) {
|
32
|
+
var method = this;
|
33
|
+
return function() {
|
34
|
+
method.apply(object, arguments);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
Function.prototype.bindAsEventListener = function(object) {
|
39
|
+
var method = this;
|
40
|
+
return function(event) {
|
41
|
+
method.call(object, event || window.event);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
Number.prototype.toColorPart = function() {
|
46
|
+
var digits = this.toString(16);
|
47
|
+
if (this < 16) return '0' + digits;
|
48
|
+
return digits;
|
49
|
+
}
|
50
|
+
|
51
|
+
var Try = {
|
52
|
+
these: function() {
|
53
|
+
var returnValue;
|
54
|
+
|
55
|
+
for (var i = 0; i < arguments.length; i++) {
|
56
|
+
var lambda = arguments[i];
|
57
|
+
try {
|
58
|
+
returnValue = lambda();
|
59
|
+
break;
|
60
|
+
} catch (e) {}
|
61
|
+
}
|
62
|
+
|
63
|
+
return returnValue;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
var Toggle = {
|
68
|
+
display: function() {
|
69
|
+
for (var i = 0; i < arguments.length; i++) {
|
70
|
+
var element = $(arguments[i]);
|
71
|
+
element.style.display =
|
72
|
+
(element.style.display == 'none' ? '' : 'none');
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
/*--------------------------------------------------------------------------*/
|
78
|
+
|
79
|
+
function $() {
|
80
|
+
var elements = new Array();
|
81
|
+
|
82
|
+
for (var i = 0; i < arguments.length; i++) {
|
83
|
+
var element = arguments[i];
|
84
|
+
if (typeof element == 'string')
|
85
|
+
element = document.getElementById(element);
|
86
|
+
|
87
|
+
if (arguments.length == 1)
|
88
|
+
return element;
|
89
|
+
|
90
|
+
elements.push(element);
|
91
|
+
}
|
92
|
+
|
93
|
+
return elements;
|
94
|
+
}
|
95
|
+
|
96
|
+
function getElementsByClassName(className) {
|
97
|
+
var children = document.getElementsByTagName('*') || document.all;
|
98
|
+
var elements = new Array();
|
99
|
+
|
100
|
+
for (var i = 0; i < children.length; i++) {
|
101
|
+
var child = children[i];
|
102
|
+
var classNames = child.className.split(' ');
|
103
|
+
for (var j = 0; j < classNames.length; j++) {
|
104
|
+
if (classNames[j] == className) {
|
105
|
+
elements.push(child);
|
106
|
+
break;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
return elements;
|
112
|
+
}
|
113
|
+
var Ajax = {
|
114
|
+
getTransport: function() {
|
115
|
+
return Try.these(
|
116
|
+
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
|
117
|
+
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
|
118
|
+
function() {return new XMLHttpRequest()}
|
119
|
+
) || false;
|
120
|
+
},
|
121
|
+
|
122
|
+
emptyFunction: function() {}
|
123
|
+
}
|
124
|
+
|
125
|
+
Ajax.Base = function() {};
|
126
|
+
Ajax.Base.prototype = {
|
127
|
+
setOptions: function(options) {
|
128
|
+
this.options = {
|
129
|
+
method: 'post',
|
130
|
+
asynchronous: true,
|
131
|
+
parameters: ''
|
132
|
+
}.extend(options || {});
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
Ajax.Request = Class.create();
|
137
|
+
Ajax.Request.Events =
|
138
|
+
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
|
139
|
+
|
140
|
+
Ajax.Request.prototype = (new Ajax.Base()).extend({
|
141
|
+
initialize: function(url, options) {
|
142
|
+
this.transport = Ajax.getTransport();
|
143
|
+
this.setOptions(options);
|
144
|
+
|
145
|
+
try {
|
146
|
+
/*if (this.options.method == 'get')
|
147
|
+
url += '?' + this.options.parameters; */
|
148
|
+
|
149
|
+
this.transport.open(this.options.method, url, true);
|
150
|
+
|
151
|
+
if (this.options.asynchronous) {
|
152
|
+
this.transport.onreadystatechange = this.onStateChange.bind(this);
|
153
|
+
setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
|
154
|
+
}
|
155
|
+
|
156
|
+
if (this.options.method == 'post') {
|
157
|
+
this.transport.setRequestHeader('Connection', 'close');
|
158
|
+
this.transport.setRequestHeader('Content-type',
|
159
|
+
'application/x-www-form-urlencoded');
|
160
|
+
}
|
161
|
+
|
162
|
+
this.transport.send(this.options.method == 'post' ?
|
163
|
+
this.options.parameters : null);
|
164
|
+
|
165
|
+
} catch (e) {
|
166
|
+
}
|
167
|
+
},
|
168
|
+
|
169
|
+
onStateChange: function() {
|
170
|
+
var readyState = this.transport.readyState;
|
171
|
+
if (readyState != 1)
|
172
|
+
this.respondToReadyState(this.transport.readyState);
|
173
|
+
},
|
174
|
+
|
175
|
+
respondToReadyState: function(readyState) {
|
176
|
+
var event = Ajax.Request.Events[readyState];
|
177
|
+
(this.options['on' + event] || Ajax.emptyFunction)(this.transport);
|
178
|
+
}
|
179
|
+
});
|
180
|
+
|
181
|
+
Ajax.Updater = Class.create();
|
182
|
+
Ajax.Updater.prototype = (new Ajax.Base()).extend({
|
183
|
+
initialize: function(container, url, options) {
|
184
|
+
this.container = $(container);
|
185
|
+
this.setOptions(options);
|
186
|
+
|
187
|
+
if (this.options.asynchronous) {
|
188
|
+
this.onComplete = this.options.onComplete;
|
189
|
+
this.options.onComplete = this.updateContent.bind(this);
|
190
|
+
}
|
191
|
+
|
192
|
+
this.request = new Ajax.Request(url, this.options);
|
193
|
+
|
194
|
+
if (!this.options.asynchronous)
|
195
|
+
this.updateContent();
|
196
|
+
},
|
197
|
+
|
198
|
+
updateContent: function() {
|
199
|
+
if (this.options.insertion) {
|
200
|
+
new this.options.insertion(this.container,
|
201
|
+
this.request.transport.responseText);
|
202
|
+
} else {
|
203
|
+
this.container.innerHTML = this.request.transport.responseText;
|
204
|
+
}
|
205
|
+
|
206
|
+
if (this.onComplete) {
|
207
|
+
setTimeout((function() {this.onComplete(this.request)}).bind(this), 10);
|
208
|
+
}
|
209
|
+
}
|
210
|
+
});
|
211
|
+
var Field = {
|
212
|
+
clear: function() {
|
213
|
+
for (var i = 0; i < arguments.length; i++)
|
214
|
+
$(arguments[i]).value = '';
|
215
|
+
},
|
216
|
+
|
217
|
+
focus: function(element) {
|
218
|
+
$(element).focus();
|
219
|
+
},
|
220
|
+
|
221
|
+
present: function() {
|
222
|
+
for (var i = 0; i < arguments.length; i++)
|
223
|
+
if ($(arguments[i]).value == '') return false;
|
224
|
+
return true;
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
/*--------------------------------------------------------------------------*/
|
229
|
+
|
230
|
+
var Form = {
|
231
|
+
serialize: function(form) {
|
232
|
+
var elements = Form.getElements($(form));
|
233
|
+
var queryComponents = new Array();
|
234
|
+
|
235
|
+
for (var i = 0; i < elements.length; i++) {
|
236
|
+
var queryComponent = Form.Element.serialize(elements[i]);
|
237
|
+
if (queryComponent)
|
238
|
+
queryComponents.push(queryComponent);
|
239
|
+
}
|
240
|
+
|
241
|
+
return queryComponents.join('&');
|
242
|
+
},
|
243
|
+
|
244
|
+
getElements: function(form) {
|
245
|
+
form = $(form);
|
246
|
+
var elements = new Array();
|
247
|
+
|
248
|
+
for (tagName in Form.Element.Serializers) {
|
249
|
+
var tagElements = form.getElementsByTagName(tagName);
|
250
|
+
for (var j = 0; j < tagElements.length; j++)
|
251
|
+
elements.push(tagElements[j]);
|
252
|
+
}
|
253
|
+
return elements;
|
254
|
+
}
|
255
|
+
}
|
256
|
+
|
257
|
+
Form.Element = {
|
258
|
+
serialize: function(element) {
|
259
|
+
element = $(element);
|
260
|
+
var method = element.tagName.toLowerCase();
|
261
|
+
var parameter = Form.Element.Serializers[method](element);
|
262
|
+
|
263
|
+
if (parameter)
|
264
|
+
return encodeURIComponent(parameter[0]) + '=' +
|
265
|
+
encodeURIComponent(parameter[1]);
|
266
|
+
},
|
267
|
+
|
268
|
+
getValue: function(element) {
|
269
|
+
element = $(element);
|
270
|
+
var method = element.tagName.toLowerCase();
|
271
|
+
var parameter = Form.Element.Serializers[method](element);
|
272
|
+
|
273
|
+
if (parameter)
|
274
|
+
return parameter[1];
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
Form.Element.Serializers = {
|
279
|
+
input: function(element) {
|
280
|
+
switch (element.type.toLowerCase()) {
|
281
|
+
case 'hidden':
|
282
|
+
case 'password':
|
283
|
+
case 'text':
|
284
|
+
return Form.Element.Serializers.textarea(element);
|
285
|
+
case 'checkbox':
|
286
|
+
case 'radio':
|
287
|
+
return Form.Element.Serializers.inputSelector(element);
|
288
|
+
}
|
289
|
+
return false;
|
290
|
+
},
|
291
|
+
|
292
|
+
inputSelector: function(element) {
|
293
|
+
if (element.checked)
|
294
|
+
return [element.name, element.value];
|
295
|
+
},
|
296
|
+
|
297
|
+
textarea: function(element) {
|
298
|
+
return [element.name, element.value];
|
299
|
+
},
|
300
|
+
|
301
|
+
select: function(element) {
|
302
|
+
var index = element.selectedIndex;
|
303
|
+
return [element.name, (index >= 0) ? element.options[index].value : ''];
|
304
|
+
}
|
305
|
+
}
|
306
|
+
|
307
|
+
/*--------------------------------------------------------------------------*/
|
308
|
+
|
309
|
+
Abstract.TimedObserver = function() {}
|
310
|
+
Abstract.TimedObserver.prototype = {
|
311
|
+
initialize: function(element, frequency, callback) {
|
312
|
+
this.frequency = frequency;
|
313
|
+
this.element = $(element);
|
314
|
+
this.callback = callback;
|
315
|
+
|
316
|
+
this.lastValue = this.getValue();
|
317
|
+
this.registerCallback();
|
318
|
+
},
|
319
|
+
|
320
|
+
registerCallback: function() {
|
321
|
+
setTimeout(this.onTimerEvent.bind(this), this.frequency * 1000);
|
322
|
+
},
|
323
|
+
|
324
|
+
onTimerEvent: function() {
|
325
|
+
var value = this.getValue();
|
326
|
+
if (this.lastValue != value) {
|
327
|
+
this.callback(this.element, value);
|
328
|
+
this.lastValue = value;
|
329
|
+
}
|
330
|
+
|
331
|
+
this.registerCallback();
|
332
|
+
}
|
333
|
+
}
|
334
|
+
|
335
|
+
Form.Element.Observer = Class.create();
|
336
|
+
Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
|
337
|
+
getValue: function() {
|
338
|
+
return Form.Element.getValue(this.element);
|
339
|
+
}
|
340
|
+
});
|
341
|
+
|
342
|
+
Form.Observer = Class.create();
|
343
|
+
Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
|
344
|
+
getValue: function() {
|
345
|
+
return Form.serialize(this.element);
|
346
|
+
}
|
347
|
+
});
|
348
|
+
|
349
|
+
Abstract.Insertion = function(adjacency) {
|
350
|
+
this.adjacency = adjacency;
|
351
|
+
}
|
352
|
+
|
353
|
+
Abstract.Insertion.prototype = {
|
354
|
+
initialize: function(element, content) {
|
355
|
+
this.element = $(element);
|
356
|
+
this.content = content;
|
357
|
+
|
358
|
+
if (this.adjacency && this.element.insertAdjacentHTML) {
|
359
|
+
this.element.insertAdjacentHTML(this.adjacency, this.content);
|
360
|
+
} else {
|
361
|
+
this.range = this.element.ownerDocument.createRange();
|
362
|
+
if (this.initializeRange) this.initializeRange();
|
363
|
+
this.fragment = this.range.createContextualFragment(this.content);
|
364
|
+
this.insertContent();
|
365
|
+
}
|
366
|
+
}
|
367
|
+
}
|
368
|
+
|
369
|
+
var Insertion = new Object();
|
370
|
+
|
371
|
+
Insertion.Before = Class.create();
|
372
|
+
Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
|
373
|
+
initializeRange: function() {
|
374
|
+
this.range.setStartBefore(this.element);
|
375
|
+
},
|
376
|
+
|
377
|
+
insertContent: function() {
|
378
|
+
this.element.parentNode.insertBefore(this.fragment, this.element);
|
379
|
+
}
|
380
|
+
});
|
381
|
+
|
382
|
+
Insertion.Top = Class.create();
|
383
|
+
Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
|
384
|
+
initializeRange: function() {
|
385
|
+
this.range.selectNodeContents(this.element);
|
386
|
+
this.range.collapse(true);
|
387
|
+
},
|
388
|
+
|
389
|
+
insertContent: function() {
|
390
|
+
this.element.insertBefore(this.fragment, this.element.firstChild);
|
391
|
+
}
|
392
|
+
});
|
393
|
+
|
394
|
+
Insertion.Bottom = Class.create();
|
395
|
+
Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
|
396
|
+
initializeRange: function() {
|
397
|
+
this.range.selectNodeContents(this.element);
|
398
|
+
this.range.collapse(this.element);
|
399
|
+
},
|
400
|
+
|
401
|
+
insertContent: function() {
|
402
|
+
this.element.appendChild(this.fragment);
|
403
|
+
}
|
404
|
+
});
|
405
|
+
|
406
|
+
Insertion.After = Class.create();
|
407
|
+
Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
|
408
|
+
initializeRange: function() {
|
409
|
+
this.range.setStartAfter(this.element);
|
410
|
+
},
|
411
|
+
|
412
|
+
insertContent: function() {
|
413
|
+
this.element.parentNode.insertBefore(this.fragment,
|
414
|
+
this.element.nextSibling);
|
415
|
+
}
|
416
|
+
});
|
417
|
+
var Effect = new Object();
|
418
|
+
|
419
|
+
Effect.Highlight = Class.create();
|
420
|
+
Effect.Highlight.prototype = {
|
421
|
+
initialize: function(element) {
|
422
|
+
this.element = $(element);
|
423
|
+
this.start = 153;
|
424
|
+
this.finish = 255;
|
425
|
+
this.current = this.start;
|
426
|
+
this.fade();
|
427
|
+
},
|
428
|
+
|
429
|
+
fade: function() {
|
430
|
+
if (this.isFinished()) return;
|
431
|
+
if (this.timer) clearTimeout(this.timer);
|
432
|
+
this.highlight(this.element, this.current);
|
433
|
+
this.current += 17;
|
434
|
+
this.timer = setTimeout(this.fade.bind(this), 250);
|
435
|
+
},
|
436
|
+
|
437
|
+
isFinished: function() {
|
438
|
+
return this.current > this.finish;
|
439
|
+
},
|
440
|
+
|
441
|
+
highlight: function(element, current) {
|
442
|
+
element.style.backgroundColor = "#ffff" + current.toColorPart();
|
443
|
+
}
|
444
|
+
}
|