PageSourceSearch

https://vnvista.com/forums/modules/portal/slide/prototype.js

js vnvista.com collected 2026-09-24 09:21:56 UTC 46,931 bytes, 1,770 lines download raw bytes

1var Prototype = {
2  Version: '1.4.0',
3  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
4
5  emptyFunction: function() {},
6  K: function(x) {return x}
7}
8
9var Class = {
10  create: function() {
11    return function() {
12      this.initialize.apply(this, arguments);
13    }
14  }
15}
16
17var Abstract = new Object();
18
19Object.extend = function(destination, source) {
20  for (property in source) {
21    destination[property] = source[property];
22  }
23  return destination;
24}
25
26Object.inspect = function(object) {
27  try {
28    if (object == undefined) return 'undefined';
29    if (object == null) return 'null';
30    return object.inspect ? object.inspect() : object.toString();
31  } catch (e) {
32    if (e instanceof RangeError) return '...';
33    throw e;
34  }
35}
36
37Function.prototype.bind = function() {
38  var __method = this, args = $A(arguments), object = args.shift();
39  return function() {
40    return __method.apply(object, args.concat($A(arguments)));
41  }
42}
43
44Function.prototype.bindAsEventListener = function(object) {
45  var __method = this;
46  return function(event) {
47    return __method.call(object, event || window.event);
48  }
49}
50
51Object.extend(Number.prototype, {
52  toColorPart: function() {
53    var digits = this.toString(16);
54    if (this < 16) return '0' + digits;
55    return digits;
56  },
57
58  succ: function() {
59    return this + 1;
60  },
61
62  times: function(iterator) {
63    $R(0, this, true).each(iterator);
64    return this;
65  }
66});
67
68var Try = {
69  these: function() {
70    var returnValue;
71
72    for (var i = 0; i < arguments.length; i++) {
73      var lambda = arguments[i];
74      try {
75        returnValue = lambda();
76        break;
77      } catch (e) {}
78    }
79
80    return returnValue;
81  }
82}
83
84/*--------------------------------------------------------------------------*/
85
86var PeriodicalExecuter = Class.create();
87PeriodicalExecuter.prototype = {
88  initialize: function(callback, frequency) {
89    this.callback = callback;
90    this.frequency = frequency;
91    this.currentlyExecuting = false;
92
93    this.registerCallback();
94  },
95
96  registerCallback: function() {
97    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
98  },
99
100  onTimerEvent: function() {
101    if (!this.currentlyExecuting) {
102      try {
103        this.currentlyExecuting = true;
104        this.callback();
105      } finally {
106        this.currentlyExecuting = false;
107      }
108    }
109  }
110}
111
112/*--------------------------------------------------------------------------*/
113
114function $() {
115  var elements = new Array();
116
117  for (var i = 0; i < arguments.length; i++) {
118    var element = arguments[i];
119    if (typeof element == 'string')
120      element = document.getElementById(element);
121
122    if (arguments.length == 1)
123      return element;
124
125    elements.push(element);
126  }
127
128  return elements;
129}
130Object.extend(String.prototype, {
131  stripTags: function() {
132    return this.replace(/<\/?[^>]+>/gi, '');
133  },
134
135  stripScripts: function() {
136    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
137  },
138
139  extractScripts: function() {
140    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
141    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
142    return (this.match(matchAll) || []).map(function(scriptTag) {
143      return (scriptTag.match(matchOne) || ['', ''])[1];
144    });
145  },
146
147  evalScripts: function() {
148    return this.extractScripts().map(eval);
149  },
150
151  escapeHTML: function() {
152    var div = document.createElement('div');
153    var text = document.createTextNode(this);
154    div.appendChild(text);
155    return div.innerHTML;
156  },
157
158  unescapeHTML: function() {
159    var div = document.createElement('div');
160    div.innerHTML = this.stripTags();
161    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
162  },
163
164  toQueryParams: function() {
165    var pairs = this.match(/^\??(.*)$/)[1].split('&');
166    return pairs.inject({}, function(params, pairString) {
167      var pair = pairString.split('=');
168      params[pair[0]] = pair[1];
169      return params;
170    });
171  },
172
173  toArray: function() {
174    return this.split('');
175  },
176
177  camelize: function() {
178    var oStringList = this.split('-');
179    if (oStringList.length == 1) return oStringList[0];
180
181    var camelizedString = this.indexOf('-') == 0
182      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
183      : oStringList[0];
184
185    for (var i = 1, len = oStringList.length; i < len; i++) {
186      var s = oStringList[i];
187      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
188    }
189
190    return camelizedString;
191  },
192
193  inspect: function() {
194    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
195  }
196});
197
198String.prototype.parseQuery = String.prototype.toQueryParams;
199
200var $break    = new Object();
201var $continue = new Object();
202
203var Enumerable = {
204  each: function(iterator) {
205    var index = 0;
206    try {
207      this._each(function(value) {
208        try {
209          iterator(value, index++);
210        } catch (e) {
211          if (e != $continue) throw e;
212        }
213      });
214    } catch (e) {
215      if (e != $break) throw e;
216    }
217  },
218
219  all: function(iterator) {
220    var result = true;
221    this.each(function(value, index) {
222      result = result && !!(iterator || Prototype.K)(value, index);
223      if (!result) throw $break;
224    });
225    return result;
226  },
227
228  any: function(iterator) {
229    var result = true;
230    this.each(function(value, index) {
231      if (result = !!(iterator || Prototype.K)(value, index))
232        throw $break;
233    });
234    return result;
235  },
236
237  collect: function(iterator) {
238    var results = [];
239    this.each(function(value, index) {
240      results.push(iterator(value, index));
241    });
242    return results;
243  },
244
245  detect: function (iterator) {
246    var result;
247    this.each(function(value, index) {
248      if (iterator(value, index)) {
249        result = value;
250        throw $break;
251      }
252    });
253    return result;
254  },
255
256  findAll: function(iterator) {
257    var results = [];
258    this.each(function(value, index) {
259      if (iterator(value, index))
260        results.push(value);
261    });
262    return results;
263  },
264
265  grep: function(pattern, iterator) {
266    var results = [];
267    this.each(function(value, index) {
268      var stringValue = value.toString();
269      if (stringValue.match(pattern))
270        results.push((iterator || Prototype.K)(value, index));
271    })
272    return results;
273  },
274
275  include: function(object) {
276    var found = false;
277    this.each(function(value) {
278      if (value == object) {
279        found = true;
280        throw $break;
281      }
282    });
283    return found;
284  },
285
286  inject: function(memo, iterator) {
287    this.each(function(value, index) {
288      memo = iterator(memo, value, index);
289    });
290    return memo;
291  },
292
293  invoke: function(method) {
294    var args = $A(arguments).slice(1);
295    return this.collect(function(value) {
296      return value[method].apply(value, args);
297    });
298  },
299
300  max: function(iterator) {
301    var result;
302    this.each(function(value, index) {
303      value = (iterator || Prototype.K)(value, index);
304      if (value >= (result || value))
305        result = value;
306    });
307    return result;
308  },
309
310  min: function(iterator) {
311    var result;
312    this.each(function(value, index) {
313      value = (iterator || Prototype.K)(value, index);
314      if (value <= (result || value))
315        result = value;
316    });
317    return result;
318  },
319
320  partition: function(iterator) {
321    var trues = [], falses = [];
322    this.each(function(value, index) {
323      ((iterator || Prototype.K)(value, index) ?
324        trues : falses).push(value);
325    });
326    return [trues, falses];
327  },
328
329  pluck: function(property) {
330    var results = [];
331    this.each(function(value, index) {
332      results.push(value[property]);
333    });
334    return results;
335  },
336
337  reject: function(iterator) {
338    var results = [];
339    this.each(function(value, index) {
340      if (!iterator(value, index))
341        results.push(value);
342    });
343    return results;
344  },
345
346  sortBy: function(iterator) {
347    return this.collect(function(value, index) {
348      return {value: value, criteria: iterator(value, index)};
349    }).sort(function(left, right) {
350      var a = left.criteria, b = right.criteria;
351      return a < b ? -1 : a > b ? 1 : 0;
352    }).pluck('value');
353  },
354
355  toArray: function() {
356    return this.collect(Prototype.K);
357  },
358
359  zip: function() {
360    var iterator = Prototype.K, args = $A(arguments);
361    if (typeof args.last() == 'function')
362      iterator = args.pop();
363
364    var collections = [this].concat(args).map($A);
365    return this.map(function(value, index) {
366      iterator(value = collections.pluck(index));
367      return value;
368    });
369  },
370
371  inspect: function() {
372    return '#<Enumerable:' + this.toArray().inspect() + '>';
373  }
374}
375
376Object.extend(Enumerable, {
377  map:     Enumerable.collect,
378  find:    Enumerable.detect,
379  select:  Enumerable.findAll,
380  member:  Enumerable.include,
381  entries: Enumerable.toArray
382});
383var $A = Array.from = function(iterable) {
384  if (!iterable) return [];
385  if (iterable.toArray) {
386    return iterable.toArray();
387  } else {
388    var results = [];
389    for (var i = 0; i < iterable.length; i++)
390      results.push(iterable[i]);
391    return results;
392  }
393}
394
395Object.extend(Array.prototype, Enumerable);
396
397Array.prototype._reverse = Array.prototype.reverse;
398
399Object.extend(Array.prototype, {
400  _each: function(iterator) {
401    for (var i = 0; i < this.length; i++)
402      iterator(this[i]);
403  },
404
405  clear: function() {
406    this.length = 0;
407    return this;
408  },
409
410  first: function() {
411    return this[0];
412  },
413
414  last: function() {
415    return this[this.length - 1];
416  },
417
418  compact: function() {
419    return this.select(function(value) {
420      return value != undefined || value != null;
421    });
422  },
423
424  flatten: function() {
425    return this.inject([], function(array, value) {
426      return array.concat(value.constructor == Array ?
427        value.flatten() : [value]);
428    });
429  },
430
431  without: function() {
432    var values = $A(arguments);
433    return this.select(function(value) {
434      return !values.include(value);
435    });
436  },
437
438  indexOf: function(object) {
439    for (var i = 0; i < this.length; i++)
440      if (this[i] == object) return i;
441    return -1;
442  },
443
444  reverse: function(inline) {
445    return (inline !== false ? this : this.toArray())._reverse();
446  },
447
448  shift: function() {
449    var result = this[0];
450    for (var i = 0; i < this.length - 1; i++)
451      this[i] = this[i + 1];
452    this.length--;
453    return result;
454  },
455
456  inspect: function() {
457    return '[' + this.map(Object.inspect).join(', ') + ']';
458  }
459});
460var Hash = {
461  _each: function(iterator) {
462    for (key in this) {
463      var value = this[key];
464      if (typeof value == 'function') continue;
465
466      var pair = [key, value];
467      pair.key = key;
468      pair.value = value;
469      iterator(pair);
470    }
471  },
472
473  keys: function() {
474    return this.pluck('key');
475  },
476
477  values: function() {
478    return this.pluck('value');
479  },
480
481  merge: function(hash) {
482    return $H(hash).inject($H(this), function(mergedHash, pair) {
483      mergedHash[pair.key] = pair.value;
484      return mergedHash;
485    });
486  },
487
488  toQueryString: function() {
489    return this.map(function(pair) {
490      return pair.map(encodeURIComponent).join('=');
491    }).join('&');
492  },
493
494  inspect: function() {
495    return '#<Hash:{' + this.map(function(pair) {
496      return pair.map(Object.inspect).join(': ');
497    }).join(', ') + '}>';
498  }
499}
500
501function $H(object) {
502  var hash = Object.extend({}, object || {});
503  Object.extend(hash, Enumerable);
504  Object.extend(hash, Hash);
505  return hash;
506}
507ObjectRange = Class.create();
508Object.extend(ObjectRange.prototype, Enumerable);
509Object.extend(ObjectRange.prototype, {
510  initialize: function(start, end, exclusive) {
511    this.start = start;
512    this.end = end;
513    this.exclusive = exclusive;
514  },
515
516  _each: function(iterator) {
517    var value = this.start;
518    do {
519      iterator(value);
520      value = value.succ();
521    } while (this.include(value));
522  },
523
524  include: function(value) {
525    if (value < this.start)
526      return false;
527    if (this.exclusive)
528      return value < this.end;
529    return value <= this.end;
530  }
531});
532
533var $R = function(start, end, exclusive) {
534  return new ObjectRange(start, end, exclusive);
535}
536
537var Ajax = {
538  getTransport: function() {
539    return Try.these(
540      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
541      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
542      function() {return new XMLHttpRequest()}
543    ) || false;
544  },
545
546  activeRequestCount: 0
547}
548
549Ajax.Responders = {
550  responders: [],
551
552  _each: function(iterator) {
553    this.responders._each(iterator);
554  },
555
556  register: function(responderToAdd) {
557    if (!this.include(responderToAdd))
558      this.responders.push(responderToAdd);
559  },
560
561  unregister: function(responderToRemove) {
562    this.responders = this.responders.without(responderToRemove);
563  },
564
565  dispatch: function(callback, request, transport, json) {
566    this.each(function(responder) {
567      if (responder[callback] && typeof responder[callback] == 'function') {
568        try {
569          responder[callback].apply(responder, [request, transport, json]);
570        } catch (e) {}
571      }
572    });
573  }
574};
575
576Object.extend(Ajax.Responders, Enumerable);
577
578Ajax.Responders.register({
579  onCreate: function() {
580    Ajax.activeRequestCount++;
581  },
582
583  onComplete: function() {
584    Ajax.activeRequestCount--;
585  }
586});
587
588Ajax.Base = function() {};
589Ajax.Base.prototype = {
590  setOptions: function(options) {
591    this.options = {
592      method:       'post',
593      asynchronous: true,
594      parameters:   ''
595    }
596    Object.extend(this.options, options || {});
597  },
598
599  responseIsSuccess: function() {
600    return this.transport.status == undefined
601        || this.transport.status == 0
602        || (this.transport.status >= 200 && this.transport.status < 300);
603  },
604
605  responseIsFailure: function() {
606    return !this.responseIsSuccess();
607  }
608}
609
610Ajax.Request = Class.create();
611Ajax.Request.Events =
612  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
613
614Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
615  initialize: function(url, options) {
616    this.transport = Ajax.getTransport();
617    this.setOptions(options);
618    this.request(url);
619  },
620
621  request: function(url) {
622    var parameters = this.options.parameters || '';
623    if (parameters.length > 0) parameters += '&_=';
624
625    try {
626      this.url = url;
627      if (this.options.method == 'get' && parameters.length > 0)
628        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
629
630      Ajax.Responders.dispatch('onCreate', this, this.transport);
631
632      this.transport.open(this.options.method, this.url,
633        this.options.asynchronous);
634
635      if (this.options.asynchronous) {
636        this.transport.onreadystatechange = this.onStateChange.bind(this);
637        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
638      }
639
640      this.setRequestHeaders();
641
642      var body = this.options.postBody ? this.options.postBody : parameters;
643      this.transport.send(this.options.method == 'post' ? body : null);
644
645    } catch (e) {
646      this.dispatchException(e);
647    }
648  },
649
650  setRequestHeaders: function() {
651    var requestHeaders =
652      ['X-Requested-With', 'XMLHttpRequest',
653       'X-Prototype-Version', Prototype.Version];
654
655    if (this.options.method == 'post') {
656      requestHeaders.push('Content-type',
657        'application/x-www-form-urlencoded');
658
659      /* Force "Connection: close" for Mozilla browsers to work around
660       * a bug where XMLHttpReqeuest sends an incorrect Content-length
661       * header. See Mozilla Bugzilla #246651.
662       */
663      if (this.transport.overrideMimeType)
664        requestHeaders.push('Connection', 'close');
665    }
666
667    if (this.options.requestHeaders)
668      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
669
670    for (var i = 0; i < requestHeaders.length; i += 2)
671      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
672  },
673
674  onStateChange: function() {
675    var readyState = this.transport.readyState;
676    if (readyState != 1)
677      this.respondToReadyState(this.transport.readyState);
678  },
679
680  header: function(name) {
681    try {
682      return this.transport.getResponseHeader(name);
683    } catch (e) {}
684  },
685
686  evalJSON: function() {
687    try {
688      return eval(this.header('X-JSON'));
689    } catch (e) {}
690  },
691
692  evalResponse: function() {
693    try {
694      return eval(this.transport.responseText);
695    } catch (e) {
696      this.dispatchException(e);
697    }
698  },
699
700  respondToReadyState: function(readyState) {
701    var event = Ajax.Request.Events[readyState];
702    var transport = this.transport, json = this.evalJSON();
703
704    if (event == 'Complete') {
705      try {
706        (this.options['on' + this.transport.status]
707         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
708         || Prototype.emptyFunction)(transport, json);
709      } catch (e) {
710        this.dispatchException(e);
711      }
712
713      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
714        this.evalResponse();
715    }
716
717    try {
718      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
719      Ajax.Responders.dispatch('on' + event, this, transport, json);
720    } catch (e) {
721      this.dispatchException(e);
722    }
723
724    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
725    if (event == 'Complete')
726      this.transport.onreadystatechange = Prototype.emptyFunction;
727  },
728
729  dispatchException: function(exception) {
730    (this.options.onException || Prototype.emptyFunction)(this, exception);
731    Ajax.Responders.dispatch('onException', this, exception);
732  }
733});
734
735Ajax.Updater = Class.create();
736
737Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
738  initialize: function(container, url, options) {
739    this.containers = {
740      success: container.success ? $(container.success) : $(container),
741      failure: container.failure ? $(container.failure) :
742        (container.success ? null : $(container))
743    }
744
745    this.transport = Ajax.getTransport();
746    this.setOptions(options);
747
748    var onComplete = this.options.onComplete || Prototype.emptyFunction;
749    this.options.onComplete = (function(transport, object) {
750      this.updateContent();
751      onComplete(transport, object);
752    }).bind(this);
753
754    this.request(url);
755  },
756
757  updateContent: function() {
758    var receiver = this.responseIsSuccess() ?
759      this.containers.success : this.containers.failure;
760    var response = this.transport.responseText;
761
762    if (!this.options.evalScripts)
763      response = response.stripScripts();
764
765    if (receiver) {
766      if (this.options.insertion) {
767        new this.options.insertion(receiver, response);
768      } else {
769        Element.update(receiver, response);
770      }
771    }
772
773    if (this.responseIsSuccess()) {
774      if (this.onComplete)
775        setTimeout(this.onComplete.bind(this), 10);
776    }
777  }
778});
779
780Ajax.PeriodicalUpdater = Class.create();
781Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
782  initialize: function(container, url, options) {
783    this.setOptions(options);
784    this.onComplete = this.options.onComplete;
785
786    this.frequency = (this.options.frequency || 2);
787    this.decay = (this.options.decay || 1);
788
789    this.updater = {};
790    this.container = container;
791    this.url = url;
792
793    this.start();
794  },
795
796  start: function() {
797    this.options.onComplete = this.updateComplete.bind(this);
798    this.onTimerEvent();
799  },
800
801  stop: function() {
802    this.updater.onComplete = undefined;
803    clearTimeout(this.timer);
804    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
805  },
806
807  updateComplete: function(request) {
808    if (this.options.decay) {
809      this.decay = (request.responseText == this.lastText ?
810        this.decay * this.options.decay : 1);
811
812      this.lastText = request.responseText;
813    }
814    this.timer = setTimeout(this.onTimerEvent.bind(this),
815      this.decay * this.frequency * 1000);
816  },
817
818  onTimerEvent: function() {
819    this.updater = new Ajax.Updater(this.container, this.url, this.options);
820  }
821});
822document.getElementsByClassName = function(className, parentElement) {
823  var children = ($(parentElement) || document.body).getElementsByTagName('*');
824  return $A(children).inject([], function(elements, child) {
825    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
826      elements.push(child);
827    return elements;
828  });
829}
830
831/*--------------------------------------------------------------------------*/
832
833if (!window.Element) {
834  var Element = new Object();
835}
836
837Object.extend(Element, {
838  visible: function(element) {
839    return $(element).style.display != 'none';
840  },
841
842  toggle: function() {
843    for (var i = 0; i < arguments.length; i++) {
844      var element = $(arguments[i]);
845      Element[Element.visible(element) ? 'hide' : 'show'](element);
846    }
847  },
848
849  hide: function() {
850    for (var i = 0; i < arguments.length; i++) {
851      var element = $(arguments[i]);
852      element.style.display = 'none';
853    }
854  },
855
856  show: function() {
857    for (var i = 0; i < arguments.length; i++) {
858      var element = $(arguments[i]);
859      element.style.display = '';
860    }
861  },
862
863  remove: function(element) {
864    element = $(element);
865    element.parentNode.removeChild(element);
866  },
867
868  update: function(element, html) {
869    $(element).innerHTML = html.stripScripts();
870    setTimeout(function() {html.evalScripts()}, 10);
871  },
872
873  getHeight: function(element) {
874    element = $(element);
875    return element.offsetHeight;
876  },
877
878  classNames: function(element) {
879    return new Element.ClassNames(element);
880  },
881
882  hasClassName: function(element, className) {
883    if (!(element = $(element))) return;
884    return Element.classNames(element).include(className);
885  },
886
887  addClassName: function(element, className) {
888    if (!(element = $(element))) return;
889    return Element.classNames(element).add(className);
890  },
891
892  removeClassName: function(element, className) {
893    if (!(element = $(element))) return;
894    return Element.classNames(element).remove(className);
895  },
896
897  // removes whitespace-only text node children
898  cleanWhitespace: function(element) {
899    element = $(element);
900    for (var i = 0; i < element.childNodes.length; i++) {
901      var node = element.childNodes[i];
902      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
903        Element.remove(node);
904    }
905  },
906
907  empty: function(element) {
908    return $(element).innerHTML.match(/^\s*$/);
909  },
910
911  scrollTo: function(element) {
912    element = $(element);
913    var x = element.x ? element.x : element.offsetLeft,
914        y = element.y ? element.y : element.offsetTop;
915    window.scrollTo(x, y);
916  },
917
918  getStyle: function(element, style) {
919    element = $(element);
920    var value = element.style[style.camelize()];
921    if (!value) {
922      if (document.defaultView && document.defaultView.getComputedStyle) {
923        var css = document.defaultView.getComputedStyle(element, null);
924        value = css ? css.getPropertyValue(style) : null;
925      } else if (element.currentStyle) {
926        value = element.currentStyle[style.camelize()];
927      }
928    }
929
930    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
931      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
932
933    return value == 'auto' ? null : value;
934  },
935
936  setStyle: function(element, style) {
937    element = $(element);
938    for (name in style)
939      element.style[name.camelize()] = style[name];
940  },
941
942  getDimensions: function(element) {
943    element = $(element);
944    if (Element.getStyle(element, 'display') != 'none')
945      return {width: element.offsetWidth, height: element.offsetHeight};
946
947    // All *Width and *Height properties give 0 on elements with display none,
948    // so enable the element temporarily
949    var els = element.style;
950    var originalVisibility = els.visibility;
951    var originalPosition = els.position;
952    els.visibility = 'hidden';
953    els.position = 'absolute';
954    els.display = '';
955    var originalWidth = element.clientWidth;
956    var originalHeight = element.clientHeight;
957    els.display = 'none';
958    els.position = originalPosition;
959    els.visibility = originalVisibility;
960    return {width: originalWidth, height: originalHeight};
961  },
962
963  makePositioned: function(element) {
964    element = $(element);
965    var pos = Element.getStyle(element, 'position');
966    if (pos == 'static' || !pos) {
967      element._madePositioned = true;
968      element.style.position = 'relative';
969      // Opera returns the offset relative to the positioning context, when an
970      // element is position relative but top and left have not been defined
971      if (window.opera) {
972        element.style.top = 0;
973        element.style.left = 0;
974      }
975    }
976  },
977
978  undoPositioned: function(element) {
979    element = $(element);
980    if (element._madePositioned) {
981      element._madePositioned = undefined;
982      element.style.position =
983        element.style.top =
984        element.style.left =
985        element.style.bottom =
986        element.style.right = '';
987    }
988  },
989
990  makeClipping: function(element) {
991    element = $(element);
992    if (element._overflow) return;
993    element._overflow = element.style.overflow;
994    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
995      element.style.overflow = 'hidden';
996  },
997
998  undoClipping: function(element) {
999    element = $(element);
1000    if (element._overflow) return;
1001    element.style.overflow = element._overflow;
1002    element._overflow = undefined;
1003  }
1004});
1005
1006var Toggle = new Object();
1007Toggle.display = Element.toggle;
1008
1009/*--------------------------------------------------------------------------*/
1010
1011Abstract.Insertion = function(adjacency) {
1012  this.adjacency = adjacency;
1013}
1014
1015Abstract.Insertion.prototype = {
1016  initialize: function(element, content) {
1017    this.element = $(element);
1018    this.content = content.stripScripts();
1019
1020    if (this.adjacency && this.element.insertAdjacentHTML) {
1021      try {
1022        this.element.insertAdjacentHTML(this.adjacency, this.content);
1023      } catch (e) {
1024        if (this.element.tagName.toLowerCase() == 'tbody') {
1025          this.insertContent(this.contentFromAnonymousTable());
1026        } else {
1027          throw e;
1028        }
1029      }
1030    } else {
1031      this.range = this.element.ownerDocument.createRange();
1032      if (this.initializeRange) this.initializeRange();
1033      this.insertContent([this.range.createContextualFragment(this.content)]);
1034    }
1035
1036    setTimeout(function() {content.evalScripts()}, 10);
1037  },
1038
1039  contentFromAnonymousTable: function() {
1040    var div = document.createElement('div');
1041    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1042    return $A(div.childNodes[0].childNodes[0].childNodes);
1043  }
1044}
1045
1046var Insertion = new Object();
1047
1048Insertion.Before = Class.create();
1049Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1050  initializeRange: function() {
1051    this.range.setStartBefore(this.element);
1052  },
1053
1054  insertContent: function(fragments) {
1055    fragments.each((function(fragment) {
1056      this.element.parentNode.insertBefore(fragment, this.element);
1057    }).bind(this));
1058  }
1059});
1060
1061Insertion.Top = Class.create();
1062Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1063  initializeRange: function() {
1064    this.range.selectNodeContents(this.element);
1065    this.range.collapse(true);
1066  },
1067
1068  insertContent: function(fragments) {
1069    fragments.reverse(false).each((function(fragment) {
1070      this.element.insertBefore(fragment, this.element.firstChild);
1071    }).bind(this));
1072  }
1073});
1074
1075Insertion.Bottom = Class.create();
1076Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1077  initializeRange: function() {
1078    this.range.selectNodeContents(this.element);
1079    this.range.collapse(this.element);
1080  },
1081
1082  insertContent: function(fragments) {
1083    fragments.each((function(fragment) {
1084      this.element.appendChild(fragment);
1085    }).bind(this));
1086  }
1087});
1088
1089Insertion.After = Class.create();
1090Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1091  initializeRange: function() {
1092    this.range.setStartAfter(this.element);
1093  },
1094
1095  insertContent: function(fragments) {
1096    fragments.each((function(fragment) {
1097      this.element.parentNode.insertBefore(fragment,
1098        this.element.nextSibling);
1099    }).bind(this));
1100  }
1101});
1102
1103/*--------------------------------------------------------------------------*/
1104
1105Element.ClassNames = Class.create();
1106Element.ClassNames.prototype = {
1107  initialize: function(element) {
1108    this.element = $(element);
1109  },
1110
1111  _each: function(iterator) {
1112    this.element.className.split(/\s+/).select(function(name) {
1113      return name.length > 0;
1114    })._each(iterator);
1115  },
1116
1117  set: function(className) {
1118    this.element.className = className;
1119  },
1120
1121  add: function(classNameToAdd) {
1122    if (this.include(classNameToAdd)) return;
1123    this.set(this.toArray().concat(classNameToAdd).join(' '));
1124  },
1125
1126  remove: function(classNameToRemove) {
1127    if (!this.include(classNameToRemove)) return;
1128    this.set(this.select(function(className) {
1129      return className != classNameToRemove;
1130    }).join(' '));
1131  },
1132
1133  toString: function() {
1134    return this.toArray().join(' ');
1135  }
1136}
1137
1138Object.extend(Element.ClassNames.prototype, Enumerable);
1139var Field = {
1140  clear: function() {
1141    for (var i = 0; i < arguments.length; i++)
1142      $(arguments[i]).value = '';
1143  },
1144
1145  focus: function(element) {
1146    $(element).focus();
1147  },
1148
1149  present: function() {
1150    for (var i = 0; i < arguments.length; i++)
1151      if ($(arguments[i]).value == '') return false;
1152    return true;
1153  },
1154
1155  select: function(element) {
1156    $(element).select();
1157  },
1158
1159  activate: function(element) {
1160    element = $(element);
1161    element.focus();
1162    if (element.select)
1163      element.select();
1164  }
1165}
1166
1167/*--------------------------------------------------------------------------*/
1168
1169var Form = {
1170  serialize: function(form) {
1171    var elements = Form.getElements($(form));
1172    var queryComponents = new Array();
1173
1174    for (var i = 0; i < elements.length; i++) {
1175      var queryComponent = Form.Element.serialize(elements[i]);
1176      if (queryComponent)
1177        queryComponents.push(queryComponent);
1178    }
1179
1180    return queryComponents.join('&');
1181  },
1182
1183  getElements: function(form) {
1184    form = $(form);
1185    var elements = new Array();
1186
1187    for (tagName in Form.Element.Serializers) {
1188      var tagElements = form.getElementsByTagName(tagName);
1189      for (var j = 0; j < tagElements.length; j++)
1190        elements.push(tagElements[j]);
1191    }
1192    return elements;
1193  },
1194
1195  getInputs: function(form, typeName, name) {
1196    form = $(form);
1197    var inputs = form.getElementsByTagName('input');
1198
1199    if (!typeName && !name)
1200      return inputs;
1201
1202    var matchingInputs = new Array();
1203    for (var i = 0; i < inputs.length; i++) {
1204      var input = inputs[i];
1205      if ((typeName && input.type != typeName) ||
1206          (name && input.name != name))
1207        continue;
1208      matchingInputs.push(input);
1209    }
1210
1211    return matchingInputs;
1212  },
1213
1214  disable: function(form) {
1215    var elements = Form.getElements(form);
1216    for (var i = 0; i < elements.length; i++) {
1217      var element = elements[i];
1218      element.blur();
1219      element.disabled = 'true';
1220    }
1221  },
1222
1223  enable: function(form) {
1224    var elements = Form.getElements(form);
1225    for (var i = 0; i < elements.length; i++) {
1226      var element = elements[i];
1227      element.disabled = '';
1228    }
1229  },
1230
1231  findFirstElement: function(form) {
1232    return Form.getElements(form).find(function(element) {
1233      return element.type != 'hidden' && !element.disabled &&
1234        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1235    });
1236  },
1237
1238  focusFirstElement: function(form) {
1239    Field.activate(Form.findFirstElement(form));
1240  },
1241
1242  reset: function(form) {
1243    $(form).reset();
1244  }
1245}
1246
1247Form.Element = {
1248  serialize: function(element) {
1249    element = $(element);
1250    var method = element.tagName.toLowerCase();
1251    var parameter = Form.Element.Serializers[method](element);
1252
1253    if (parameter) {
1254      var key = encodeURIComponent(parameter[0]);
1255      if (key.length == 0) return;
1256
1257      if (parameter[1].constructor != Array)
1258        parameter[1] = [parameter[1]];
1259
1260      return parameter[1].map(function(value) {
1261        return key + '=' + encodeURIComponent(value);
1262      }).join('&');
1263    }
1264  },
1265
1266  getValue: function(element) {
1267    element = $(element);
1268    var method = element.tagName.toLowerCase();
1269    var parameter = Form.Element.Serializers[method](element);
1270
1271    if (parameter)
1272      return parameter[1];
1273  }
1274}
1275
1276Form.Element.Serializers = {
1277  input: function(element) {
1278    switch (element.type.toLowerCase()) {
1279      case 'submit':
1280      case 'hidden':
1281      case 'password':
1282      case 'text':
1283        return Form.Element.Serializers.textarea(element);
1284      case 'checkbox':
1285      case 'radio':
1286        return Form.Element.Serializers.inputSelector(element);
1287    }
1288    return false;
1289  },
1290
1291  inputSelector: function(element) {
1292    if (element.checked)
1293      return [element.name, element.value];
1294  },
1295
1296  textarea: function(element) {
1297    return [element.name, element.value];
1298  },
1299
1300  select: function(element) {
1301    return Form.Element.Serializers[element.type == 'select-one' ?
1302      'selectOne' : 'selectMany'](element);
1303  },
1304
1305  selectOne: function(element) {
1306    var value = '', opt, index = element.selectedIndex;
1307    if (index >= 0) {
1308      opt = element.options[index];
1309      value = opt.value;
1310      if (!value && !('value' in opt))
1311        value = opt.text;
1312    }
1313    return [element.name, value];
1314  },
1315
1316  selectMany: function(element) {
1317    var value = new Array();
1318    for (var i = 0; i < element.length; i++) {
1319      var opt = element.options[i];
1320      if (opt.selected) {
1321        var optValue = opt.value;
1322        if (!optValue && !('value' in opt))
1323          optValue = opt.text;
1324        value.push(optValue);
1325      }
1326    }
1327    return [element.name, value];
1328  }
1329}
1330
1331/*--------------------------------------------------------------------------*/
1332
1333var $F = Form.Element.getValue;
1334
1335/*--------------------------------------------------------------------------*/
1336
1337Abstract.TimedObserver = function() {}
1338Abstract.TimedObserver.prototype = {
1339  initialize: function(element, frequency, callback) {
1340    this.frequency = frequency;
1341    this.element   = $(element);
1342    this.callback  = callback;
1343
1344    this.lastValue = this.getValue();
1345    this.registerCallback();
1346  },
1347
1348  registerCallback: function() {
1349    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
1350  },
1351
1352  onTimerEvent: function() {
1353    var value = this.getValue();
1354    if (this.lastValue != value) {
1355      this.callback(this.element, value);
1356      this.lastValue = value;
1357    }
1358  }
1359}
1360
1361Form.Element.Observer = Class.create();
1362Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1363  getValue: function() {
1364    return Form.Element.getValue(this.element);
1365  }
1366});
1367
1368Form.Observer = Class.create();
1369Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1370  getValue: function() {
1371    return Form.serialize(this.element);
1372  }
1373});
1374
1375/*--------------------------------------------------------------------------*/
1376
1377Abstract.EventObserver = function() {}
1378Abstract.EventObserver.prototype = {
1379  initialize: function(element, callback) {
1380    this.element  = $(element);
1381    this.callback = callback;
1382
1383    this.lastValue = this.getValue();
1384    if (this.element.tagName.toLowerCase() == 'form')
1385      this.registerFormCallbacks();
1386    else
1387      this.registerCallback(this.element);
1388  },
1389
1390  onElementEvent: function() {
1391    var value = this.getValue();
1392    if (this.lastValue != value) {
1393      this.callback(this.element, value);
1394      this.lastValue = value;
1395    }
1396  },
1397
1398  registerFormCallbacks: function() {
1399    var elements = Form.getElements(this.element);
1400    for (var i = 0; i < elements.length; i++)
1401      this.registerCallback(elements[i]);
1402  },
1403
1404  registerCallback: function(element) {
1405    if (element.type) {
1406      switch (element.type.toLowerCase()) {
1407        case 'checkbox':
1408        case 'radio':
1409          Event.observe(element, 'click', this.onElementEvent.bind(this));
1410          break;
1411        case 'password':
1412        case 'text':
1413        case 'textarea':
1414        case 'select-one':
1415        case 'select-multiple':
1416          Event.observe(element, 'change', this.onElementEvent.bind(this));
1417          break;
1418      }
1419    }
1420  }
1421}
1422
1423Form.Element.EventObserver = Class.create();
1424Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1425  getValue: function() {
1426    return Form.Element.getValue(this.element);
1427  }
1428});
1429
1430Form.EventObserver = Class.create();
1431Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1432  getValue: function() {
1433    return Form.serialize(this.element);
1434  }
1435});
1436if (!window.Event) {
1437  var Event = new Object();
1438}
1439
1440Object.extend(Event, {
1441  KEY_BACKSPACE: 8,
1442  KEY_TAB:       9,
1443  KEY_RETURN:   13,
1444  KEY_ESC:      27,
1445  KEY_LEFT:     37,
1446  KEY_UP:       38,
1447  KEY_RIGHT:    39,
1448  KEY_DOWN:     40,
1449  KEY_DELETE:   46,
1450
1451  element: function(event) {
1452    return event.target || event.srcElement;
1453  },
1454
1455  isLeftClick: function(event) {
1456    return (((event.which) && (event.which == 1)) ||
1457            ((event.button) && (event.button == 1)));
1458  },
1459
1460  pointerX: function(event) {
1461    return event.pageX || (event.clientX +
1462      (document.documentElement.scrollLeft || document.body.scrollLeft));
1463  },
1464
1465  pointerY: function(event) {
1466    return event.pageY || (event.clientY +
1467      (document.documentElement.scrollTop || document.body.scrollTop));
1468  },
1469
1470  stop: function(event) {
1471    if (event.preventDefault) {
1472      event.preventDefault();
1473      event.stopPropagation();
1474    } else {
1475      event.returnValue = false;
1476      event.cancelBubble = true;
1477    }
1478  },
1479
1480  // find the first node with the given tagName, starting from the
1481  // node the event was triggered on; traverses the DOM upwards
1482  findElement: function(event, tagName) {
1483    var element = Event.element(event);
1484    while (element.parentNode && (!element.tagName ||
1485        (element.tagName.toUpperCase() != tagName.toUpperCase())))
1486      element = element.parentNode;
1487    return element;
1488  },
1489
1490  observers: false,
1491
1492  _observeAndCache: function(element, name, observer, useCapture) {
1493    if (!this.observers) this.observers = [];
1494    if (element.addEventListener) {
1495      this.observers.push([element, name, observer, useCapture]);
1496      element.addEventListener(name, observer, useCapture);
1497    } else if (element.attachEvent) {
1498      this.observers.push([element, name, observer, useCapture]);
1499      element.attachEvent('on' + name, observer);
1500    }
1501  },
1502
1503  unloadCache: function() {
1504    if (!Event.observers) return;
1505    for (var i = 0; i < Event.observers.length; i++) {
1506      Event.stopObserving.apply(this, Event.observers[i]);
1507      Event.observers[i][0] = null;
1508    }
1509    Event.observers = false;
1510  },
1511
1512  observe: function(element, name, observer, useCapture) {
1513    var element = $(element);
1514    useCapture = useCapture || false;
1515
1516    if (name == 'keypress' &&
1517        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1518        || element.attachEvent))
1519      name = 'keydown';
1520
1521    this._observeAndCache(element, name, observer, useCapture);
1522  },
1523
1524  stopObserving: function(element, name, observer, useCapture) {
1525    var element = $(element);
1526    useCapture = useCapture || false;
1527
1528    if (name == 'keypress' &&
1529        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1530        || element.detachEvent))
1531      name = 'keydown';
1532
1533    if (element.removeEventListener) {
1534      element.removeEventListener(name, observer, useCapture);
1535    } else if (element.detachEvent) {
1536      element.detachEvent('on' + name, observer);
1537    }
1538  }
1539});
1540
1541/* prevent memory leaks in IE */
1542Event.observe(window, 'unload', Event.unloadCache, false);
1543var Position = {
1544  // set to true if needed, warning: firefox performance problems
1545  // NOT neeeded for page scrolling, only if draggable contained in
1546  // scrollable elements
1547  includeScrollOffsets: false,
1548
1549  // must be called before calling withinIncludingScrolloffset, every time the
1550  // page is scrolled
1551  prepare: function() {
1552    this.deltaX =  window.pageXOffset
1553                || document.documentElement.scrollLeft
1554                || document.body.scrollLeft
1555                || 0;
1556    this.deltaY =  window.pageYOffset
1557                || document.documentElement.scrollTop
1558                || document.body.scrollTop
1559                || 0;
1560  },
1561
1562  realOffset: function(element) {
1563    var valueT = 0, valueL = 0;
1564    do {
1565      valueT += element.scrollTop  || 0;
1566      valueL += element.scrollLeft || 0;
1567      element = element.parentNode;
1568    } while (element);
1569    return [valueL, valueT];
1570  },
1571
1572  cumulativeOffset: function(element) {
1573    var valueT = 0, valueL = 0;
1574    do {
1575      valueT += element.offsetTop  || 0;
1576      valueL += element.offsetLeft || 0;
1577      element = element.offsetParent;
1578    } while (element);
1579    return [valueL, valueT];
1580  },
1581
1582  positionedOffset: function(element) {
1583    var valueT = 0, valueL = 0;
1584    do {
1585      valueT += element.offsetTop  || 0;
1586      valueL += element.offsetLeft || 0;
1587      element = element.offsetParent;
1588      if (element) {
1589        p = Element.getStyle(element, 'position');
1590        if (p == 'relative' || p == 'absolute') break;
1591      }
1592    } while (element);
1593    return [valueL, valueT];
1594  },
1595
1596  offsetParent: function(element) {
1597    if (element.offsetParent) return element.offsetParent;
1598    if (element == document.body) return element;
1599
1600    while ((element = element.parentNode) && element != document.body)
1601      if (Element.getStyle(element, 'position') != 'static')
1602        return element;
1603
1604    return document.body;
1605  },
1606
1607  // caches x/y coordinate pair to use with overlap
1608  within: function(element, x, y) {
1609    if (this.includeScrollOffsets)
1610      return this.withinIncludingScrolloffsets(element, x, y);
1611    this.xcomp = x;
1612    this.ycomp = y;
1613    this.offset = this.cumulativeOffset(element);
1614
1615    return (y >= this.offset[1] &&
1616            y <  this.offset[1] + element.offsetHeight &&
1617            x >= this.offset[0] &&
1618            x <  this.offset[0] + element.offsetWidth);
1619  },
1620
1621  withinIncludingScrolloffsets: function(element, x, y) {
1622    var offsetcache = this.realOffset(element);
1623
1624    this.xcomp = x + offsetcache[0] - this.deltaX;
1625    this.ycomp = y + offsetcache[1] - this.deltaY;
1626    this.offset = this.cumulativeOffset(element);
1627
1628    return (this.ycomp >= this.offset[1] &&
1629            this.ycomp <  this.offset[1] + element.offsetHeight &&
1630            this.xcomp >= this.offset[0] &&
1631            this.xcomp <  this.offset[0] + element.offsetWidth);
1632  },
1633
1634  // within must be called directly before
1635  overlap: function(mode, element) {
1636    if (!mode) return 0;
1637    if (mode == 'vertical')
1638      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
1639        element.offsetHeight;
1640    if (mode == 'horizontal')
1641      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
1642        element.offsetWidth;
1643  },
1644
1645  clone: function(source, target) {
1646    source = $(source);
1647    target = $(target);
1648    target.style.position = 'absolute';
1649    var offsets = this.cumulativeOffset(source);
1650    target.style.top    = offsets[1] + 'px';
1651    target.style.left   = offsets[0] + 'px';
1652    target.style.width  = source.offsetWidth + 'px';
1653    target.style.height = source.offsetHeight + 'px';
1654  },
1655
1656  page: function(forElement) {
1657    var valueT = 0, valueL = 0;
1658
1659    var element = forElement;
1660    do {
1661      valueT += element.offsetTop  || 0;
1662      valueL += element.offsetLeft || 0;
1663
1664      // Safari fix
1665      if (element.offsetParent==document.body)
1666        if (Element.getStyle(element,'position')=='absolute') break;
1667
1668    } while (element = element.offsetParent);
1669
1670    element = forElement;
1671    do {
1672      valueT -= element.scrollTop  || 0;
1673      valueL -= element.scrollLeft || 0;
1674    } while (element = element.parentNode);
1675
1676    return [valueL, valueT];
1677  },
1678
1679  clone: function(source, target) {
1680    var options = Object.extend({
1681      setLeft:    true,
1682      setTop:     true,
1683      setWidth:   true,
1684      setHeight:  true,
1685      offsetTop:  0,
1686      offsetLeft: 0
1687    }, arguments[2] || {})
1688
1689    // find page position of source
1690    source = $(source);
1691    var p = Position.page(source);
1692
1693    // find coordinate system to use
1694    target = $(target);
1695    var delta = [0, 0];
1696    var parent = null;
1697    // delta [0,0] will do fine with position: fixed elements,
1698    // position:absolute needs offsetParent deltas
1699    if (Element.getStyle(target,'position') == 'absolute') {
1700      parent = Position.offsetParent(target);
1701      delta = Position.page(parent);
1702    }
1703
1704    // correct by body offsets (fixes Safari)
1705    if (parent == document.body) {
1706      delta[0] -= document.body.offsetLeft;
1707      delta[1] -= document.body.offsetTop;
1708    }
1709
1710    // set position
1711    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
1712    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
1713    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
1714    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
1715  },
1716
1717  absolutize: function(element) {
1718    element = $(element);
1719    if (element.style.position == 'absolute') return;
1720    Position.prepare();
1721
1722    var offsets = Position.positionedOffset(element);
1723    var top     = offsets[1];
1724    var left    = offsets[0];
1725    var width   = element.clientWidth;
1726    var height  = element.clientHeight;
1727
1728    element._originalLeft   = left - parseFloat(element.style.left  || 0);
1729    element._originalTop    = top  - parseFloat(element.style.top || 0);
1730    element._originalWidth  = element.style.width;
1731    element._originalHeight = element.style.height;
1732
1733    element.style.position = 'absolute';
1734    element.style.top    = top + 'px';;
1735    element.style.left   = left + 'px';;
1736    element.style.width  = width + 'px';;
1737    element.style.height = height + 'px';;
1738  },
1739
1740  relativize: function(element) {
1741    element = $(element);
1742    if (element.style.position == 'relative') return;
1743    Position.prepare();
1744
1745    element.style.position = 'relative';
1746    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
1747    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1748
1749    element.style.top    = top + 'px';
1750    element.style.left   = left + 'px';
1751    element.style.height = element._originalHeight;
1752    element.style.width  = element._originalWidth;
1753  }
1754}
1755
1756if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1757  Position.cumulativeOffset = function(element) {
1758    var valueT = 0, valueL = 0;
1759    do {
1760      valueT += element.offsetTop  || 0;
1761      valueL += element.offsetLeft || 0;
1762      if (element.offsetParent == document.body)
1763        if (Element.getStyle(element, 'position') == 'absolute') break;
1764
1765      element = element.offsetParent;
1766    } while (element);
1767
1768    return [valueL, valueT];
1769  }
1770}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.