Project

General

Profile

« Previous | Next » 

Revision 2865

Added by sgarg over 18 years ago

added prototype.js - used by ajax in templates/getReview.tmpl

View differences:

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

  
13
var Prototype = {
14
  Version: '1.3.1',
15
  emptyFunction: function() {}
16
}
17

  
18
var Class = {
19
  create: function() {
20
    return function() { 
21
      this.initialize.apply(this, arguments);
22
    }
23
  }
24
}
25

  
26
var Abstract = new Object();
27

  
28
Object.extend = function(destination, source) {
29
  for (property in source) {
30
    destination[property] = source[property];
31
  }
32
  return destination;
33
}
34

  
35
Object.prototype.extend = function(object) {
36
  return Object.extend.apply(this, [this, object]);
37
}
38

  
39
Function.prototype.bind = function(object) {
40
  var __method = this;
41
  return function() {
42
    __method.apply(object, arguments);
43
  }
44
}
45

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

  
53
Number.prototype.toColorPart = function() {
54
  var digits = this.toString(16);
55
  if (this < 16) return '0' + digits;
56
  return digits;
57
}
58

  
59
var Try = {
60
  these: function() {
61
    var returnValue;
62

  
63
    for (var i = 0; i < arguments.length; i++) {
64
      var lambda = arguments[i];
65
      try {
66
        returnValue = lambda();
67
        break;
68
      } catch (e) {}
69
    }
70

  
71
    return returnValue;
72
  }
73
}
74

  
75
/*--------------------------------------------------------------------------*/
76

  
77
var PeriodicalExecuter = Class.create();
78
PeriodicalExecuter.prototype = {
79
  initialize: function(callback, frequency) {
80
    this.callback = callback;
81
    this.frequency = frequency;
82
    this.currentlyExecuting = false;
83

  
84
    this.registerCallback();
85
  },
86

  
87
  registerCallback: function() {
88
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
89
  },
90

  
91
  onTimerEvent: function() {
92
    if (!this.currentlyExecuting) {
93
      try { 
94
        this.currentlyExecuting = true;
95
        this.callback(); 
96
      } finally { 
97
        this.currentlyExecuting = false;
98
      }
99
    }
100
  }
101
}
102

  
103
/*--------------------------------------------------------------------------*/
104

  
105
function $() {
106
  var elements = new Array();
107

  
108
  for (var i = 0; i < arguments.length; i++) {
109
    var element = arguments[i];
110
    if (typeof element == 'string')
111
      element = document.getElementById(element);
112

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

  
116
    elements.push(element);
117
  }
118

  
119
  return elements;
120
}
121

  
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
}
130

  
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
}
149

  
150
String.prototype.extend({
151
  stripTags: function() {
152
    return this.replace(/<\/?[^>]+>/gi, '');
153
  },
154

  
155
  escapeHTML: function() {
156
    var div = document.createElement('div');
157
    var text = document.createTextNode(this);
158
    div.appendChild(text);
159
    return div.innerHTML;
160
  },
161

  
162
  unescapeHTML: function() {
163
    var div = document.createElement('div');
164
    div.innerHTML = this.stripTags();
165
    return div.childNodes[0].nodeValue;
166
  }
167
});
168

  
169
var Ajax = {
170
  getTransport: function() {
171
    return Try.these(
172
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
173
      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
174
      function() {return new XMLHttpRequest()}
175
    ) || false;
176
  }
177
}
178

  
179
Ajax.Base = function() {};
180
Ajax.Base.prototype = {
181
  setOptions: function(options) {
182
    this.options = {
183
      method:       'post',
184
      asynchronous: true,
185
      parameters:   ''
186
    }.extend(options || {});
187
  },
188

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

  
195
  responseIsFailure: function() {
196
    return !this.responseIsSuccess();
197
  }
198
}
199

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

  
204
Ajax.Request.prototype = (new Ajax.Base()).extend({
205
  initialize: function(url, options) {
206
    this.transport = Ajax.getTransport();
207
    this.setOptions(options);
208
    this.request(url);
209
  },
210

  
211
  request: function(url) {
212
    var parameters = this.options.parameters || '';
213
    if (parameters.length > 0) parameters += '&_=';
214

  
215
    try {
216
      if (this.options.method == 'get')
217
        url += '?' + parameters;
218

  
219
      this.transport.open(this.options.method, url,
220
        this.options.asynchronous);
221

  
222
      if (this.options.asynchronous) {
223
        this.transport.onreadystatechange = this.onStateChange.bind(this);
224
        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
225
      }
226

  
227
      this.setRequestHeaders();
228

  
229
      var body = this.options.postBody ? this.options.postBody : parameters;
230
      this.transport.send(this.options.method == 'post' ? body : null);
231

  
232
    } catch (e) {
233
    }
234
  },
235

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

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

  
245
      /* Force "Connection: close" for Mozilla browsers to work around
246
       * a bug where XMLHttpReqeuest sends an incorrect Content-length
247
       * header. See Mozilla Bugzilla #246651. 
248
       */
249
      if (this.transport.overrideMimeType)
250
        requestHeaders.push('Connection', 'close');
251
    }
252

  
253
    if (this.options.requestHeaders)
254
      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
255

  
256
    for (var i = 0; i < requestHeaders.length; i += 2)
257
      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
258
  },
259

  
260
  onStateChange: function() {
261
    var readyState = this.transport.readyState;
262
    if (readyState != 1)
263
      this.respondToReadyState(this.transport.readyState);
264
  },
265

  
266
  respondToReadyState: function(readyState) {
267
    var event = Ajax.Request.Events[readyState];
268

  
269
    if (event == 'Complete')
270
      (this.options['on' + this.transport.status]
271
       || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
272
       || Prototype.emptyFunction)(this.transport);
273

  
274
    (this.options['on' + event] || Prototype.emptyFunction)(this.transport);
275

  
276
    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
277
    if (event == 'Complete')
278
      this.transport.onreadystatechange = Prototype.emptyFunction;
279
  }
280
});
281

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

  
285
Ajax.Updater.prototype.extend(Ajax.Request.prototype).extend({
286
  initialize: function(container, url, options) {
287
    this.containers = {
288
      success: container.success ? $(container.success) : $(container),
289
      failure: container.failure ? $(container.failure) :
290
        (container.success ? null : $(container))
291
    }
292

  
293
    this.transport = Ajax.getTransport();
294
    this.setOptions(options);
295

  
296
    var onComplete = this.options.onComplete || Prototype.emptyFunction;
297
    this.options.onComplete = (function() {
298
      this.updateContent();
299
      onComplete(this.transport);
300
    }).bind(this);
301

  
302
    this.request(url);
303
  },
304

  
305
  updateContent: function() {
306
    var receiver = this.responseIsSuccess() ?
307
      this.containers.success : this.containers.failure;
308

  
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);
312

  
313
    if (receiver) {
314
      if (this.options.insertion) {
315
        new this.options.insertion(receiver, response);
316
      } else {
317
        receiver.innerHTML = response;
318
      }
319
    }
320

  
321
    if (this.responseIsSuccess()) {
322
      if (this.onComplete)
323
        setTimeout((function() {this.onComplete(
324
          this.transport)}).bind(this), 10);
325
    }
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
  }
335
});
336

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

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

  
346
    this.updater = {};
347
    this.container = container;
348
    this.url = url;
349

  
350
    this.start();
351
  },
352

  
353
  start: function() {
354
    this.options.onComplete = this.updateComplete.bind(this);
355
    this.onTimerEvent();
356
  },
357

  
358
  stop: function() {
359
    this.updater.onComplete = undefined;
360
    clearTimeout(this.timer);
361
    (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
362
  },
363

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

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

  
375
  onTimerEvent: function() {
376
    this.updater = new Ajax.Updater(this.container, this.url, this.options);
377
  }
378
});
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;
396
}
397

  
398
/*--------------------------------------------------------------------------*/
399

  
400
if (!window.Element) {
401
  var Element = new Object();
402
}
403

  
404
Object.extend(Element, {
405
  toggle: function() {
406
    for (var i = 0; i < arguments.length; i++) {
407
      var element = $(arguments[i]);
408
      element.style.display = 
409
        (element.style.display == 'none' ? '' : 'none');
410
    }
411
  },
412

  
413
  hide: function() {
414
    for (var i = 0; i < arguments.length; i++) {
415
      var element = $(arguments[i]);
416
      element.style.display = 'none';
417
    }
418
  },
419

  
420
  show: function() {
421
    for (var i = 0; i < arguments.length; i++) {
422
      var element = $(arguments[i]);
423
      element.style.display = '';
424
    }
425
  },
426

  
427
  remove: function(element) {
428
    element = $(element);
429
    element.parentNode.removeChild(element);
430
  },
431
   
432
  getHeight: function(element) {
433
    element = $(element);
434
    return element.offsetHeight; 
435
  },
436

  
437
  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;
447
  },
448

  
449
  addClassName: function(element, className) {
450
    element = $(element);
451
    Element.removeClassName(element, className);
452
    element.className += ' ' + className;
453
  },
454

  
455
  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;
469
  },
470
  
471
  // removes whitespace-only text node children
472
  cleanWhitespace: function(element) {
473
    var element = $(element);
474
    for (var i = 0; i < element.childNodes.length; i++) {
475
      var node = element.childNodes[i];
476
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 
477
        Element.remove(node);
478
    }
479
  }
480
});
481

  
482
var Toggle = new Object();
483
Toggle.display = Element.toggle;
484

  
485
/*--------------------------------------------------------------------------*/
486

  
487
Abstract.Insertion = function(adjacency) {
488
  this.adjacency = adjacency;
489
}
490

  
491
Abstract.Insertion.prototype = {
492
  initialize: function(element, content) {
493
    this.element = $(element);
494
    this.content = content;
495
    
496
    if (this.adjacency && this.element.insertAdjacentHTML) {
497
      this.element.insertAdjacentHTML(this.adjacency, this.content);
498
    } else {
499
      this.range = this.element.ownerDocument.createRange();
500
      if (this.initializeRange) this.initializeRange();
501
      this.fragment = this.range.createContextualFragment(this.content);
502
      this.insertContent();
503
    }
504
  }
505
}
506

  
507
var Insertion = new Object();
508

  
509
Insertion.Before = Class.create();
510
Insertion.Before.prototype = (new Abstract.Insertion('beforeBegin')).extend({
511
  initializeRange: function() {
512
    this.range.setStartBefore(this.element);
513
  },
514
  
515
  insertContent: function() {
516
    this.element.parentNode.insertBefore(this.fragment, this.element);
517
  }
518
});
519

  
520
Insertion.Top = Class.create();
521
Insertion.Top.prototype = (new Abstract.Insertion('afterBegin')).extend({
522
  initializeRange: function() {
523
    this.range.selectNodeContents(this.element);
524
    this.range.collapse(true);
525
  },
526
  
527
  insertContent: function() {  
528
    this.element.insertBefore(this.fragment, this.element.firstChild);
529
  }
530
});
531

  
532
Insertion.Bottom = Class.create();
533
Insertion.Bottom.prototype = (new Abstract.Insertion('beforeEnd')).extend({
534
  initializeRange: function() {
535
    this.range.selectNodeContents(this.element);
536
    this.range.collapse(this.element);
537
  },
538
  
539
  insertContent: function() {
540
    this.element.appendChild(this.fragment);
541
  }
542
});
543

  
544
Insertion.After = Class.create();
545
Insertion.After.prototype = (new Abstract.Insertion('afterEnd')).extend({
546
  initializeRange: function() {
547
    this.range.setStartAfter(this.element);
548
  },
549
  
550
  insertContent: function() {
551
    this.element.parentNode.insertBefore(this.fragment, 
552
      this.element.nextSibling);
553
  }
554
});
555

  
556
var Field = {
557
  clear: function() {
558
    for (var i = 0; i < arguments.length; i++)
559
      $(arguments[i]).value = '';
560
  },
561

  
562
  focus: function(element) {
563
    $(element).focus();
564
  },
565
  
566
  present: function() {
567
    for (var i = 0; i < arguments.length; i++)
568
      if ($(arguments[i]).value == '') return false;
569
    return true;
570
  },
571
  
572
  select: function(element) {
573
    $(element).select();
574
  },
575
   
576
  activate: function(element) {
577
    $(element).focus();
578
    $(element).select();
579
  }
580
}
581

  
582
/*--------------------------------------------------------------------------*/
583

  
584
var Form = {
585
  serialize: function(form) {
586
    var elements = Form.getElements($(form));
587
    var queryComponents = new Array();
588
    
589
    for (var i = 0; i < elements.length; i++) {
590
      var queryComponent = Form.Element.serialize(elements[i]);
591
      if (queryComponent)
592
        queryComponents.push(queryComponent);
593
    }
594
    
595
    return queryComponents.join('&');
596
  },
597
  
598
  getElements: function(form) {
599
    var form = $(form);
600
    var elements = new Array();
601

  
602
    for (tagName in Form.Element.Serializers) {
603
      var tagElements = form.getElementsByTagName(tagName);
604
      for (var j = 0; j < tagElements.length; j++)
605
        elements.push(tagElements[j]);
606
    }
607
    return elements;
608
  },
609
  
610
  getInputs: function(form, typeName, name) {
611
    var form = $(form);
612
    var inputs = form.getElementsByTagName('input');
613
    
614
    if (!typeName && !name)
615
      return inputs;
616
      
617
    var matchingInputs = new Array();
618
    for (var i = 0; i < inputs.length; i++) {
619
      var input = inputs[i];
620
      if ((typeName && input.type != typeName) ||
621
          (name && input.name != name)) 
622
        continue;
623
      matchingInputs.push(input);
624
    }
625

  
626
    return matchingInputs;
627
  },
628

  
629
  disable: function(form) {
630
    var elements = Form.getElements(form);
631
    for (var i = 0; i < elements.length; i++) {
632
      var element = elements[i];
633
      element.blur();
634
      element.disabled = 'true';
635
    }
636
  },
637

  
638
  enable: function(form) {
639
    var elements = Form.getElements(form);
640
    for (var i = 0; i < elements.length; i++) {
641
      var element = elements[i];
642
      element.disabled = '';
643
    }
644
  },
645

  
646
  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
    }
656
  },
657

  
658
  reset: function(form) {
659
    $(form).reset();
660
  }
661
}
662

  
663
Form.Element = {
664
  serialize: function(element) {
665
    var element = $(element);
666
    var method = element.tagName.toLowerCase();
667
    var parameter = Form.Element.Serializers[method](element);
668
    
669
    if (parameter)
670
      return encodeURIComponent(parameter[0]) + '=' + 
671
        encodeURIComponent(parameter[1]);                   
672
  },
673
  
674
  getValue: function(element) {
675
    var element = $(element);
676
    var method = element.tagName.toLowerCase();
677
    var parameter = Form.Element.Serializers[method](element);
678
    
679
    if (parameter) 
680
      return parameter[1];
681
  }
682
}
683

  
684
Form.Element.Serializers = {
685
  input: function(element) {
686
    switch (element.type.toLowerCase()) {
687
      case 'submit':
688
      case 'hidden':
689
      case 'password':
690
      case 'text':
691
        return Form.Element.Serializers.textarea(element);
692
      case 'checkbox':  
693
      case 'radio':
694
        return Form.Element.Serializers.inputSelector(element);
695
    }
696
    return false;
697
  },
698

  
699
  inputSelector: function(element) {
700
    if (element.checked)
701
      return [element.name, element.value];
702
  },
703

  
704
  textarea: function(element) {
705
    return [element.name, element.value];
706
  },
707

  
708
  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);
720
      }
721
    }
722
    return [element.name, value];
723
  }
724
}
725

  
726
/*--------------------------------------------------------------------------*/
727

  
728
var $F = Form.Element.getValue;
729

  
730
/*--------------------------------------------------------------------------*/
731

  
732
Abstract.TimedObserver = function() {}
733
Abstract.TimedObserver.prototype = {
734
  initialize: function(element, frequency, callback) {
735
    this.frequency = frequency;
736
    this.element   = $(element);
737
    this.callback  = callback;
738
    
739
    this.lastValue = this.getValue();
740
    this.registerCallback();
741
  },
742
  
743
  registerCallback: function() {
744
    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
745
  },
746
  
747
  onTimerEvent: function() {
748
    var value = this.getValue();
749
    if (this.lastValue != value) {
750
      this.callback(this.element, value);
751
      this.lastValue = value;
752
    }
753
  }
754
}
755

  
756
Form.Element.Observer = Class.create();
757
Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
758
  getValue: function() {
759
    return Form.Element.getValue(this.element);
760
  }
761
});
762

  
763
Form.Observer = Class.create();
764
Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
765
  getValue: function() {
766
    return Form.serialize(this.element);
767
  }
768
});
769

  
770
/*--------------------------------------------------------------------------*/
771

  
772
Abstract.EventObserver = function() {}
773
Abstract.EventObserver.prototype = {
774
  initialize: function(element, callback) {
775
    this.element  = $(element);
776
    this.callback = callback;
777
    
778
    this.lastValue = this.getValue();
779
    if (this.element.tagName.toLowerCase() == 'form')
780
      this.registerFormCallbacks();
781
    else
782
      this.registerCallback(this.element);
783
  },
784
  
785
  onElementEvent: function() {
786
    var value = this.getValue();
787
    if (this.lastValue != value) {
788
      this.callback(this.element, value);
789
      this.lastValue = value;
790
    }
791
  },
792
  
793
  registerFormCallbacks: function() {
794
    var elements = Form.getElements(this.element);
795
    for (var i = 0; i < elements.length; i++)
796
      this.registerCallback(elements[i]);
797
  },
798
  
799
  registerCallback: function(element) {
800
    if (element.type) {
801
      switch (element.type.toLowerCase()) {
802
        case 'checkbox':  
803
        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
          }
810
          break;
811
        case 'password':
812
        case 'text':
813
        case 'textarea':
814
        case 'select-one':
815
        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
          }
822
          break;
823
      }
824
    }    
825
  }
826
}
827

  
828
Form.Element.EventObserver = Class.create();
829
Form.Element.EventObserver.prototype = (new Abstract.EventObserver()).extend({
830
  getValue: function() {
831
    return Form.Element.getValue(this.element);
832
  }
833
});
834

  
835
Form.EventObserver = Class.create();
836
Form.EventObserver.prototype = (new Abstract.EventObserver()).extend({
837
  getValue: function() {
838
    return Form.serialize(this.element);
839
  }
840
});
841

  
842

  
843
if (!window.Event) {
844
  var Event = new Object();
845
}
846

  
847
Object.extend(Event, {
848
  KEY_BACKSPACE: 8,
849
  KEY_TAB:       9,
850
  KEY_RETURN:   13,
851
  KEY_ESC:      27,
852
  KEY_LEFT:     37,
853
  KEY_UP:       38,
854
  KEY_RIGHT:    39,
855
  KEY_DOWN:     40,
856
  KEY_DELETE:   46,
857

  
858
  element: function(event) {
859
    return event.target || event.srcElement;
860
  },
861

  
862
  isLeftClick: function(event) {
863
    return (((event.which) && (event.which == 1)) ||
864
            ((event.button) && (event.button == 1)));
865
  },
866

  
867
  pointerX: function(event) {
868
    return event.pageX || (event.clientX + 
869
      (document.documentElement.scrollLeft || document.body.scrollLeft));
870
  },
871

  
872
  pointerY: function(event) {
873
    return event.pageY || (event.clientY + 
874
      (document.documentElement.scrollTop || document.body.scrollTop));
875
  },
876

  
877
  stop: function(event) {
878
    if (event.preventDefault) { 
879
      event.preventDefault(); 
880
      event.stopPropagation(); 
881
    } else {
882
      event.returnValue = false;
883
    }
884
  },
885

  
886
  // find the first node with the given tagName, starting from the
887
  // node the event was triggered on; traverses the DOM upwards
888
  findElement: function(event, tagName) {
889
    var element = Event.element(event);
890
    while (element.parentNode && (!element.tagName ||
891
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
892
      element = element.parentNode;
893
    return element;
894
  },
895

  
896
  observers: false,
897
  
898
  _observeAndCache: function(element, name, observer, useCapture) {
899
    if (!this.observers) this.observers = [];
900
    if (element.addEventListener) {
901
      this.observers.push([element, name, observer, useCapture]);
902
      element.addEventListener(name, observer, useCapture);
903
    } else if (element.attachEvent) {
904
      this.observers.push([element, name, observer, useCapture]);
905
      element.attachEvent('on' + name, observer);
906
    }
907
  },
908
  
909
  unloadCache: function() {
910
    if (!Event.observers) return;
911
    for (var i = 0; i < Event.observers.length; i++) {
912
      Event.stopObserving.apply(this, Event.observers[i]);
913
      Event.observers[i][0] = null;
914
    }
915
    Event.observers = false;
916
  },
917

  
918
  observe: function(element, name, observer, useCapture) {
919
    var element = $(element);
920
    useCapture = useCapture || false;
921
    
922
    if (name == 'keypress' &&
923
        ((navigator.appVersion.indexOf('AppleWebKit') > 0) 
924
        || element.attachEvent))
925
      name = 'keydown';
926
    
927
    this._observeAndCache(element, name, observer, useCapture);
928
  },
929

  
930
  stopObserving: function(element, name, observer, useCapture) {
931
    var element = $(element);
932
    useCapture = useCapture || false;
933
    
934
    if (name == 'keypress' &&
935
        ((navigator.appVersion.indexOf('AppleWebKit') > 0) 
936
        || element.detachEvent))
937
      name = 'keydown';
938
    
939
    if (element.removeEventListener) {
940
      element.removeEventListener(name, observer, useCapture);
941
    } else if (element.detachEvent) {
942
      element.detachEvent('on' + name, observer);
943
    }
944
  }
945
});
946

  
947
/* prevent memory leaks in IE */
948
Event.observe(window, 'unload', Event.unloadCache, false);
949

  
950
var Position = {
951

  
952
  // set to true if needed, warning: firefox performance problems
953
  // NOT neeeded for page scrolling, only if draggable contained in
954
  // scrollable elements
955
  includeScrollOffsets: false, 
956

  
957
  // must be called before calling withinIncludingScrolloffset, every time the
958
  // page is scrolled
959
  prepare: function() {
960
    this.deltaX =  window.pageXOffset 
961
                || document.documentElement.scrollLeft 
962
                || document.body.scrollLeft 
963
                || 0;
964
    this.deltaY =  window.pageYOffset 
965
                || document.documentElement.scrollTop 
966
                || document.body.scrollTop 
967
                || 0;
968
  },
969

  
970
  realOffset: function(element) {
971
    var valueT = 0, valueL = 0;
972
    do {
973
      valueT += element.scrollTop  || 0;
974
      valueL += element.scrollLeft || 0; 
975
      element = element.parentNode;
976
    } while (element);
977
    return [valueL, valueT];
978
  },
979

  
980
  cumulativeOffset: function(element) {
981
    var valueT = 0, valueL = 0;
982
    do {
983
      valueT += element.offsetTop  || 0;
984
      valueL += element.offsetLeft || 0;
985
      element = element.offsetParent;
986
    } while (element);
987
    return [valueL, valueT];
988
  },
989

  
990
  // caches x/y coordinate pair to use with overlap
991
  within: function(element, x, y) {
992
    if (this.includeScrollOffsets)
993
      return this.withinIncludingScrolloffsets(element, x, y);
994
    this.xcomp = x;
995
    this.ycomp = y;
996
    this.offset = this.cumulativeOffset(element);
997

  
998
    return (y >= this.offset[1] &&
999
            y <  this.offset[1] + element.offsetHeight &&
1000
            x >= this.offset[0] && 
1001
            x <  this.offset[0] + element.offsetWidth);
1002
  },
1003

  
1004
  withinIncludingScrolloffsets: function(element, x, y) {
1005
    var offsetcache = this.realOffset(element);
1006

  
1007
    this.xcomp = x + offsetcache[0] - this.deltaX;
1008
    this.ycomp = y + offsetcache[1] - this.deltaY;
1009
    this.offset = this.cumulativeOffset(element);
1010

  
1011
    return (this.ycomp >= this.offset[1] &&
1012
            this.ycomp <  this.offset[1] + element.offsetHeight &&
1013
            this.xcomp >= this.offset[0] && 
1014
            this.xcomp <  this.offset[0] + element.offsetWidth);
1015
  },
1016

  
1017
  // within must be called directly before
1018
  overlap: function(mode, element) {  
1019
    if (!mode) return 0;  
1020
    if (mode == 'vertical') 
1021
      return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 
1022
        element.offsetHeight;
1023
    if (mode == 'horizontal')
1024
      return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 
1025
        element.offsetWidth;
1026
  },
1027

  
1028
  clone: function(source, target) {
1029
    source = $(source);
1030
    target = $(target);
1031
    target.style.position = 'absolute';
1032
    var offsets = this.cumulativeOffset(source);
1033
    target.style.top    = offsets[1] + 'px';
1034
    target.style.left   = offsets[0] + 'px';
1035
    target.style.width  = source.offsetWidth + 'px';
1036
    target.style.height = source.offsetHeight + 'px';
1037
  }
1038
}
0 1039

  

Also available in: Unified diff