Project

General

Profile

« Previous | Next » 

Revision 2887

Added by anderson over 18 years ago

Adding review resources.

View differences:

prototype.js
1
/*  Prototype JavaScript framework, version 1.3.1
1
/*  Prototype JavaScript framework, version 1.4.0
2 2
 *  (c) 2005 Sam Stephenson <sam@conio.net>
3 3
 *
4 4
 *  THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
5
 *  against the source tree, available from the Prototype darcs repository. 
5
 *  against the source tree, available from the Prototype darcs repository.
6 6
 *
7 7
 *  Prototype is freely distributable under the terms of an MIT-style license.
8 8
 *
......
11 11
/*--------------------------------------------------------------------------*/
12 12

  
13 13
var Prototype = {
14
  Version: '1.3.1',
15
  emptyFunction: function() {}
14
  Version: '1.4.0',
15
  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
16

  
17
  emptyFunction: function() {},
18
  K: function(x) {return x}
16 19
}
17 20

  
18 21
var Class = {
19 22
  create: function() {
20
    return function() { 
23
    return function() {
21 24
      this.initialize.apply(this, arguments);
22 25
    }
23 26
  }
......
32 35
  return destination;
33 36
}
34 37

  
35
Object.prototype.extend = function(object) {
36
  return Object.extend.apply(this, [this, object]);
38
Object.inspect = function(object) {
39
  try {
40
    if (object == undefined) return 'undefined';
41
    if (object == null) return 'null';
42
    return object.inspect ? object.inspect() : object.toString();
43
  } catch (e) {
44
    if (e instanceof RangeError) return '...';
45
    throw e;
46
  }
37 47
}
38 48

  
39
Function.prototype.bind = function(object) {
40
  var __method = this;
49
Function.prototype.bind = function() {
50
  var __method = this, args = $A(arguments), object = args.shift();
41 51
  return function() {
42
    __method.apply(object, arguments);
52
    return __method.apply(object, args.concat($A(arguments)));
43 53
  }
44 54
}
45 55

  
46 56
Function.prototype.bindAsEventListener = function(object) {
47 57
  var __method = this;
48 58
  return function(event) {
49
    __method.call(object, event || window.event);
59
    return __method.call(object, event || window.event);
50 60
  }
51 61
}
52 62

  
53
Number.prototype.toColorPart = function() {
54
  var digits = this.toString(16);
55
  if (this < 16) return '0' + digits;
56
  return digits;
57
}
63
Object.extend(Number.prototype, {
64
  toColorPart: function() {
65
    var digits = this.toString(16);
66
    if (this < 16) return '0' + digits;
67
    return digits;
68
  },
58 69

  
70
  succ: function() {
71
    return this + 1;
72
  },
73

  
74
  times: function(iterator) {
75
    $R(0, this, true).each(iterator);
76
    return this;
77
  }
78
});
79

  
59 80
var Try = {
60 81
  these: function() {
61 82
    var returnValue;
......
90 111

  
91 112
  onTimerEvent: function() {
92 113
    if (!this.currentlyExecuting) {
93
      try { 
114
      try {
94 115
        this.currentlyExecuting = true;
95
        this.callback(); 
96
      } finally { 
116
        this.callback();
117
      } finally {
97 118
        this.currentlyExecuting = false;
98 119
      }
99 120
    }
......
110 131
    if (typeof element == 'string')
111 132
      element = document.getElementById(element);
112 133

  
113
    if (arguments.length == 1) 
134
    if (arguments.length == 1)
114 135
      return element;
115 136

  
116 137
    elements.push(element);
......
118 139

  
119 140
  return elements;
120 141
}
142
Object.extend(String.prototype, {
143
  stripTags: function() {
144
    return this.replace(/<\/?[^>]+>/gi, '');
145
  },
121 146

  
122
if (!Array.prototype.push) {
123
  Array.prototype.push = function() {
124
		var startLength = this.length;
125
		for (var i = 0; i < arguments.length; i++)
126
      this[startLength + i] = arguments[i];
127
	  return this.length;
128
  }
129
}
147
  stripScripts: function() {
148
    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
149
  },
130 150

  
131
if (!Function.prototype.apply) {
132
  // Based on code from http://www.youngpup.net/
133
  Function.prototype.apply = function(object, parameters) {
134
    var parameterStrings = new Array();
135
    if (!object)     object = window;
136
    if (!parameters) parameters = new Array();
137
    
138
    for (var i = 0; i < parameters.length; i++)
139
      parameterStrings[i] = 'parameters[' + i + ']';
140
    
141
    object.__apply__ = this;
142
    var result = eval('object.__apply__(' + 
143
      parameterStrings.join(', ') + ')');
144
    object.__apply__ = null;
145
    
146
    return result;
147
  }
148
}
151
  trim: function() {
152
    return(this.replace(/^\s+/,'').replace(/\s+$/,''));
153
  },
149 154

  
150
String.prototype.extend({
151
  stripTags: function() {
152
    return this.replace(/<\/?[^>]+>/gi, '');
155
  extractScripts: function() {
156
    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
157
    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
158
    return (this.match(matchAll) || []).map(function(scriptTag) {
159
      return (scriptTag.match(matchOne) || ['', ''])[1];
160
    });
153 161
  },
154 162

  
163
  evalScripts: function() {
164
    return this.extractScripts().map(eval);
165
  },
166

  
155 167
  escapeHTML: function() {
156 168
    var div = document.createElement('div');
157 169
    var text = document.createTextNode(this);
......
162 174
  unescapeHTML: function() {
163 175
    var div = document.createElement('div');
164 176
    div.innerHTML = this.stripTags();
165
    return div.childNodes[0].nodeValue;
177
    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
178
  },
179

  
180
  toQueryParams: function() {
181
    var pairs = this.match(/^\??(.*)$/)[1].split('&');
182
    return pairs.inject({}, function(params, pairString) {
183
      var pair = pairString.split('=');
184
      params[pair[0]] = pair[1];
185
      return params;
186
    });
187
  },
188

  
189
  toArray: function() {
190
    return this.split('');
191
  },
192

  
193
  camelize: function() {
194
    var oStringList = this.split('-');
195
    if (oStringList.length == 1) return oStringList[0];
196

  
197
    var camelizedString = this.indexOf('-') == 0
198
      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
199
      : oStringList[0];
200

  
201
    for (var i = 1, len = oStringList.length; i < len; i++) {
202
      var s = oStringList[i];
203
      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
204
    }
205

  
206
    return camelizedString;
207
  },
208

  
209
  inspect: function() {
210
    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
166 211
  }
167 212
});
168 213

  
214
String.prototype.parseQuery = String.prototype.toQueryParams;
215

  
216
var $break    = new Object();
217
var $continue = new Object();
218

  
219
var Enumerable = {
220
  each: function(iterator) {
221
    var index = 0;
222
    try {
223
      this._each(function(value) {
224
        try {
225
          iterator(value, index++);
226
        } catch (e) {
227
          if (e != $continue) throw e;
228
        }
229
      });
230
    } catch (e) {
231
      if (e != $break) throw e;
232
    }
233
  },
234

  
235
  all: function(iterator) {
236
    var result = true;
237
    this.each(function(value, index) {
238
      result = result && !!(iterator || Prototype.K)(value, index);
239
      if (!result) throw $break;
240
    });
241
    return result;
242
  },
243

  
244
  any: function(iterator) {
245
    var result = true;
246
    this.each(function(value, index) {
247
      if (result = !!(iterator || Prototype.K)(value, index))
248
        throw $break;
249
    });
250
    return result;
251
  },
252

  
253
  collect: function(iterator) {
254
    var results = [];
255
    this.each(function(value, index) {
256
      results.push(iterator(value, index));
257
    });
258
    return results;
259
  },
260

  
261
  detect: function (iterator) {
262
    var result;
263
    this.each(function(value, index) {
264
      if (iterator(value, index)) {
265
        result = value;
266
        throw $break;
267
      }
268
    });
269
    return result;
270
  },
271

  
272
  findAll: function(iterator) {
273
    var results = [];
274
    this.each(function(value, index) {
275
      if (iterator(value, index))
276
        results.push(value);
277
    });
278
    return results;
279
  },
280

  
281
  grep: function(pattern, iterator) {
282
    var results = [];
283
    this.each(function(value, index) {
284
      var stringValue = value.toString();
285
      if (stringValue.match(pattern))
286
        results.push((iterator || Prototype.K)(value, index));
287
    })
288
    return results;
289
  },
290

  
291
  include: function(object) {
292
    var found = false;
293
    this.each(function(value) {
294
      if (value == object) {
295
        found = true;
296
        throw $break;
297
      }
298
    });
299
    return found;
300
  },
301

  
302
  inject: function(memo, iterator) {
303
    this.each(function(value, index) {
304
      memo = iterator(memo, value, index);
305
    });
306
    return memo;
307
  },
308

  
309
  invoke: function(method) {
310
    var args = $A(arguments).slice(1);
311
    return this.collect(function(value) {
312
      return value[method].apply(value, args);
313
    });
314
  },
315

  
316
  max: function(iterator) {
317
    var result;
318
    this.each(function(value, index) {
319
      value = (iterator || Prototype.K)(value, index);
320
      if (value >= (result || value))
321
        result = value;
322
    });
323
    return result;
324
  },
325

  
326
  min: function(iterator) {
327
    var result;
328
    this.each(function(value, index) {
329
      value = (iterator || Prototype.K)(value, index);
330
      if (value <= (result || value))
331
        result = value;
332
    });
333
    return result;
334
  },
335

  
336
  partition: function(iterator) {
337
    var trues = [], falses = [];
338
    this.each(function(value, index) {
339
      ((iterator || Prototype.K)(value, index) ?
340
        trues : falses).push(value);
341
    });
342
    return [trues, falses];
343
  },
344

  
345
  pluck: function(property) {
346
    var results = [];
347
    this.each(function(value, index) {
348
      results.push(value[property]);
349
    });
350
    return results;
351
  },
352

  
353
  reject: function(iterator) {
354
    var results = [];
355
    this.each(function(value, index) {
356
      if (!iterator(value, index))
357
        results.push(value);
358
    });
359
    return results;
360
  },
361

  
362
  sortBy: function(iterator) {
363
    return this.collect(function(value, index) {
364
      return {value: value, criteria: iterator(value, index)};
365
    }).sort(function(left, right) {
366
      var a = left.criteria, b = right.criteria;
367
      return a < b ? -1 : a > b ? 1 : 0;
368
    }).pluck('value');
369
  },
370

  
371
  toArray: function() {
372
    return this.collect(Prototype.K);
373
  },
374

  
375
  zip: function() {
376
    var iterator = Prototype.K, args = $A(arguments);
377
    if (typeof args.last() == 'function')
378
      iterator = args.pop();
379

  
380
    var collections = [this].concat(args).map($A);
381
    return this.map(function(value, index) {
382
      iterator(value = collections.pluck(index));
383
      return value;
384
    });
385
  },
386

  
387
  inspect: function() {
388
    return '#<Enumerable:' + this.toArray().inspect() + '>';
389
  }
390
}
391

  
392
Object.extend(Enumerable, {
393
  map:     Enumerable.collect,
394
  find:    Enumerable.detect,
395
  select:  Enumerable.findAll,
396
  member:  Enumerable.include,
397
  entries: Enumerable.toArray
398
});
399
var $A = Array.from = function(iterable) {
400
  if (!iterable) return [];
401
  if (iterable.toArray) {
402
    return iterable.toArray();
403
  } else {
404
    var results = [];
405
    for (var i = 0; i < iterable.length; i++)
406
      results.push(iterable[i]);
407
    return results;
408
  }
409
}
410

  
411
Object.extend(Array.prototype, Enumerable);
412

  
413
Array.prototype._reverse = Array.prototype.reverse;
414

  
415
Object.extend(Array.prototype, {
416
  _each: function(iterator) {
417
    for (var i = 0; i < this.length; i++)
418
      iterator(this[i]);
419
  },
420

  
421
  clear: function() {
422
    this.length = 0;
423
    return this;
424
  },
425

  
426
  first: function() {
427
    return this[0];
428
  },
429

  
430
  last: function() {
431
    return this[this.length - 1];
432
  },
433

  
434
  compact: function() {
435
    return this.select(function(value) {
436
      return value != undefined || value != null;
437
    });
438
  },
439

  
440
  flatten: function() {
441
    return this.inject([], function(array, value) {
442
      return array.concat(value.constructor == Array ?
443
        value.flatten() : [value]);
444
    });
445
  },
446

  
447
  without: function() {
448
    var values = $A(arguments);
449
    return this.select(function(value) {
450
      return !values.include(value);
451
    });
452
  },
453

  
454
  indexOf: function(object) {
455
    for (var i = 0; i < this.length; i++)
456
      if (this[i] == object) return i;
457
    return -1;
458
  },
459

  
460
  reverse: function(inline) {
461
    return (inline !== false ? this : this.toArray())._reverse();
462
  },
463

  
464
  shift: function() {
465
    var result = this[0];
466
    for (var i = 0; i < this.length - 1; i++)
467
      this[i] = this[i + 1];
468
    this.length--;
469
    return result;
470
  },
471

  
472
  inspect: function() {
473
    return '[' + this.map(Object.inspect).join(', ') + ']';
474
  }
475
});
476
var Hash = {
477
  _each: function(iterator) {
478
    for (key in this) {
479
      var value = this[key];
480
      if (typeof value == 'function') continue;
481

  
482
      var pair = [key, value];
483
      pair.key = key;
484
      pair.value = value;
485
      iterator(pair);
486
    }
487
  },
488

  
489
  keys: function() {
490
    return this.pluck('key');
491
  },
492

  
493
  values: function() {
494
    return this.pluck('value');
495
  },
496

  
497
  merge: function(hash) {
498
    return $H(hash).inject($H(this), function(mergedHash, pair) {
499
      mergedHash[pair.key] = pair.value;
500
      return mergedHash;
501
    });
502
  },
503

  
504
  toQueryString: function() {
505
    return this.map(function(pair) {
506
      return pair.map(encodeURIComponent).join('=');
507
    }).join('&');
508
  },
509

  
510
  inspect: function() {
511
    return '#<Hash:{' + this.map(function(pair) {
512
      return pair.map(Object.inspect).join(': ');
513
    }).join(', ') + '}>';
514
  }
515
}
516

  
517
function $H(object) {
518
  var hash = Object.extend({}, object || {});
519
  Object.extend(hash, Enumerable);
520
  Object.extend(hash, Hash);
521
  return hash;
522
}
523
ObjectRange = Class.create();
524
Object.extend(ObjectRange.prototype, Enumerable);
525
Object.extend(ObjectRange.prototype, {
526
  initialize: function(start, end, exclusive) {
527
    this.start = start;
528
    this.end = end;
529
    this.exclusive = exclusive;
530
  },
531

  
532
  _each: function(iterator) {
533
    var value = this.start;
534
    do {
535
      iterator(value);
536
      value = value.succ();
537
    } while (this.include(value));
538
  },
539

  
540
  include: function(value) {
541
    if (value < this.start)
542
      return false;
543
    if (this.exclusive)
544
      return value < this.end;
545
    return value <= this.end;
546
  }
547
});
548

  
549
var $R = function(start, end, exclusive) {
550
  return new ObjectRange(start, end, exclusive);
551
}
552

  
169 553
var Ajax = {
170 554
  getTransport: function() {
171 555
    return Try.these(
......
173 557
      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
174 558
      function() {return new XMLHttpRequest()}
175 559
    ) || false;
176
  }
560
  },
561

  
562
  activeRequestCount: 0
177 563
}
178 564

  
565
Ajax.Responders = {
566
  responders: [],
567

  
568
  _each: function(iterator) {
569
    this.responders._each(iterator);
570
  },
571

  
572
  register: function(responderToAdd) {
573
    if (!this.include(responderToAdd))
574
      this.responders.push(responderToAdd);
575
  },
576

  
577
  unregister: function(responderToRemove) {
578
    this.responders = this.responders.without(responderToRemove);
579
  },
580

  
581
  dispatch: function(callback, request, transport, json) {
582
    this.each(function(responder) {
583
      if (responder[callback] && typeof responder[callback] == 'function') {
584
        try {
585
          responder[callback].apply(responder, [request, transport, json]);
586
        } catch (e) {}
587
      }
588
    });
589
  }
590
};
591

  
592
Object.extend(Ajax.Responders, Enumerable);
593

  
594
Ajax.Responders.register({
595
  onCreate: function() {
596
    Ajax.activeRequestCount++;
597
  },
598

  
599
  onComplete: function() {
600
    Ajax.activeRequestCount--;
601
  }
602
});
603

  
179 604
Ajax.Base = function() {};
180 605
Ajax.Base.prototype = {
181 606
  setOptions: function(options) {
......
183 608
      method:       'post',
184 609
      asynchronous: true,
185 610
      parameters:   ''
186
    }.extend(options || {});
611
    }
612
    Object.extend(this.options, options || {});
187 613
  },
188 614

  
189 615
  responseIsSuccess: function() {
190 616
    return this.transport.status == undefined
191
        || this.transport.status == 0 
617
        || this.transport.status == 0
192 618
        || (this.transport.status >= 200 && this.transport.status < 300);
193 619
  },
194 620

  
......
198 624
}
199 625

  
200 626
Ajax.Request = Class.create();
201
Ajax.Request.Events = 
627
Ajax.Request.Events =
202 628
  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
203 629

  
204
Ajax.Request.prototype = (new Ajax.Base()).extend({
630
Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
205 631
  initialize: function(url, options) {
206 632
    this.transport = Ajax.getTransport();
207 633
    this.setOptions(options);
......
213 639
    if (parameters.length > 0) parameters += '&_=';
214 640

  
215 641
    try {
216
      if (this.options.method == 'get')
217
        url += '?' + parameters;
642
      this.url = url;
643
      if (this.options.method == 'get' && parameters.length > 0)
644
        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
218 645

  
219
      this.transport.open(this.options.method, url,
646
      Ajax.Responders.dispatch('onCreate', this, this.transport);
647

  
648
      this.transport.open(this.options.method, this.url,
220 649
        this.options.asynchronous);
221 650

  
222 651
      if (this.options.asynchronous) {
......
230 659
      this.transport.send(this.options.method == 'post' ? body : null);
231 660

  
232 661
    } catch (e) {
662
      this.dispatchException(e);
233 663
    }
234 664
  },
235 665

  
236 666
  setRequestHeaders: function() {
237
    var requestHeaders = 
667
    var requestHeaders =
238 668
      ['X-Requested-With', 'XMLHttpRequest',
239 669
       'X-Prototype-Version', Prototype.Version];
240 670

  
241 671
    if (this.options.method == 'post') {
242
      requestHeaders.push('Content-type', 
672
      requestHeaders.push('Content-type',
243 673
        'application/x-www-form-urlencoded');
244 674

  
245 675
      /* Force "Connection: close" for Mozilla browsers to work around
246 676
       * a bug where XMLHttpReqeuest sends an incorrect Content-length
247
       * header. See Mozilla Bugzilla #246651. 
677
       * header. See Mozilla Bugzilla #246651.
248 678
       */
249 679
      if (this.transport.overrideMimeType)
250 680
        requestHeaders.push('Connection', 'close');
......
263 693
      this.respondToReadyState(this.transport.readyState);
264 694
  },
265 695

  
696
  header: function(name) {
697
    try {
698
      return this.transport.getResponseHeader(name);
699
    } catch (e) {}
700
  },
701

  
702
  evalJSON: function() {
703
    try {
704
      return eval(this.header('X-JSON'));
705
    } catch (e) {}
706
  },
707

  
708
  evalResponse: function() {
709
    try {
710
      return eval(this.transport.responseText);
711
    } catch (e) {
712
      this.dispatchException(e);
713
    }
714
  },
715

  
266 716
  respondToReadyState: function(readyState) {
267 717
    var event = Ajax.Request.Events[readyState];
718
    var transport = this.transport, json = this.evalJSON();
268 719

  
269
    if (event == 'Complete')
270
      (this.options['on' + this.transport.status]
271
       || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
272
       || Prototype.emptyFunction)(this.transport);
720
    if (event == 'Complete') {
721
      try {
722
        (this.options['on' + this.transport.status]
723
         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
724
         || Prototype.emptyFunction)(transport, json);
725
      } catch (e) {
726
        this.dispatchException(e);
727
      }
273 728

  
274
    (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
729
      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
730
        this.evalResponse();
731
    }
275 732

  
733
    try {
734
      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
735
      Ajax.Responders.dispatch('on' + event, this, transport, json);
736
    } catch (e) {
737
      this.dispatchException(e);
738
    }
739

  
276 740
    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
277 741
    if (event == 'Complete')
278 742
      this.transport.onreadystatechange = Prototype.emptyFunction;
743
  },
744

  
745
  dispatchException: function(exception) {
746
    (this.options.onException || Prototype.emptyFunction)(this, exception);
747
    Ajax.Responders.dispatch('onException', this, exception);
279 748
  }
280 749
});
281 750

  
282 751
Ajax.Updater = Class.create();
283
Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';
284 752

  
285
Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
753
Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
286 754
  initialize: function(container, url, options) {
287 755
    this.containers = {
288 756
      success: container.success ? $(container.success) : $(container),
......
294 762
    this.setOptions(options);
295 763

  
296 764
    var onComplete = this.options.onComplete || Prototype.emptyFunction;
297
    this.options.onComplete = (function() {
765
    this.options.onComplete = (function(transport, object) {
298 766
      this.updateContent();
299
      onComplete(this.transport);
767
      onComplete(transport, object);
300 768
    }).bind(this);
301 769

  
302 770
    this.request(url);
......
305 773
  updateContent: function() {
306 774
    var receiver = this.responseIsSuccess() ?
307 775
      this.containers.success : this.containers.failure;
776
    var response = this.transport.responseText;
308 777

  
309
    var match    = new RegExp(Ajax.Updater.ScriptFragment, 'img');
310
    var response = this.transport.responseText.replace(match, '');
311
    var scripts  = this.transport.responseText.match(match);
778
    if (!this.options.evalScripts)
779
      response = response.stripScripts();
312 780

  
313 781
    if (receiver) {
314 782
      if (this.options.insertion) {
315 783
        new this.options.insertion(receiver, response);
316 784
      } else {
317
        receiver.innerHTML = response;
785
        Element.update(receiver, response);
318 786
      }
319 787
    }
320 788

  
321 789
    if (this.responseIsSuccess()) {
322 790
      if (this.onComplete)
323
        setTimeout((function() {this.onComplete(
324
          this.transport)}).bind(this), 10);
791
        setTimeout(this.onComplete.bind(this), 10);
325 792
    }
326

  
327
    if (this.options.evalScripts && scripts) {
328
      match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
329
      setTimeout((function() {
330
        for (var i = 0; i < scripts.length; i++)
331
          eval(scripts[i].match(match)[1]);
332
      }).bind(this), 10);
333
    }
334 793
  }
335 794
});
336 795

  
337 796
Ajax.PeriodicalUpdater = Class.create();
338
Ajax.PeriodicalUpdater.prototype = (new Ajax.Base()).extend({
797
Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
339 798
  initialize: function(container, url, options) {
340 799
    this.setOptions(options);
341 800
    this.onComplete = this.options.onComplete;
342 801

  
343 802
    this.frequency = (this.options.frequency || 2);
344
    this.decay = 1;
803
    this.decay = (this.options.decay || 1);
345 804

  
346 805
    this.updater = {};
347 806
    this.container = container;
......
358 817
  stop: function() {
359 818
    this.updater.onComplete = undefined;
360 819
    clearTimeout(this.timer);
361
    (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
820
    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
362 821
  },
363 822

  
364 823
  updateComplete: function(request) {
365 824
    if (this.options.decay) {
366
      this.decay = (request.responseText == this.lastText ? 
825
      this.decay = (request.responseText == this.lastText ?
367 826
        this.decay * this.options.decay : 1);
368 827

  
369 828
      this.lastText = request.responseText;
370 829
    }
371
    this.timer = setTimeout(this.onTimerEvent.bind(this), 
830
    this.timer = setTimeout(this.onTimerEvent.bind(this),
372 831
      this.decay * this.frequency * 1000);
373 832
  },
374 833

  
......
376 835
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
377 836
  }
378 837
});
379

  
380
document.getElementsByClassName = function(className) {
381
  var children = document.getElementsByTagName('*') || document.all;
382
  var elements = new Array();
383
  
384
  for (var i = 0; i < children.length; i++) {
385
    var child = children[i];
386
    var classNames = child.className.split(' ');
387
    for (var j = 0; j < classNames.length; j++) {
388
      if (classNames[j] == className) {
389
        elements.push(child);
390
        break;
391
      }
392
    }
393
  }
394
  
395
  return elements;
838
document.getElementsByClassName = function(className, parentElement) {
839
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
840
  return $A(children).inject([], function(elements, child) {
841
    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
842
      elements.push(child);
843
    return elements;
844
  });
396 845
}
397 846

  
398 847
/*--------------------------------------------------------------------------*/
......
402 851
}
403 852

  
404 853
Object.extend(Element, {
854
  visible: function(element) {
855
    return $(element).style.display != 'none';
856
  },
857

  
405 858
  toggle: function() {
406 859
    for (var i = 0; i < arguments.length; i++) {
407 860
      var element = $(arguments[i]);
408
      element.style.display = 
409
        (element.style.display == 'none' ? '' : 'none');
861
      Element[Element.visible(element) ? 'hide' : 'show'](element);
410 862
    }
411 863
  },
412 864

  
......
428 880
    element = $(element);
429 881
    element.parentNode.removeChild(element);
430 882
  },
431
   
883

  
884
  update: function(element, html) {
885
    $(element).innerHTML = html.stripScripts();
886
    setTimeout(function() {html.evalScripts()}, 10);
887
  },
888

  
432 889
  getHeight: function(element) {
433 890
    element = $(element);
434
    return element.offsetHeight; 
891
    return element.offsetHeight;
435 892
  },
436 893

  
894
  classNames: function(element) {
895
    return new Element.ClassNames(element);
896
  },
897

  
437 898
  hasClassName: function(element, className) {
438
    element = $(element);
439
    if (!element)
440
      return;
441
    var a = element.className.split(' ');
442
    for (var i = 0; i < a.length; i++) {
443
      if (a[i] == className)
444
        return true;
445
    }
446
    return false;
899
    if (!(element = $(element))) return;
900
    return Element.classNames(element).include(className);
447 901
  },
448 902

  
449 903
  addClassName: function(element, className) {
450
    element = $(element);
451
    Element.removeClassName(element, className);
452
    element.className += ' ' + className;
904
    if (!(element = $(element))) return;
905
    return Element.classNames(element).add(className);
453 906
  },
454 907

  
455 908
  removeClassName: function(element, className) {
456
    element = $(element);
457
    if (!element)
458
      return;
459
    var newClassName = '';
460
    var a = element.className.split(' ');
461
    for (var i = 0; i < a.length; i++) {
462
      if (a[i] != className) {
463
        if (i > 0)
464
          newClassName += ' ';
465
        newClassName += a[i];
466
      }
467
    }
468
    element.className = newClassName;
909
    if (!(element = $(element))) return;
910
    return Element.classNames(element).remove(className);
469 911
  },
470
  
912

  
471 913
  // removes whitespace-only text node children
472 914
  cleanWhitespace: function(element) {
473
    var element = $(element);
915
    element = $(element);
474 916
    for (var i = 0; i < element.childNodes.length; i++) {
475 917
      var node = element.childNodes[i];
476
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 
918
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
477 919
        Element.remove(node);
478 920
    }
921
  },
922

  
923
  empty: function(element) {
924
    return $(element).innerHTML.match(/^\s*$/);
925
  },
926

  
927
  scrollTo: function(element) {
928
    element = $(element);
929
    var x = element.x ? element.x : element.offsetLeft,
930
        y = element.y ? element.y : element.offsetTop;
931
    window.scrollTo(x, y);
932
  },
933

  
934
  getStyle: function(element, style) {
935
    element = $(element);
936
    var value = element.style[style.camelize()];
937
    if (!value) {
938
      if (document.defaultView && document.defaultView.getComputedStyle) {
939
        var css = document.defaultView.getComputedStyle(element, null);
940
        value = css ? css.getPropertyValue(style) : null;
941
      } else if (element.currentStyle) {
942
        value = element.currentStyle[style.camelize()];
943
      }
944
    }
945

  
946
    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
947
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
948

  
949
    return value == 'auto' ? null : value;
950
  },
951

  
952
  setStyle: function(element, style) {
953
    element = $(element);
954
    for (name in style)
955
      element.style[name.camelize()] = style[name];
956
  },
957

  
958
  getDimensions: function(element) {
959
    element = $(element);
960
    if (Element.getStyle(element, 'display') != 'none')
961
      return {width: element.offsetWidth, height: element.offsetHeight};
962

  
963
    // All *Width and *Height properties give 0 on elements with display none,
964
    // so enable the element temporarily
965
    var els = element.style;
966
    var originalVisibility = els.visibility;
967
    var originalPosition = els.position;
968
    els.visibility = 'hidden';
969
    els.position = 'absolute';
970
    els.display = '';
971
    var originalWidth = element.clientWidth;
972
    var originalHeight = element.clientHeight;
973
    els.display = 'none';
974
    els.position = originalPosition;
975
    els.visibility = originalVisibility;
976
    return {width: originalWidth, height: originalHeight};
977
  },
978

  
979
  makePositioned: function(element) {
980
    element = $(element);
981
    var pos = Element.getStyle(element, 'position');
982
    if (pos == 'static' || !pos) {
983
      element._madePositioned = true;
984
      element.style.position = 'relative';
985
      // Opera returns the offset relative to the positioning context, when an
986
      // element is position relative but top and left have not been defined
987
      if (window.opera) {
988
        element.style.top = 0;
989
        element.style.left = 0;
990
      }
991
    }
992
  },
993

  
994
  undoPositioned: function(element) {
995
    element = $(element);
996
    if (element._madePositioned) {
997
      element._madePositioned = undefined;
998
      element.style.position =
999
        element.style.top =
1000
        element.style.left =
1001
        element.style.bottom =
1002
        element.style.right = '';
1003
    }
1004
  },
1005

  
1006
  makeClipping: function(element) {
1007
    element = $(element);
1008
    if (element._overflow) return;
1009
    element._overflow = element.style.overflow;
1010
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1011
      element.style.overflow = 'hidden';
1012
  },
1013

  
1014
  undoClipping: function(element) {
1015
    element = $(element);
1016
    if (element._overflow) return;
1017
    element.style.overflow = element._overflow;
1018
    element._overflow = undefined;
479 1019
  }
480 1020
});
481 1021

  
......
491 1031
Abstract.Insertion.prototype = {
492 1032
  initialize: function(element, content) {
493 1033
    this.element = $(element);
494
    this.content = content;
495
    
1034
    this.content = content.stripScripts();
1035

  
496 1036
    if (this.adjacency && this.element.insertAdjacentHTML) {
497
      this.element.insertAdjacentHTML(this.adjacency, this.content);
1037
      try {
1038
        this.element.insertAdjacentHTML(this.adjacency, this.content);
1039
      } catch (e) {
1040
        if (this.element.tagName.toLowerCase() == 'tbody') {
1041
          this.insertContent(this.contentFromAnonymousTable());
1042
        } else {
1043
          throw e;
1044
        }
1045
      }
498 1046
    } else {
499 1047
      this.range = this.element.ownerDocument.createRange();
500 1048
      if (this.initializeRange) this.initializeRange();
501
      this.fragment = this.range.createContextualFragment(this.content);
502
      this.insertContent();
1049
      this.insertContent([this.range.createContextualFragment(this.content)]);
503 1050
    }
1051

  
1052
    setTimeout(function() {content.evalScripts()}, 10);
1053
  },
1054

  
1055
  contentFromAnonymousTable: function() {
1056
    var div = document.createElement('div');
1057
    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1058
    return $A(div.childNodes[0].childNodes[0].childNodes);
504 1059
  }
505 1060
}
506 1061

  
507 1062
var Insertion = new Object();
508 1063

  
509 1064
Insertion.Before = Class.create();
510
Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
1065
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
511 1066
  initializeRange: function() {
512 1067
    this.range.setStartBefore(this.element);
513 1068
  },
514
  
515
  insertContent: function() {
516
    this.element.parentNode.insertBefore(this.fragment, this.element);
1069

  
1070
  insertContent: function(fragments) {
1071
    fragments.each((function(fragment) {
1072
      this.element.parentNode.insertBefore(fragment, this.element);
1073
    }).bind(this));
517 1074
  }
518 1075
});
519 1076

  
520 1077
Insertion.Top = Class.create();
521
Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
1078
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
522 1079
  initializeRange: function() {
523 1080
    this.range.selectNodeContents(this.element);
524 1081
    this.range.collapse(true);
525 1082
  },
526
  
527
  insertContent: function() {  
528
    this.element.insertBefore(this.fragment, this.element.firstChild);
1083

  
1084
  insertContent: function(fragments) {
1085
    fragments.reverse(false).each((function(fragment) {
1086
      this.element.insertBefore(fragment, this.element.firstChild);
1087
    }).bind(this));
529 1088
  }
530 1089
});
531 1090

  
532 1091
Insertion.Bottom = Class.create();
533
Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
1092
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
534 1093
  initializeRange: function() {
535 1094
    this.range.selectNodeContents(this.element);
536 1095
    this.range.collapse(this.element);
537 1096
  },
538
  
539
  insertContent: function() {
540
    this.element.appendChild(this.fragment);
1097

  
1098
  insertContent: function(fragments) {
1099
    fragments.each((function(fragment) {
1100
      this.element.appendChild(fragment);
1101
    }).bind(this));
541 1102
  }
542 1103
});
543 1104

  
544 1105
Insertion.After = Class.create();
545
Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
1106
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
546 1107
  initializeRange: function() {
547 1108
    this.range.setStartAfter(this.element);
548 1109
  },
549
  
550
  insertContent: function() {
551
    this.element.parentNode.insertBefore(this.fragment, 
552
      this.element.nextSibling);
1110

  
1111
  insertContent: function(fragments) {
1112
    fragments.each((function(fragment) {
1113
      this.element.parentNode.insertBefore(fragment,
1114
        this.element.nextSibling);
1115
    }).bind(this));
553 1116
  }
554 1117
});
555 1118

  
1119
/*--------------------------------------------------------------------------*/
1120

  
1121
Element.ClassNames = Class.create();
1122
Element.ClassNames.prototype = {
1123
  initialize: function(element) {
1124
    this.element = $(element);
1125
  },
1126

  
1127
  _each: function(iterator) {
1128
    this.element.className.split(/\s+/).select(function(name) {
1129
      return name.length > 0;
1130
    })._each(iterator);
1131
  },
1132

  
1133
  set: function(className) {
1134
    this.element.className = className;
1135
  },
1136

  
1137
  add: function(classNameToAdd) {
1138
    if (this.include(classNameToAdd)) return;
1139
    this.set(this.toArray().concat(classNameToAdd).join(' '));
1140
  },
1141

  
1142
  remove: function(classNameToRemove) {
1143
    if (!this.include(classNameToRemove)) return;
1144
    this.set(this.select(function(className) {
1145
      return className != classNameToRemove;
1146
    }).join(' '));
1147
  },
1148

  
1149
  toString: function() {
1150
    return this.toArray().join(' ');
1151
  }
1152
}
1153

  
1154
Object.extend(Element.ClassNames.prototype, Enumerable);
556 1155
var Field = {
557 1156
  clear: function() {
558 1157
    for (var i = 0; i < arguments.length; i++)
......
562 1161
  focus: function(element) {
563 1162
    $(element).focus();
564 1163
  },
565
  
1164

  
566 1165
  present: function() {
567 1166
    for (var i = 0; i < arguments.length; i++)
568 1167
      if ($(arguments[i]).value == '') return false;
569 1168
    return true;
570 1169
  },
571
  
1170

  
572 1171
  select: function(element) {
573 1172
    $(element).select();
574 1173
  },
575
   
1174

  
576 1175
  activate: function(element) {
577
    $(element).focus();
578
    $(element).select();
1176
    element = $(element);
1177
    element.focus();
1178
    if (element.select)
1179
      element.select();
579 1180
  }
580 1181
}
581 1182

  
......
585 1186
  serialize: function(form) {
586 1187
    var elements = Form.getElements($(form));
587 1188
    var queryComponents = new Array();
588
    
1189

  
589 1190
    for (var i = 0; i < elements.length; i++) {
590 1191
      var queryComponent = Form.Element.serialize(elements[i]);
591 1192
      if (queryComponent)
592 1193
        queryComponents.push(queryComponent);
593 1194
    }
594
    
1195

  
595 1196
    return queryComponents.join('&');
596 1197
  },
597
  
1198

  
598 1199
  getElements: function(form) {
599
    var form = $(form);
1200
    form = $(form);
600 1201
    var elements = new Array();
601 1202

  
602 1203
    for (tagName in Form.Element.Serializers) {
......
606 1207
    }
607 1208
    return elements;
608 1209
  },
609
  
1210

  
610 1211
  getInputs: function(form, typeName, name) {
611
    var form = $(form);
1212
    form = $(form);
612 1213
    var inputs = form.getElementsByTagName('input');
613
    
1214

  
614 1215
    if (!typeName && !name)
615 1216
      return inputs;
616
      
1217

  
617 1218
    var matchingInputs = new Array();
618 1219
    for (var i = 0; i < inputs.length; i++) {
619 1220
      var input = inputs[i];
620 1221
      if ((typeName && input.type != typeName) ||
621
          (name && input.name != name)) 
1222
          (name && input.name != name))
622 1223
        continue;
623 1224
      matchingInputs.push(input);
624 1225
    }
......
643 1244
    }
644 1245
  },
645 1246

  
1247
  findFirstElement: function(form) {
1248
    return Form.getElements(form).find(function(element) {
1249
      return element.type != 'hidden' && !element.disabled &&
1250
        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1251
    });
1252
  },
1253

  
646 1254
  focusFirstElement: function(form) {
647
    var form = $(form);
648
    var elements = Form.getElements(form);
649
    for (var i = 0; i < elements.length; i++) {
650
      var element = elements[i];
651
      if (element.type != 'hidden' && !element.disabled) {
652
        Field.activate(element);
653
        break;
654
      }
655
    }
1255
    Field.activate(Form.findFirstElement(form));
656 1256
  },
657 1257

  
658 1258
  reset: function(form) {
......
662 1262

  
663 1263
Form.Element = {
664 1264
  serialize: function(element) {
665
    var element = $(element);
1265
    element = $(element);
666 1266
    var method = element.tagName.toLowerCase();
667 1267
    var parameter = Form.Element.Serializers[method](element);
668
    
669
    if (parameter)
670
      return encodeURIComponent(parameter[0]) + '=' + 
671
        encodeURIComponent(parameter[1]);                   
1268

  
1269
    if (parameter) {
1270
      var key = encodeURIComponent(parameter[0]);
1271
      if (key.length == 0) return;
1272

  
1273
      if (parameter[1].constructor != Array)
1274
        parameter[1] = [parameter[1]];
1275

  
1276
      return parameter[1].map(function(value) {
1277
        return key + '=' + encodeURIComponent(value);
1278
      }).join('&');
1279
    }
672 1280
  },
673
  
1281

  
674 1282
  getValue: function(element) {
675
    var element = $(element);
1283
    element = $(element);
676 1284
    var method = element.tagName.toLowerCase();
677 1285
    var parameter = Form.Element.Serializers[method](element);
678
    
679
    if (parameter) 
1286

  
1287
    if (parameter)
680 1288
      return parameter[1];
681 1289
  }
682 1290
}
......
689 1297
      case 'password':
690 1298
      case 'text':
691 1299
        return Form.Element.Serializers.textarea(element);
692
      case 'checkbox':  
1300
      case 'checkbox':
693 1301
      case 'radio':
694 1302
        return Form.Element.Serializers.inputSelector(element);
695 1303
    }
......
706 1314
  },
707 1315

  
708 1316
  select: function(element) {
709
    var value = '';
710
    if (element.type == 'select-one') {
711
      var index = element.selectedIndex;
712
      if (index >= 0)
713
        value = element.options[index].value || element.options[index].text;
714
    } else {
715
      value = new Array();
716
      for (var i = 0; i < element.length; i++) {
717
        var opt = element.options[i];
718
        if (opt.selected)
719
          value.push(opt.value || opt.text);
1317
    return Form.Element.Serializers[element.type == 'select-one' ?
1318
      'selectOne' : 'selectMany'](element);
1319
  },
1320

  
1321
  selectOne: function(element) {
1322
    var value = '', opt, index = element.selectedIndex;
1323
    if (index >= 0) {
1324
      opt = element.options[index];
1325
      value = opt.value;
1326
      if (!value && !('value' in opt))
1327
        value = opt.text;
1328
    }
1329
    return [element.name, value];
1330
  },
1331

  
1332
  selectMany: function(element) {
1333
    var value = new Array();
1334
    for (var i = 0; i < element.length; i++) {
1335
      var opt = element.options[i];
1336
      if (opt.selected) {
1337
        var optValue = opt.value;
1338
        if (!optValue && !('value' in opt))
1339
          optValue = opt.text;
1340
        value.push(optValue);
720 1341
      }
721 1342
    }
722 1343
    return [element.name, value];
......
735 1356
    this.frequency = frequency;
736 1357
    this.element   = $(element);
737 1358
    this.callback  = callback;
738
    
1359

  
739 1360
    this.lastValue = this.getValue();
740 1361
    this.registerCallback();
741 1362
  },
742
  
1363

  
743 1364
  registerCallback: function() {
744 1365
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
745 1366
  },
746
  
1367

  
747 1368
  onTimerEvent: function() {
748 1369
    var value = this.getValue();
749 1370
    if (this.lastValue != value) {
......
754 1375
}
755 1376

  
756 1377
Form.Element.Observer = Class.create();
757
Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
1378
Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
758 1379
  getValue: function() {
759 1380
    return Form.Element.getValue(this.element);
760 1381
  }
761 1382
});
762 1383

  
763 1384
Form.Observer = Class.create();
764
Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
1385
Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
765 1386
  getValue: function() {
766 1387
    return Form.serialize(this.element);
767 1388
  }
......
774 1395
  initialize: function(element, callback) {
775 1396
    this.element  = $(element);
776 1397
    this.callback = callback;
777
    
1398

  
778 1399
    this.lastValue = this.getValue();
779 1400
    if (this.element.tagName.toLowerCase() == 'form')
780 1401
      this.registerFormCallbacks();
781 1402
    else
782 1403
      this.registerCallback(this.element);
783 1404
  },
784
  
1405

  
785 1406
  onElementEvent: function() {
786 1407
    var value = this.getValue();
787 1408
    if (this.lastValue != value) {
......
789 1410
      this.lastValue = value;
790 1411
    }
791 1412
  },
792
  
1413

  
793 1414
  registerFormCallbacks: function() {
794 1415
    var elements = Form.getElements(this.element);
795 1416
    for (var i = 0; i < elements.length; i++)
796 1417
      this.registerCallback(elements[i]);
797 1418
  },
798
  
1419

  
799 1420
  registerCallback: function(element) {
800 1421
    if (element.type) {
801 1422
      switch (element.type.toLowerCase()) {
802
        case 'checkbox':  
1423
        case 'checkbox':
803 1424
        case 'radio':
804
          element.target = this;
805
          element.prev_onclick = element.onclick || Prototype.emptyFunction;
806
          element.onclick = function() {
807
            this.prev_onclick(); 
808
            this.target.onElementEvent();
809
          }
1425
          Event.observe(element, 'click', this.onElementEvent.bind(this));
810 1426
          break;
811 1427
        case 'password':
812 1428
        case 'text':
813 1429
        case 'textarea':
814 1430
        case 'select-one':
815 1431
        case 'select-multiple':
816
          element.target = this;
817
          element.prev_onchange = element.onchange || Prototype.emptyFunction;
818
          element.onchange = function() {
819
            this.prev_onchange(); 
820
            this.target.onElementEvent();
821
          }
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff