wee 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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
- Method <i>process_callbacks</i> of class Component first invokes all input
241
- callbacks specified for this component, then calls
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/cache'
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(Klass.new(klass))
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.action(:choose, klass).with(klass.name) }
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.action(:choose, instance).with("0x%x" % instance.object_id) }
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.action(:back).with("back")
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, r) }
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, r) }
115
- r.table_data { render_obj(v, r) }
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(r)
126
+ render_instance_variables
128
127
  end
129
128
 
130
- def render_instance_variables(r)
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, r) end
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, r)
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, r)
144
+ render_obj(v)
146
145
  end
147
146
  end
148
147
  end
149
148
 
150
- def render_obj(obj, r)
151
- r.anchor.action(:choose, obj).with do
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
- "hello" => { [1,2,3] => [5,6,7], "test" => :super },
175
- "other" => %w(a b c d e f)
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::Application.new {|app|
193
- app.name = 'ObjectBrowser'
194
- app.path = '/ob'
195
- app.session_class = MySession
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
+ }