[ Index ]
 

Code source de PRADO 3.0.6

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/framework/Web/Javascripts/js/debug/ -> prado.js (source)

   1  /*  Prototype JavaScript framework, version <%= PROTOTYPE_VERSION %>
   2   *  (c) 2005 Sam Stephenson <sam@conio.net>
   3   *
   4   *  Prototype is freely distributable under the terms of an MIT-style license.
   5   *  For details, see the Prototype web site: http://prototype.conio.net/
   6   *
   7  /*--------------------------------------------------------------------------*/
   8  
   9  var Prototype = {
  10    Version: '1.50',
  11    ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
  12    
  13    emptyFunction: function() {},
  14    K: function(x) {return x}
  15  }
  16  
  17  /*
  18  <%= include 'base.js', 'string.js' %>
  19  
  20  <%= include 'enumerable.js', 'array.js', 'hash.js', 'range.js' %>
  21  
  22  <%= include 'ajax.js', 'dom.js', 'selector.js', 'form.js', 'event.js', 'position.js' %>
  23  
  24  */
  25  
  26  var Class = {
  27    create: function() {
  28      return function() { 
  29        this.initialize.apply(this, arguments);
  30      }
  31    }
  32  }
  33  
  34  var Abstract = new Object();
  35  
  36  Object.extend = function(destination, source) {
  37    for (var property in source) {
  38      destination[property] = source[property];
  39    }
  40    return destination;
  41  }
  42  
  43  Object.inspect = function(object) {
  44    try {
  45      if (object == undefined) return 'undefined';
  46      if (object == null) return 'null';
  47      return object.inspect ? object.inspect() : object.toString();
  48    } catch (e) {
  49      if (e instanceof RangeError) return '...';
  50      throw e;
  51    }
  52  }
  53  
  54  Function.prototype.bind = function() {
  55    var __method = this, args = $A(arguments), object = args.shift();
  56    return function() {
  57      return __method.apply(object, args.concat($A(arguments)));
  58    }
  59  }
  60  
  61  Function.prototype.bindAsEventListener = function(object) {
  62    var __method = this;
  63    return function(event) {
  64      return __method.call(object, event || window.event);
  65    }
  66  }
  67  
  68  Object.extend(Number.prototype, {
  69    toColorPart: function() {
  70      var digits = this.toString(16);
  71      if (this < 16) return '0' + digits;
  72      return digits;
  73    },
  74  
  75    succ: function() {
  76      return this + 1;
  77    },
  78    
  79    times: function(iterator) {
  80      $R(0, this, true).each(iterator);
  81      return this;
  82    }
  83  });
  84  
  85  var Try = {
  86    these: function() {
  87      var returnValue;
  88  
  89      for (var i = 0; i < arguments.length; i++) {
  90        var lambda = arguments[i];
  91        try {
  92          returnValue = lambda();
  93          break;
  94        } catch (e) {}
  95      }
  96  
  97      return returnValue;
  98    }
  99  }
 100  
 101  /*--------------------------------------------------------------------------*/
 102  
 103  var PeriodicalExecuter = Class.create();
 104  PeriodicalExecuter.prototype = {
 105    initialize: function(callback, frequency) {
 106      this.callback = callback;
 107      this.frequency = frequency;
 108      this.currentlyExecuting = false;
 109  
 110      this.registerCallback();
 111    },
 112  
 113    registerCallback: function() {
 114      setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
 115    },
 116  
 117    onTimerEvent: function() {
 118      if (!this.currentlyExecuting) {
 119        try { 
 120          this.currentlyExecuting = true;
 121          this.callback(); 
 122        } finally { 
 123          this.currentlyExecuting = false;
 124        }
 125      }
 126    }
 127  }
 128  
 129  
 130  
 131  /**
 132   * Similar to bindAsEventLister, but takes additional arguments.
 133   */
 134  Function.prototype.bindEvent = function() 
 135  {
 136      var __method = this, args = $A(arguments), object = args.shift();
 137      return function(event) 
 138      {
 139          return __method.apply(object, [event || window.event].concat(args));
 140      }
 141  }
 142  
 143  /**
 144   * Creates a new function by copying function definition from
 145   * the <tt>base</tt> and optional <tt>definition</tt>.
 146   * @param function a base function to copy from.
 147   * @param array additional definition
 148   * @param function return a new function with definition from both
 149   * <tt>base</tt> and <tt>definition</tt>.
 150   */
 151  Class.extend = function(base, definition)
 152  {
 153          var component = Class.create();
 154          Object.extend(component.prototype, base.prototype);
 155          if(definition) 
 156              Object.extend(component.prototype, definition);
 157          return component;
 158  }
 159  
 160  Object.extend(String.prototype, {
 161    gsub: function(pattern, replacement) {
 162      var result = '', source = this, match;
 163      replacement = arguments.callee.prepareReplacement(replacement);
 164      
 165      while (source.length > 0) {
 166        if (match = source.match(pattern)) {
 167          result += source.slice(0, match.index);
 168          result += (replacement(match) || '').toString();
 169          source  = source.slice(match.index + match[0].length);
 170        } else {
 171          result += source, source = '';
 172        }
 173      }
 174      return result;
 175    },
 176    
 177    sub: function(pattern, replacement, count) {
 178      replacement = this.gsub.prepareReplacement(replacement);
 179      count = count === undefined ? 1 : count;
 180      
 181      return this.gsub(pattern, function(match) {
 182        if (--count < 0) return match[0];
 183        return replacement(match);
 184      });
 185    },
 186    
 187    scan: function(pattern, iterator) {
 188      this.gsub(pattern, iterator);
 189      return this;
 190    },
 191    
 192    truncate: function(length, truncation) {
 193      length = length || 30;
 194      truncation = truncation === undefined ? '...' : truncation;
 195      return this.length > length ? 
 196        this.slice(0, length - truncation.length) + truncation : this;
 197    },
 198  
 199    strip: function() {
 200      return this.replace(/^\s+/, '').replace(/\s+$/, '');
 201    },
 202    
 203    stripTags: function() {
 204      return this.replace(/<\/?[^>]+>/gi, '');
 205    },
 206  
 207    stripScripts: function() {
 208      return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
 209    },
 210    
 211    extractScripts: function() {
 212      var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
 213      var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
 214      return (this.match(matchAll) || []).map(function(scriptTag) {
 215        return (scriptTag.match(matchOne) || ['', ''])[1];
 216      });
 217    },
 218    
 219    evalScripts: function() {
 220      return this.extractScripts().map(function(script) { return eval(script) });
 221    },
 222  
 223    escapeHTML: function() {
 224      var div = document.createElement('div');
 225      var text = document.createTextNode(this);
 226      div.appendChild(text);
 227      return div.innerHTML;
 228    },
 229  
 230    unescapeHTML: function() {
 231      var div = document.createElement('div');
 232      div.innerHTML = this.stripTags();
 233      return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
 234    },
 235    
 236    toQueryParams: function() {
 237      var pairs = this.match(/^\??(.*)$/)[1].split('&');
 238      return pairs.inject({}, function(params, pairString) {
 239        var pair = pairString.split('=');
 240        params[pair[0]] = pair[1];
 241        return params;
 242      });
 243    },
 244    
 245    toArray: function() {
 246      return this.split('');
 247    },
 248    
 249    camelize: function() {
 250      var oStringList = this.split('-');
 251      if (oStringList.length == 1) return oStringList[0];
 252        
 253      var camelizedString = this.indexOf('-') == 0
 254        ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 
 255        : oStringList[0];
 256        
 257      for (var i = 1, len = oStringList.length; i < len; i++) {
 258        var s = oStringList[i];
 259        camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
 260      }
 261      
 262      return camelizedString;
 263    },
 264  
 265    inspect: function() {
 266      return "'" + this.replace(/\\/g, '\\\\').replace(/'/g, '\\\'') + "'";
 267    }
 268  });
 269  
 270  String.prototype.gsub.prepareReplacement = function(replacement) {
 271    if (typeof replacement == 'function') return replacement;
 272    var template = new Template(replacement);
 273    return function(match) { return template.evaluate(match) };
 274  }
 275  
 276  String.prototype.parseQuery = String.prototype.toQueryParams;
 277  
 278  var Template = Class.create();
 279  Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
 280  Template.prototype = {
 281    initialize: function(template, pattern) {
 282      this.template = template.toString();
 283      this.pattern  = pattern || Template.Pattern;
 284    },
 285    
 286    evaluate: function(object) {
 287      return this.template.gsub(this.pattern, function(match) {
 288        var before = match[1];
 289        if (before == '\\') return match[2];
 290        return before + (object[match[3]] || '').toString();
 291      });
 292    }
 293  }
 294  
 295  
 296  /**
 297   * @class String extensions
 298   */
 299  Object.extend(String.prototype, {
 300      /**
 301       * @param {String} "left" to pad the string on the left, "right" to pad right.
 302       * @param {Number} minimum string length.
 303       * @param {String} character(s) to pad 
 304       * @return {String} padded character(s) on the left or right to satisfy minimum string length
 305       */
 306  
 307      pad : function(side, len, chr) {
 308          if (!chr) chr = ' ';
 309          var s = this;
 310          var left = side.toLowerCase()=='left';
 311          while (s.length<len) s = left? chr + s : s + chr;
 312          return s;
 313      },
 314  
 315      /**
 316       * @param {Number} minimum string length.
 317       * @param {String} character(s) to pad 
 318       * @return {String} padded character(s) on the left to satisfy minimum string length
 319       */
 320      padLeft : function(len, chr) {
 321          return this.pad('left',len,chr);
 322      },
 323  
 324      /**
 325       * @param {Number} minimum string length.
 326       * @param {String} character(s) to pad 
 327       * @return {String} padded character(s) on the right to satisfy minimum string length
 328       */
 329      padRight : function(len, chr) {
 330          return this.pad('right',len,chr);
 331      },
 332  
 333      /**
 334       * @param {Number} minimum string length.
 335       * @return {String} append zeros to the left to satisfy minimum string length.
 336       */
 337      zerofill : function(len) { 
 338          return this.padLeft(len,'0');
 339      },
 340  
 341      /**
 342       * @return {String} removed white spaces from both ends.
 343       */
 344      trim : function() { 
 345          return this.replace(/^\s+|\s+$/g,'');
 346      },
 347  
 348      /**
 349       * @return {String} removed white spaces from the left end.
 350       */
 351      trimLeft : function() { 
 352          return this.replace(/^\s+/,''); 
 353      },
 354  
 355      /**
 356       * @return {String} removed white spaces from the right end.
 357       */
 358      trimRight : function() { 
 359          return this.replace(/\s+$/,'');
 360      },
 361  
 362      /**
 363       * Convert period separated function names into a function reference.
 364       * e.g. "Prado.AJAX.Callback.Action.setValue".toFunction() will return
 365       * the actual function Prado.AJAX.Callback.Action.setValue()
 366       * @return {Function} the corresponding function represented by the string.
 367       */
 368      toFunction : function()
 369      {
 370          var commands = this.split(/\./);
 371          var command = window;
 372          commands.each(function(action)
 373          { 
 374              if(command[new String(action)]) 
 375                  command=command[new String(action)]; 
 376          });
 377          if(typeof(command) == "function")
 378              return command;
 379          else
 380          {
 381              if(typeof Logger != "undefined")
 382                  Logger.error("Missing function", this);
 383                  
 384              throw new Error	("Missing function '"+this+"'");
 385          }
 386      },
 387  
 388      /** 
 389       * Convert a string into integer, returns null if not integer.
 390       * @return {Number} null if string does not represent an integer.
 391       */
 392      toInteger : function()
 393      {
 394          var exp = /^\s*[-\+]?\d+\s*$/;
 395          if (this.match(exp) == null)
 396              return null;
 397          var num = parseInt(this, 10);
 398          return (isNaN(num) ? null : num);
 399      },
 400  
 401      /** 
 402       * Convert a string into a double/float value. <b>Internationalization 
 403       * is not supported</b>
 404       * @param {String} the decimal character
 405       * @return {Double} null if string does not represent a float value
 406       */
 407      toDouble : function(decimalchar)
 408      {
 409          if(this.length <= 0) return null;
 410          decimalchar = decimalchar || ".";
 411          var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$");
 412          var m = this.match(exp);
 413          
 414          if (m == null)    
 415              return null;
 416          m[1] = m[1] || "";
 417          m[2] = m[2] || "0";
 418          m[4] = m[4] || "0";
 419                  
 420          var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
 421          var num = parseFloat(cleanInput);
 422          return (isNaN(num) ? null : num);
 423      },
 424  
 425      /**
 426       * Convert strings that represent a currency value (e.g. a float with grouping 
 427       * characters) to float. E.g. "10,000.50" will become "10000.50". The number 
 428       * of dicimal digits, grouping and decimal characters can be specified.
 429       * <i>The currency input format is <b>very</b> strict, null will be returned if
 430       * the pattern does not match</i>.
 431       * @param {String} the grouping character, default is ","
 432       * @param {Number} number of decimal digits
 433       * @param {String} the decimal character, default is "."
 434       * @type {Double} the currency value as float.
 435       */
 436      toCurrency : function(groupchar, digits, decimalchar)
 437      {
 438          groupchar = groupchar || ",";
 439          decimalchar = decimalchar || ".";
 440          digits = typeof(digits) == "undefined" ? 2 : digits;
 441  
 442          var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)"
 443              + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "")
 444              + "\\s*$");
 445          var m = this.match(exp);
 446          if (m == null)
 447              return null;
 448          var intermed = m[2] + m[5] ;
 449          var cleanInput = m[1] + intermed.replace(
 450                  new RegExp("(\\" + groupchar + ")", "g"), "") 
 451                                  + ((digits > 0) ? "." + m[7] : "");
 452          var num = parseFloat(cleanInput);
 453          return (isNaN(num) ? null : num);
 454      },
 455  
 456      /**
 457       * Converts the string to a date by finding values that matches the 
 458       * date format pattern.
 459       * @param string date format pattern, e.g. MM-dd-yyyy
 460       * @return {Date} the date extracted from the string
 461       */
 462      toDate : function(format)
 463      {
 464          return Date.SimpleParse(this, format);
 465      }
 466  });
 467  
 468  var $break    = new Object();
 469  var $continue = new Object();
 470  
 471  var Enumerable = {
 472    each: function(iterator) {
 473      var index = 0;
 474      try {
 475        this._each(function(value) {
 476          try {
 477            iterator(value, index++);
 478          } catch (e) {
 479            if (e != $continue) throw e;
 480          }
 481        });
 482      } catch (e) {
 483        if (e != $break) throw e;
 484      }
 485    },
 486    
 487    all: function(iterator) {
 488      var result = true;
 489      this.each(function(value, index) {
 490        result = result && !!(iterator || Prototype.K)(value, index);
 491        if (!result) throw $break;
 492      });
 493      return result;
 494    },
 495    
 496    any: function(iterator) {
 497      var result = true;
 498      this.each(function(value, index) {
 499        if (result = !!(iterator || Prototype.K)(value, index)) 
 500          throw $break;
 501      });
 502      return result;
 503    },
 504    
 505    collect: function(iterator) {
 506      var results = [];
 507      this.each(function(value, index) {
 508        results.push(iterator(value, index));
 509      });
 510      return results;
 511    },
 512    
 513    detect: function (iterator) {
 514      var result;
 515      this.each(function(value, index) {
 516        if (iterator(value, index)) {
 517          result = value;
 518          throw $break;
 519        }
 520      });
 521      return result;
 522    },
 523    
 524    findAll: function(iterator) {
 525      var results = [];
 526      this.each(function(value, index) {
 527        if (iterator(value, index))
 528          results.push(value);
 529      });
 530      return results;
 531    },
 532    
 533    grep: function(pattern, iterator) {
 534      var results = [];
 535      this.each(function(value, index) {
 536        var stringValue = value.toString();
 537        if (stringValue.match(pattern))
 538          results.push((iterator || Prototype.K)(value, index));
 539      })
 540      return results;
 541    },
 542    
 543    include: function(object) {
 544      var found = false;
 545      this.each(function(value) {
 546        if (value == object) {
 547          found = true;
 548          throw $break;
 549        }
 550      });
 551      return found;
 552    },
 553    
 554    inject: function(memo, iterator) {
 555      this.each(function(value, index) {
 556        memo = iterator(memo, value, index);
 557      });
 558      return memo;
 559    },
 560    
 561    invoke: function(method) {
 562      var args = $A(arguments).slice(1);
 563      return this.collect(function(value) {
 564        return value[method].apply(value, args);
 565      });
 566    },
 567    
 568    max: function(iterator) {
 569      var result;
 570      this.each(function(value, index) {
 571        value = (iterator || Prototype.K)(value, index);
 572        if (result == undefined || value >= result)
 573          result = value;
 574      });
 575      return result;
 576    },
 577    
 578    min: function(iterator) {
 579      var result;
 580      this.each(function(value, index) {
 581        value = (iterator || Prototype.K)(value, index);
 582        if (result == undefined || value < result)
 583          result = value;
 584      });
 585      return result;
 586    },
 587    
 588    partition: function(iterator) {
 589      var trues = [], falses = [];
 590      this.each(function(value, index) {
 591        ((iterator || Prototype.K)(value, index) ? 
 592          trues : falses).push(value);
 593      });
 594      return [trues, falses];
 595    },
 596    
 597    pluck: function(property) {
 598      var results = [];
 599      this.each(function(value, index) {
 600        results.push(value[property]);
 601      });
 602      return results;
 603    },
 604    
 605    reject: function(iterator) {
 606      var results = [];
 607      this.each(function(value, index) {
 608        if (!iterator(value, index))
 609          results.push(value);
 610      });
 611      return results;
 612    },
 613    
 614    sortBy: function(iterator) {
 615      return this.collect(function(value, index) {
 616        return {value: value, criteria: iterator(value, index)};
 617      }).sort(function(left, right) {
 618        var a = left.criteria, b = right.criteria;
 619        return a < b ? -1 : a > b ? 1 : 0;
 620      }).pluck('value');
 621    },
 622    
 623    toArray: function() {
 624      return this.collect(Prototype.K);
 625    },
 626    
 627    zip: function() {
 628      var iterator = Prototype.K, args = $A(arguments);
 629      if (typeof args.last() == 'function')
 630        iterator = args.pop();
 631  
 632      var collections = [this].concat(args).map($A);
 633      return this.map(function(value, index) {
 634        return iterator(collections.pluck(index));
 635      });
 636    },
 637    
 638    inspect: function() {
 639      return '#<Enumerable:' + this.toArray().inspect() + '>';
 640    }
 641  }
 642  
 643  Object.extend(Enumerable, {
 644    map:     Enumerable.collect,
 645    find:    Enumerable.detect,
 646    select:  Enumerable.findAll,
 647    member:  Enumerable.include,
 648    entries: Enumerable.toArray
 649  });
 650  
 651  
 652  var $A = Array.from = function(iterable) {
 653    if (!iterable) return [];
 654    if (iterable.toArray) {
 655      return iterable.toArray();
 656    } else {
 657      var results = [];
 658      for (var i = 0; i < iterable.length; i++)
 659        results.push(iterable[i]);
 660      return results;
 661    }
 662  }
 663  
 664  Object.extend(Array.prototype, Enumerable);
 665  
 666  if (!Array.prototype._reverse)
 667    Array.prototype._reverse = Array.prototype.reverse;
 668  
 669  Object.extend(Array.prototype, {
 670    _each: function(iterator) {
 671      for (var i = 0; i < this.length; i++)
 672        iterator(this[i]);
 673    },
 674    
 675    clear: function() {
 676      this.length = 0;
 677      return this;
 678    },
 679    
 680    first: function() {
 681      return this[0];
 682    },
 683    
 684    last: function() {
 685      return this[this.length - 1];
 686    },
 687    
 688    compact: function() {
 689      return this.select(function(value) {
 690        return value != undefined || value != null;
 691      });
 692    },
 693    
 694    flatten: function() {
 695      return this.inject([], function(array, value) {
 696        return array.concat(value && value.constructor == Array ?
 697          value.flatten() : [value]);
 698      });
 699    },
 700    
 701    without: function() {
 702      var values = $A(arguments);
 703      return this.select(function(value) {
 704        return !values.include(value);
 705      });
 706    },
 707    
 708    indexOf: function(object) {
 709      for (var i = 0; i < this.length; i++)
 710        if (this[i] == object) return i;
 711      return -1;
 712    },
 713    
 714    reverse: function(inline) {
 715      return (inline !== false ? this : this.toArray())._reverse();
 716    },
 717    
 718    inspect: function() {
 719      return '[' + this.map(Object.inspect).join(', ') + ']';
 720    }
 721  });
 722  
 723  
 724  var Hash = {
 725    _each: function(iterator) {
 726      for (var key in this) {
 727        var value = this[key];
 728        if (typeof value == 'function') continue;
 729        
 730        var pair = [key, value];
 731        pair.key = key;
 732        pair.value = value;
 733        iterator(pair);
 734      }
 735    },
 736    
 737    keys: function() {
 738      return this.pluck('key');
 739    },
 740    
 741    values: function() {
 742      return this.pluck('value');
 743    },
 744    
 745    merge: function(hash) {
 746      return $H(hash).inject($H(this), function(mergedHash, pair) {
 747        mergedHash[pair.key] = pair.value;
 748        return mergedHash;
 749      });
 750    },
 751    
 752    toQueryString: function() {
 753      return this.map(function(pair) {
 754        return pair.map(encodeURIComponent).join('=');
 755      }).join('&');
 756    },
 757    
 758    inspect: function() {
 759      return '#<Hash:{' + this.map(function(pair) {
 760        return pair.map(Object.inspect).join(': ');
 761      }).join(', ') + '}>';
 762    }
 763  }
 764  
 765  function $H(object) {
 766    var hash = Object.extend({}, object || {});
 767    Object.extend(hash, Enumerable);
 768    Object.extend(hash, Hash);
 769    return hash;
 770  }
 771  
 772  
 773  ObjectRange = Class.create();
 774  Object.extend(ObjectRange.prototype, Enumerable);
 775  Object.extend(ObjectRange.prototype, {
 776    initialize: function(start, end, exclusive) {
 777      this.start = start;
 778      this.end = end;
 779      this.exclusive = exclusive;
 780    },
 781    
 782    _each: function(iterator) {
 783      var value = this.start;
 784      do {
 785        iterator(value);
 786        value = value.succ();
 787      } while (this.include(value));
 788    },
 789    
 790    include: function(value) {
 791      if (value < this.start) 
 792        return false;
 793      if (this.exclusive)
 794        return value < this.end;
 795      return value <= this.end;
 796    }
 797  });
 798  
 799  var $R = function(start, end, exclusive) {
 800    return new ObjectRange(start, end, exclusive);
 801  }
 802  
 803  function $() {
 804    var results = [], element;
 805    for (var i = 0; i < arguments.length; i++) {
 806      element = arguments[i];
 807      if (typeof element == 'string')
 808        element = document.getElementById(element);
 809      results.push(Element.extend(element));
 810    }
 811    return results.length < 2 ? results[0] : results;
 812  }
 813  
 814  document.getElementsByClassName = function(className, parentElement) {
 815    var children = ($(parentElement) || document.body).getElementsByTagName('*');
 816    return $A(children).inject([], function(elements, child) {
 817      if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
 818        elements.push(Element.extend(child));
 819      return elements;
 820    });
 821  }
 822  
 823  /*--------------------------------------------------------------------------*/
 824  
 825  if (!window.Element)
 826    var Element = new Object();
 827  
 828  Element.extend = function(element) {
 829    if (!element) return;
 830    if (_nativeExtensions) return element;
 831    
 832    if (!element._extended && element.tagName && element != window) {
 833      var methods = Element.Methods, cache = Element.extend.cache;
 834      for (property in methods) {
 835        var value = methods[property];
 836        if (typeof value == 'function')
 837          element[property] = cache.findOrStore(value);
 838      }
 839    }
 840    
 841    element._extended = true;
 842    return element;
 843  }
 844  
 845  Element.extend.cache = {
 846    findOrStore: function(value) {
 847      return this[value] = this[value] || function() {
 848        return value.apply(null, [this].concat($A(arguments)));
 849      }
 850    }
 851  }
 852  
 853  Element.Methods = {
 854    visible: function(element) {
 855      return $(element).style.display != 'none';
 856    },
 857    
 858    toggle: function() {
 859      for (var i = 0; i < arguments.length; i++) {
 860        var element = $(arguments[i]);
 861        Element[Element.visible(element) ? 'hide' : 'show'](element);
 862      }
 863    },
 864  
 865    hide: function() {
 866      for (var i = 0; i < arguments.length; i++) {
 867        var element = $(arguments[i]);
 868        element.style.display = 'none';
 869      }
 870    },
 871    
 872    show: function() {
 873      for (var i = 0; i < arguments.length; i++) {
 874        var element = $(arguments[i]);
 875        element.style.display = '';
 876      }
 877    },
 878  
 879    remove: function(element) {
 880      element = $(element);
 881      element.parentNode.removeChild(element);
 882    },
 883  
 884    update: function(element, html) {
 885      $(element).innerHTML = html.stripScripts();
 886      setTimeout(function() {html.evalScripts()}, 10);
 887    },
 888    
 889    replace: function(element, html) {
 890      element = $(element);
 891      if (element.outerHTML) {
 892        element.outerHTML = html.stripScripts();
 893      } else {
 894        var range = element.ownerDocument.createRange();
 895        range.selectNodeContents(element);
 896        element.parentNode.replaceChild(
 897          range.createContextualFragment(html.stripScripts()), element);
 898      }
 899      setTimeout(function() {html.evalScripts()}, 10);
 900    },
 901    
 902    getHeight: function(element) {
 903      element = $(element);
 904      return element.offsetHeight; 
 905    },
 906    
 907    classNames: function(element) {
 908      return new Element.ClassNames(element);
 909    },
 910  
 911    hasClassName: function(element, className) {
 912      if (!(element = $(element))) return;
 913      return Element.classNames(element).include(className);
 914    },
 915  
 916    addClassName: function(element, className) {
 917      if (!(element = $(element))) return;
 918      return Element.classNames(element).add(className);
 919    },
 920  
 921    removeClassName: function(element, className) {
 922      if (!(element = $(element))) return;
 923      return Element.classNames(element).remove(className);
 924    },
 925    
 926    // removes whitespace-only text node children
 927    cleanWhitespace: function(element) {
 928      element = $(element);
 929      for (var i = 0; i < element.childNodes.length; i++) {
 930        var node = element.childNodes[i];
 931        if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 
 932          Element.remove(node);
 933      }
 934    },
 935    
 936    empty: function(element) {
 937      return $(element).innerHTML.match(/^\s*$/);
 938    },
 939    
 940    childOf: function(element, ancestor) {
 941      element = $(element), ancestor = $(ancestor);
 942      while (element = element.parentNode)
 943        if (element == ancestor) return true;
 944      return false;
 945    },
 946    
 947    scrollTo: function(element) {
 948      element = $(element);
 949      var x = element.x ? element.x : element.offsetLeft,
 950          y = element.y ? element.y : element.offsetTop;
 951      window.scrollTo(x, y);
 952    },
 953    
 954    getStyle: function(element, style) {
 955      element = $(element);
 956      var value = element.style[style.camelize()];
 957      if (!value) {
 958        if (document.defaultView && document.defaultView.getComputedStyle) {
 959          var css = document.defaultView.getComputedStyle(element, null);
 960          value = css ? css.getPropertyValue(style) : null;
 961        } else if (element.currentStyle) {
 962          value = element.currentStyle[style.camelize()];
 963        }
 964      }
 965  
 966      if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
 967        if (Element.getStyle(element, 'position') == 'static') value = 'auto';
 968  
 969      return value == 'auto' ? null : value;
 970    },
 971    
 972    setStyle: function(element, style) {
 973      element = $(element);
 974      for (var name in style) 
 975        element.style[name.camelize()] = style[name];
 976    },
 977    
 978    getDimensions: function(element) {
 979      element = $(element);
 980      if (Element.getStyle(element, 'display') != 'none')
 981        return {width: element.offsetWidth, height: element.offsetHeight};
 982      
 983      // All *Width and *Height properties give 0 on elements with display none,
 984      // so enable the element temporarily
 985      var els = element.style;
 986      var originalVisibility = els.visibility;
 987      var originalPosition = els.position;
 988      els.visibility = 'hidden';
 989      els.position = 'absolute';
 990      els.display = '';
 991      var originalWidth = element.clientWidth;
 992      var originalHeight = element.clientHeight;
 993      els.display = 'none';
 994      els.position = originalPosition;
 995      els.visibility = originalVisibility;
 996      return {width: originalWidth, height: originalHeight};    
 997    },
 998    
 999    makePositioned: function(element) {
1000      element = $(element);
1001      var pos = Element.getStyle(element, 'position');
1002      if (pos == 'static' || !pos) {
1003        element._madePositioned = true;
1004        element.style.position = 'relative';
1005        // Opera returns the offset relative to the positioning context, when an
1006        // element is position relative but top and left have not been defined
1007        if (window.opera) {
1008          element.style.top = 0;
1009          element.style.left = 0;
1010        }  
1011      }
1012    },
1013  
1014    undoPositioned: function(element) {
1015      element = $(element);
1016      if (element._madePositioned) {
1017        element._madePositioned = undefined;
1018        element.style.position =
1019          element.style.top =
1020          element.style.left =
1021          element.style.bottom =
1022          element.style.right = '';   
1023      }
1024    },
1025  
1026    makeClipping: function(element) {
1027      element = $(element);
1028      if (element._overflow) return;
1029      element._overflow = element.style.overflow;
1030      if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
1031        element.style.overflow = 'hidden';
1032    },
1033  
1034    undoClipping: function(element) {
1035      element = $(element);
1036      if (element._overflow) return;
1037      element.style.overflow = element._overflow;
1038      element._overflow = undefined;
1039    }
1040  }
1041  
1042  Object.extend(Element, Element.Methods);
1043  
1044  var _nativeExtensions = false;
1045  
1046  if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1047    var HTMLElement = {}
1048    HTMLElement.prototype = document.createElement('div').__proto__;
1049  }
1050  
1051  Element.addMethods = function(methods) {
1052    Object.extend(Element.Methods, methods || {});
1053    
1054    if(typeof HTMLElement != 'undefined') {
1055      var methods = Element.Methods, cache = Element.extend.cache;
1056      for (property in methods) {
1057        var value = methods[property];
1058        if (typeof value == 'function')
1059          HTMLElement.prototype[property] = cache.findOrStore(value);
1060      }
1061      _nativeExtensions = true;
1062    }
1063  }
1064  
1065  Element.addMethods();
1066  
1067  var Toggle = new Object();
1068  Toggle.display = Element.toggle;
1069  
1070  /*--------------------------------------------------------------------------*/
1071  
1072  Abstract.Insertion = function(adjacency) {
1073    this.adjacency = adjacency;
1074  }
1075  
1076  Abstract.Insertion.prototype = {
1077    initialize: function(element, content) {
1078      this.element = $(element);
1079      this.content = content.stripScripts();
1080      
1081      if (this.adjacency && this.element.insertAdjacentHTML) {
1082        try {
1083          this.element.insertAdjacentHTML(this.adjacency, this.content);
1084        } catch (e) {
1085          var tagName = this.element.tagName.toLowerCase();
1086          if (tagName == 'tbody' || tagName == 'tr') {
1087            this.insertContent(this.contentFromAnonymousTable());
1088          } else {
1089            throw e;
1090          }
1091        }
1092      } else {
1093        this.range = this.element.ownerDocument.createRange();
1094        if (this.initializeRange) this.initializeRange();
1095        this.insertContent([this.range.createContextualFragment(this.content)]);
1096      }
1097  
1098      setTimeout(function() {content.evalScripts()}, 10);   
1099    },
1100    
1101    contentFromAnonymousTable: function() {
1102      var div = document.createElement('div');
1103      div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
1104      return $A(div.childNodes[0].childNodes[0].childNodes);
1105    }
1106  }
1107  
1108  var Insertion = new Object();
1109  
1110  Insertion.Before = Class.create();
1111  Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
1112    initializeRange: function() {
1113      this.range.setStartBefore(this.element);
1114    },
1115    
1116    insertContent: function(fragments) {
1117      fragments.each((function(fragment) {
1118        this.element.parentNode.insertBefore(fragment, this.element);
1119      }).bind(this));
1120    }
1121  });
1122  
1123  Insertion.Top = Class.create();
1124  Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
1125    initializeRange: function() {
1126      this.range.selectNodeContents(this.element);
1127      this.range.collapse(true);
1128    },
1129    
1130    insertContent: function(fragments) {
1131      fragments.reverse(false).each((function(fragment) {
1132        this.element.insertBefore(fragment, this.element.firstChild);
1133      }).bind(this));
1134    }
1135  });
1136  
1137  Insertion.Bottom = Class.create();
1138  Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
1139    initializeRange: function() {
1140      this.range.selectNodeContents(this.element);
1141      this.range.collapse(this.element);
1142    },
1143    
1144    insertContent: function(fragments) {
1145      fragments.each((function(fragment) {
1146        this.element.appendChild(fragment);
1147      }).bind(this));
1148    }
1149  });
1150  
1151  Insertion.After = Class.create();
1152  Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
1153    initializeRange: function() {
1154      this.range.setStartAfter(this.element);
1155    },
1156    
1157    insertContent: function(fragments) {
1158      fragments.each((function(fragment) {
1159        this.element.parentNode.insertBefore(fragment, 
1160          this.element.nextSibling);
1161      }).bind(this));
1162    }
1163  });
1164  
1165  /*--------------------------------------------------------------------------*/
1166  
1167  Element.ClassNames = Class.create();
1168  Element.ClassNames.prototype = {
1169    initialize: function(element) {
1170      this.element = $(element);
1171    },
1172  
1173    _each: function(iterator) {
1174      this.element.className.split(/\s+/).select(function(name) {
1175        return name.length > 0;
1176      })._each(iterator);
1177    },
1178    
1179    set: function(className) {
1180      this.element.className = className;
1181    },
1182    
1183    add: function(classNameToAdd) {
1184      if (this.include(classNameToAdd)) return;
1185      this.set(this.toArray().concat(classNameToAdd).join(' '));
1186    },
1187    
1188    remove: function(classNameToRemove) {
1189      if (!this.include(classNameToRemove)) return;
1190      this.set(this.select(function(className) {
1191        return className != classNameToRemove;
1192      }).join(' '));
1193    },
1194    
1195    toString: function() {
1196      return this.toArray().join(' ');
1197    }
1198  }
1199  
1200  Object.extend(Element.ClassNames.prototype, Enumerable);
1201  
1202  
1203  var Field = {
1204    clear: function() {
1205      for (var i = 0; i < arguments.length; i++)
1206        $(arguments[i]).value = '';
1207    },
1208  
1209    focus: function(element) {
1210      $(element).focus();
1211    },
1212    
1213    present: function() {
1214      for (var i = 0; i < arguments.length; i++)
1215        if ($(arguments[i]).value == '') return false;
1216      return true;
1217    },
1218    
1219    select: function(element) {
1220      $(element).select();
1221    },
1222     
1223    activate: function(element) {
1224      element = $(element);
1225      element.focus();
1226      if (element.select)
1227        element.select();
1228    }
1229  }
1230  
1231  /*--------------------------------------------------------------------------*/
1232  
1233  var Form = {
1234    serialize: function(form) {
1235      var elements = Form.getElements($(form));
1236      var queryComponents = new Array();
1237      
1238      for (var i = 0; i < elements.length; i++) {
1239        var queryComponent = Form.Element.serialize(elements[i]);
1240        if (queryComponent)
1241          queryComponents.push(queryComponent);
1242      }
1243      
1244      return queryComponents.join('&');
1245    },
1246    
1247    getElements: function(form) {
1248      form = $(form);
1249      var elements = new Array();
1250  
1251      for (var tagName in Form.Element.Serializers) {
1252        var tagElements = form.getElementsByTagName(tagName);
1253        for (var j = 0; j < tagElements.length; j++)
1254          elements.push(tagElements[j]);
1255      }
1256      return elements;
1257    },
1258    
1259    getInputs: function(form, typeName, name) {
1260      form = $(form);
1261      var inputs = form.getElementsByTagName('input');
1262      
1263      if (!typeName && !name)
1264        return inputs;
1265        
1266      var matchingInputs = new Array();
1267      for (var i = 0; i < inputs.length; i++) {
1268        var input = inputs[i];
1269        if ((typeName && input.type != typeName) ||
1270            (name && input.name != name)) 
1271          continue;
1272        matchingInputs.push(input);
1273      }
1274  
1275      return matchingInputs;
1276    },
1277  
1278    disable: function(form) {
1279      var elements = Form.getElements(form);
1280      for (var i = 0; i < elements.length; i++) {
1281        var element = elements[i];
1282        element.blur();
1283        element.disabled = 'true';
1284      }
1285    },
1286  
1287    enable: function(form) {
1288      var elements = Form.getElements(form);
1289      for (var i = 0; i < elements.length; i++) {
1290        var element = elements[i];
1291        element.disabled = '';
1292      }
1293    },
1294  
1295    findFirstElement: function(form) {
1296      return Form.getElements(form).find(function(element) {
1297        return element.type != 'hidden' && !element.disabled &&
1298          ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
1299      });
1300    },
1301  
1302    focusFirstElement: function(form) {
1303      Field.activate(Form.findFirstElement(form));
1304    },
1305  
1306    reset: function(form) {
1307      $(form).reset();
1308    }
1309  }
1310  
1311  Form.Element = {
1312    serialize: function(element) {
1313      element = $(element);
1314      var method = element.tagName.toLowerCase();
1315      var parameter = Form.Element.Serializers[method](element);
1316      
1317      if (parameter) {
1318        var key = encodeURIComponent(parameter[0]);
1319        if (key.length == 0) return;
1320        
1321        if (parameter[1].constructor != Array)
1322          parameter[1] = [parameter[1]];
1323        
1324        return parameter[1].map(function(value) {
1325          return key + '=' + encodeURIComponent(value);
1326        }).join('&');
1327      }
1328    },
1329    
1330    getValue: function(element) {
1331      element = $(element);
1332      var method = element.tagName.toLowerCase();
1333      var parameter = Form.Element.Serializers[method](element);
1334      
1335      if (parameter)
1336        return parameter[1];
1337    }
1338  }
1339  
1340  Form.Element.Serializers = {
1341    input: function(element) {
1342      switch (element.type.toLowerCase()) {
1343        case 'submit':
1344        case 'hidden':
1345        case 'password':
1346        case 'text':
1347          return Form.Element.Serializers.textarea(element);
1348        case 'checkbox':  
1349        case 'radio':
1350          return Form.Element.Serializers.inputSelector(element);
1351      }
1352      return false;
1353    },
1354  
1355    inputSelector: function(element) {
1356      if (element.checked)
1357        return [element.name, element.value];
1358    },
1359  
1360    textarea: function(element) {
1361      return [element.name, element.value];
1362    },
1363    
1364    select: function(element) {
1365      return Form.Element.Serializers[element.type == 'select-one' ? 
1366        'selectOne' : 'selectMany'](element);
1367    },
1368    
1369    selectOne: function(element) {
1370      var value = '', opt, index = element.selectedIndex;
1371      if (index >= 0) {
1372        opt = element.options[index];
1373        value = opt.value || opt.text;
1374      }
1375      return [element.name, value];
1376    },
1377    
1378    selectMany: function(element) {
1379      var value = [];
1380      for (var i = 0; i < element.length; i++) {
1381        var opt = element.options[i];
1382        if (opt.selected)
1383          value.push(opt.value || opt.text);
1384      }
1385      return [element.name, value];
1386    }
1387  }
1388  
1389  /*--------------------------------------------------------------------------*/
1390  
1391  var $F = Form.Element.getValue;
1392  
1393  /*--------------------------------------------------------------------------*/
1394  
1395  Abstract.TimedObserver = function() {}
1396  Abstract.TimedObserver.prototype = {
1397    initialize: function(element, frequency, callback) {
1398      this.frequency = frequency;
1399      this.element   = $(element);
1400      this.callback  = callback;
1401      
1402      this.lastValue = this.getValue();
1403      this.registerCallback();
1404    },
1405    
1406    registerCallback: function() {
1407      setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
1408    },
1409    
1410    onTimerEvent: function() {
1411      var value = this.getValue();
1412      if (this.lastValue != value) {
1413        this.callback(this.element, value);
1414        this.lastValue = value;
1415      }
1416    }
1417  }
1418  
1419  Form.Element.Observer = Class.create();
1420  Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1421    getValue: function() {
1422      return Form.Element.getValue(this.element);
1423    }
1424  });
1425  
1426  Form.Observer = Class.create();
1427  Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
1428    getValue: function() {
1429      return Form.serialize(this.element);
1430    }
1431  });
1432  
1433  /*--------------------------------------------------------------------------*/
1434  
1435  Abstract.EventObserver = function() {}
1436  Abstract.EventObserver.prototype = {
1437    initialize: function(element, callback) {
1438      this.element  = $(element);
1439      this.callback = callback;
1440      
1441      this.lastValue = this.getValue();
1442      if (this.element.tagName.toLowerCase() == 'form')
1443        this.registerFormCallbacks();
1444      else
1445        this.registerCallback(this.element);
1446    },
1447    
1448    onElementEvent: function() {
1449      var value = this.getValue();
1450      if (this.lastValue != value) {
1451        this.callback(this.element, value);
1452        this.lastValue = value;
1453      }
1454    },
1455    
1456    registerFormCallbacks: function() {
1457      var elements = Form.getElements(this.element);
1458      for (var i = 0; i < elements.length; i++)
1459        this.registerCallback(elements[i]);
1460    },
1461    
1462    registerCallback: function(element) {
1463      if (element.type) {
1464        switch (element.type.toLowerCase()) {
1465          case 'checkbox':  
1466          case 'radio':
1467            Event.observe(element, 'click', this.onElementEvent.bind(this));
1468            break;
1469          case 'password':
1470          case 'text':
1471          case 'textarea':
1472          case 'select-one':
1473          case 'select-multiple':
1474            Event.observe(element, 'change', this.onElementEvent.bind(this));
1475            break;
1476        }
1477      }    
1478    }
1479  }
1480  
1481  Form.Element.EventObserver = Class.create();
1482  Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1483    getValue: function() {
1484      return Form.Element.getValue(this.element);
1485    }
1486  });
1487  
1488  Form.EventObserver = Class.create();
1489  Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
1490    getValue: function() {
1491      return Form.serialize(this.element);
1492    }
1493  });
1494  
1495  
1496  
1497  if (!window.Event) {
1498    var Event = new Object();
1499  }
1500  
1501  Object.extend(Event, {
1502    KEY_BACKSPACE: 8,
1503    KEY_TAB:       9,
1504    KEY_RETURN:   13,
1505    KEY_ESC:      27,
1506    KEY_LEFT:     37,
1507    KEY_UP:       38,
1508    KEY_RIGHT:    39,
1509    KEY_DOWN:     40,
1510    KEY_DELETE:   46,
1511    KEY_SPACEBAR: 32,
1512  
1513    element: function(event) {
1514      return event.target || event.srcElement;
1515    },
1516  
1517    isLeftClick: function(event) {
1518      return (((event.which) && (event.which == 1)) ||
1519              ((event.button) && (event.button == 1)));
1520    },
1521  
1522    pointerX: function(event) {
1523      return event.pageX || (event.clientX + 
1524        (document.documentElement.scrollLeft || document.body.scrollLeft));
1525    },
1526  
1527    pointerY: function(event) {
1528      return event.pageY || (event.clientY + 
1529        (document.documentElement.scrollTop || document.body.scrollTop));
1530    },
1531  
1532    stop: function(event) {
1533      if (event.preventDefault) { 
1534        event.preventDefault(); 
1535        event.stopPropagation(); 
1536      } else {
1537        event.returnValue = false;
1538        event.cancelBubble = true;
1539      }
1540    },
1541  
1542    // find the first node with the given tagName, starting from the
1543    // node the event was triggered on; traverses the DOM upwards
1544    findElement: function(event, tagName) {
1545      var element = Event.element(event);
1546      while (element.parentNode && (!element.tagName ||
1547          (element.tagName.toUpperCase() != tagName.toUpperCase())))
1548        element = element.parentNode;
1549      return element;
1550    },
1551  
1552    observers: false,
1553    
1554    _observeAndCache: function(element, name, observer, useCapture) {
1555      if (!this.observers) this.observers = [];
1556      if (element.addEventListener) {
1557        this.observers.push([element, name, observer, useCapture]);
1558        element.addEventListener(name, observer, useCapture);
1559      } else if (element.attachEvent) {
1560        this.observers.push([element, name, observer, useCapture]);
1561        element.attachEvent('on' + name, observer);
1562      }
1563    },
1564    
1565    unloadCache: function() {
1566      if (!Event.observers) return;
1567      for (var i = 0; i < Event.observers.length; i++) {
1568        Event.stopObserving.apply(this, Event.observers[i]);
1569        Event.observers[i][0] = null;
1570      }
1571      Event.observers = false;
1572    },
1573  
1574    observe: function(element, name, observer, useCapture) {
1575      var element = $(element);
1576      useCapture = useCapture || false;
1577      
1578      if (name == 'keypress' &&
1579          (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1580          || element.attachEvent))
1581        name = 'keydown';
1582      
1583      this._observeAndCache(element, name, observer, useCapture);
1584    },
1585  
1586    stopObserving: function(element, name, observer, useCapture) {
1587      var element = $(element);
1588      useCapture = useCapture || false;
1589      
1590      if (name == 'keypress' &&
1591          (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
1592          || element.detachEvent))
1593        name = 'keydown';
1594      
1595      if (element.removeEventListener) {
1596        element.removeEventListener(name, observer, useCapture);
1597      } else if (element.detachEvent) {
1598        element.detachEvent('on' + name, observer);
1599      }
1600    }
1601  });
1602  
1603  /* prevent memory leaks in IE */
1604  if (navigator.appVersion.match(/\bMSIE\b/))
1605    Event.observe(window, 'unload', Event.unloadCache, false);
1606  
1607  
1608  /**
1609   * @class Event extensions.
1610   */
1611  Object.extend(Event, 
1612  {
1613      /**
1614       * Register a function to be executed when the page is loaded. 
1615       * Note that the page is only loaded if all resources (e.g. images) 
1616       * are loaded.
1617       * 
1618       * Example: Show an alert box with message "Page Loaded!" when the 
1619       * page finished loading.
1620       * <code>
1621       * Event.OnLoad(function(){ alert("Page Loaded!"); });
1622       * </code>
1623       *
1624       * @param {Function} function to execute when page is loaded.
1625       */
1626      OnLoad : function (fn) 
1627      {
1628          // opera onload is in document, not window
1629          var w = document.addEventListener && 
1630                      !window.addEventListener ? document : window;
1631          Event.observe(w,'load',fn);
1632      },
1633  
1634      /**
1635       * @param {Event} a keyboard event
1636       * @return {Number} the Unicode character code generated by the key 
1637       * that was struck. 
1638       */
1639      keyCode : function(e)
1640      {
1641         return e.keyCode != null ? e.keyCode : e.charCode
1642      },
1643  
1644      /**
1645       * @param {String} event type or event name.
1646       * @return {Boolean} true if event type is of HTMLEvent, false 
1647       * otherwise
1648       */
1649      isHTMLEvent : function(type)
1650      {
1651          var events = ['abort', 'blur', 'change', 'error', 'focus', 
1652                      'load', 'reset', 'resize', 'scroll', 'select', 
1653                      'submit', 'unload'];
1654          return events.include(type);
1655      },
1656  
1657      /**
1658       * @param {String} event type or event name
1659       * @return {Boolean} true if event type is of MouseEvent, 
1660       * false otherwise
1661       */
1662      isMouseEvent : function(type)
1663      {
1664          var events = ['click', 'mousedown', 'mousemove', 'mouseout', 
1665                      'mouseover', 'mouseup'];
1666          return events.include(type);
1667      },
1668  
1669      /**
1670       * Dispatch the DOM event of a given <tt>type</tt> on a DOM 
1671       * <tt>element</tt>. Only HTMLEvent and MouseEvent can be 
1672       * dispatched, keyboard events or UIEvent can not be dispatch 
1673       * via javascript consistently.
1674       * For the "submit" event the submit() method is called.
1675       * @param {Object} element id string or a DOM element.
1676       * @param {String} event type to dispatch.
1677       */
1678      fireEvent : function(element,type)
1679      {
1680          element = $(element);
1681          if(type == "submit")
1682              return element.submit();
1683          if(document.createEvent)
1684          {            
1685              if(Event.isHTMLEvent(type))
1686              {
1687                  var event = document.createEvent('HTMLEvents');
1688                  event.initEvent(type, true, true);
1689              }
1690              else if(Event.isMouseEvent(type))
1691              {
1692                  var event = document.createEvent('MouseEvents');                
1693                  if (event.initMouseEvent)
1694                  {
1695                      event.initMouseEvent(type,true,true,
1696                          document.defaultView, 1, 0, 0, 0, 0, false, 
1697                                  false, false, false, 0, null);
1698                  }
1699                  else
1700                  {
1701                      // Safari
1702                      // TODO we should be initialising other mouse-event related attributes here
1703                      event.initEvent(type, true, true);
1704                  }
1705              }
1706              element.dispatchEvent(event);
1707          }
1708          else if(document.createEventObject)
1709          {
1710              var evObj = document.createEventObject();
1711              element.fireEvent('on'+type, evObj);
1712          }
1713          else if(typeof(element['on'+type]) == "function")
1714              element['on'+type]();
1715      }
1716  });
1717  
1718  var Position = {
1719    // set to true if needed, warning: firefox performance problems
1720    // NOT neeeded for page scrolling, only if draggable contained in
1721    // scrollable elements
1722    includeScrollOffsets: false, 
1723  
1724    // must be called before calling withinIncludingScrolloffset, every time the
1725    // page is scrolled
1726    prepare: function() {
1727      this.deltaX =  window.pageXOffset 
1728                  || document.documentElement.scrollLeft 
1729                  || document.body.scrollLeft 
1730                  || 0;
1731      this.deltaY =  window.pageYOffset 
1732                  || document.documentElement.scrollTop 
1733                  || document.body.scrollTop 
1734                  || 0;
1735    },
1736  
1737    realOffset: function(element) {
1738      var valueT = 0, valueL = 0;
1739      do {
1740        valueT += element.scrollTop  || 0;
1741        valueL += element.scrollLeft || 0; 
1742        element = element.parentNode;
1743      } while (element);
1744      return [valueL, valueT];
1745    },
1746  
1747    cumulativeOffset: function(element) {
1748      var valueT = 0, valueL = 0;
1749      do {
1750        valueT += element.offsetTop  || 0;
1751        valueL += element.offsetLeft || 0;
1752        element = element.offsetParent;
1753      } while (element);
1754      return [valueL, valueT];
1755    },
1756  
1757    positionedOffset: function(element) {
1758      var valueT = 0, valueL = 0;
1759      do {
1760        valueT += element.offsetTop  || 0;
1761        valueL += element.offsetLeft || 0;
1762        element = element.offsetParent;
1763        if (element) {
1764          p = Element.getStyle(element, 'position');
1765          if (p == 'relative' || p == 'absolute') break;
1766        }
1767      } while (element);
1768      return [valueL, valueT];
1769    },
1770    
1771    offsetParent: function(element) {
1772      if (element.offsetParent) return element.offsetParent;
1773      if (element == document.body) return element;
1774  
1775      while ((element = element.parentNode) && element != document.body)
1776        if (Element.getStyle(element, 'position') != 'static')
1777          return element;
1778  
1779      return document.body;
1780    },
1781    
1782    // caches x/y coordinate pair to use with overlap
1783    within: function(element, x, y) {
1784      if (this.includeScrollOffsets)
1785        return this.withinIncludingScrolloffsets(element, x, y);
1786      this.xcomp = x;
1787      this.ycomp = y;
1788      this.offset = this.cumulativeOffset(element);
1789  
1790      return (y >= this.offset[1] &&
1791              y <  this.offset[1] + element.offsetHeight &&
1792              x >= this.offset[0] && 
1793              x <  this.offset[0] + element.offsetWidth);
1794    },
1795  
1796    withinIncludingScrolloffsets: function(element, x, y) {
1797      var offsetcache = this.realOffset(element);
1798  
1799      this.xcomp = x + offsetcache[0] - this.deltaX;
1800      this.ycomp = y + offsetcache[1] - this.deltaY;
1801      this.offset = this.cumulativeOffset(element);
1802  
1803      return (this.ycomp >= this.offset[1] &&
1804              this.ycomp <  this.offset[1] + element.offsetHeight &&
1805              this.xcomp >= this.offset[0] && 
1806              this.xcomp <  this.offset[0] + element.offsetWidth);
1807    },
1808  
1809    // within must be called directly before
1810    overlap: function(mode, element) {  
1811      if (!mode) return 0;  
1812      if (mode == 'vertical') 
1813        return ((this.offset[1] + element.offsetHeight) - this.ycomp) / 
1814          element.offsetHeight;
1815      if (mode == 'horizontal')
1816        return ((this.offset[0] + element.offsetWidth) - this.xcomp) / 
1817          element.offsetWidth;
1818    },
1819  
1820    clone: function(source, target) {
1821      source = $(source);
1822      target = $(target);
1823      target.style.position = 'absolute';
1824      var offsets = this.cumulativeOffset(source);
1825      target.style.top    = offsets[1] + 'px';
1826      target.style.left   = offsets[0] + 'px';
1827      target.style.width  = source.offsetWidth + 'px';
1828      target.style.height = source.offsetHeight + 'px';
1829    },
1830  
1831    page: function(forElement) {
1832      var valueT = 0, valueL = 0;
1833  
1834      var element = forElement;
1835      do {
1836        valueT += element.offsetTop  || 0;
1837        valueL += element.offsetLeft || 0;
1838  
1839        // Safari fix
1840        if (element.offsetParent==document.body)
1841          if (Element.getStyle(element,'position')=='absolute') break;
1842  
1843      } while (element = element.offsetParent);
1844  
1845      element = forElement;
1846      do {
1847        valueT -= element.scrollTop  || 0;
1848        valueL -= element.scrollLeft || 0;    
1849      } while (element = element.parentNode);
1850  
1851      return [valueL, valueT];
1852    },
1853  
1854    clone: function(source, target) {
1855      var options = Object.extend({
1856        setLeft:    true,
1857        setTop:     true,
1858        setWidth:   true,
1859        setHeight:  true,
1860        offsetTop:  0,
1861        offsetLeft: 0
1862      }, arguments[2] || {})
1863  
1864      // find page position of source
1865      source = $(source);
1866      var p = Position.page(source);
1867  
1868      // find coordinate system to use
1869      target = $(target);
1870      var delta = [0, 0];
1871      var parent = null;
1872      // delta [0,0] will do fine with position: fixed elements, 
1873      // position:absolute needs offsetParent deltas
1874      if (Element.getStyle(target,'position') == 'absolute') {
1875        parent = Position.offsetParent(target);
1876        delta = Position.page(parent);
1877      }
1878  
1879      // correct by body offsets (fixes Safari)
1880      if (parent == document.body) {
1881        delta[0] -= document.body.offsetLeft;
1882        delta[1] -= document.body.offsetTop; 
1883      }
1884  
1885      // set position
1886      if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
1887      if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
1888      if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
1889      if(options.setHeight) target.style.height = source.offsetHeight + 'px';
1890    },
1891  
1892    absolutize: function(element) {
1893      element = $(element);
1894      if (element.style.position == 'absolute') return;
1895      Position.prepare();
1896  
1897      var offsets = Position.positionedOffset(element);
1898      var top     = offsets[1];
1899      var left    = offsets[0];
1900      var width   = element.clientWidth;
1901      var height  = element.clientHeight;
1902  
1903      element._originalLeft   = left - parseFloat(element.style.left  || 0);
1904      element._originalTop    = top  - parseFloat(element.style.top || 0);
1905      element._originalWidth  = element.style.width;
1906      element._originalHeight = element.style.height;
1907  
1908      element.style.position = 'absolute';
1909      element.style.top    = top + 'px';;
1910      element.style.left   = left + 'px';;
1911      element.style.width  = width + 'px';;
1912      element.style.height = height + 'px';;
1913    },
1914  
1915    relativize: function(element) {
1916      element = $(element);
1917      if (element.style.position == 'relative') return;
1918      Position.prepare();
1919  
1920      element.style.position = 'relative';
1921      var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
1922      var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
1923  
1924      element.style.top    = top + 'px';
1925      element.style.left   = left + 'px';
1926      element.style.height = element._originalHeight;
1927      element.style.width  = element._originalWidth;
1928    }
1929  }
1930  
1931  // Safari returns margins on body which is incorrect if the child is absolutely
1932  // positioned.  For performance reasons, redefine Position.cumulativeOffset for
1933  // KHTML/WebKit only.
1934  if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
1935    Position.cumulativeOffset = function(element) {
1936      var valueT = 0, valueL = 0;
1937      do {
1938        valueT += element.offsetTop  || 0;
1939        valueL += element.offsetLeft || 0;
1940        if (element.offsetParent == document.body)
1941          if (Element.getStyle(element, 'position') == 'absolute') break;
1942          
1943        element = element.offsetParent;
1944      } while (element);
1945      
1946      return [valueL, valueT];
1947    }
1948  }
1949  
1950  
1951  
1952  
1953  var Selector = Class.create();
1954  Selector.prototype = {
1955    initialize: function(expression) {
1956      this.params = {classNames: []};
1957      this.expression = expression.toString().strip();
1958      this.parseExpression();
1959      this.compileMatcher();
1960    },
1961  
1962    parseExpression: function() {
1963      function abort(message) { throw 'Parse error in selector: ' + message; }
1964  
1965      if (this.expression == '')  abort('empty expression');
1966  
1967      var params = this.params, expr = this.expression, match, modifier, clause, rest;
1968      while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
1969        params.attributes = params.attributes || [];
1970        params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
1971        expr = match[1];
1972      }
1973  
1974      if (expr == '*') return this.params.wildcard = true;
1975      
1976      while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
1977        modifier = match[1], clause = match[2], rest = match[3];
1978        switch (modifier) {
1979          case '#':       params.id = clause; break;
1980          case '.':       params.classNames.push(clause); break;
1981          case '':
1982          case undefined: params.tagName = clause.toUpperCase(); break;
1983          default:        abort(expr.inspect());
1984        }
1985        expr = rest;
1986      }
1987      
1988      if (expr.length > 0) abort(expr.inspect());
1989    },
1990  
1991    buildMatchExpression: function() {
1992      var params = this.params, conditions = [], clause;
1993  
1994      if (params.wildcard)
1995        conditions.push('true');
1996      if (clause = params.id)
1997        conditions.push('element.id == ' + clause.inspect());
1998      if (clause = params.tagName)
1999        conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
2000      if ((clause = params.classNames).length > 0)
2001        for (var i = 0; i < clause.length; i++)
2002          conditions.push('Element.hasClassName(element, ' + clause[i].inspect() + ')');
2003      if (clause = params.attributes) {
2004        clause.each(function(attribute) {
2005          var value = 'element.getAttribute(' + attribute.name.inspect() + ')';
2006          var splitValueBy = function(delimiter) {
2007            return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
2008          }
2009          
2010          switch (attribute.operator) {
2011            case '=':       conditions.push(value + ' == ' + attribute.value.inspect()); break;
2012            case '~=':      conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
2013            case '|=':      conditions.push(
2014                              splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
2015                            ); break;
2016            case '!=':      conditions.push(value + ' != ' + attribute.value.inspect()); break;
2017            case '':
2018            case undefined: conditions.push(value + ' != null'); break;
2019            default:        throw 'Unknown operator ' + attribute.operator + ' in selector';
2020          }
2021        });
2022      }
2023  
2024      return conditions.join(' && ');
2025    },
2026  
2027    compileMatcher: function() {
2028      this.match = new Function('element', 'if (!element.tagName) return false; \
2029        return ' + this.buildMatchExpression());
2030    },
2031  
2032    findElements: function(scope) {
2033      var element;
2034  
2035      if (element = $(this.params.id))
2036        if (this.match(element))
2037          if (!scope || Element.childOf(element, scope))
2038            return [element];
2039  
2040      scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
2041  
2042      var results = [];
2043      for (var i = 0; i < scope.length; i++)
2044        if (this.match(element = scope[i]))
2045          results.push(Element.extend(element));
2046  
2047      return results;
2048    },
2049  
2050    toString: function() {
2051      return this.expression;
2052    }
2053  }
2054  
2055  function $$() {
2056    return $A(arguments).map(function(expression) {
2057      return expression.strip().split(/\s+/).inject([null], function(results, expr) {
2058        var selector = new Selector(expr);
2059        return results.map(selector.findElements.bind(selector)).flatten();
2060      });
2061    }).flatten();
2062  }
2063  
2064  
2065  // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2066  //
2067  // See scriptaculous.js for full license.
2068  
2069  var Builder = {
2070    NODEMAP: {
2071      AREA: 'map',
2072      CAPTION: 'table',
2073      COL: 'table',
2074      COLGROUP: 'table',
2075      LEGEND: 'fieldset',
2076      OPTGROUP: 'select',
2077      OPTION: 'select',
2078      PARAM: 'object',
2079      TBODY: 'table',
2080      TD: 'table',
2081      TFOOT: 'table',
2082      TH: 'table',
2083      THEAD: 'table',
2084      TR: 'table'
2085    },
2086    // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
2087    //       due to a Firefox bug
2088    node: function(elementName) {
2089      elementName = elementName.toUpperCase();
2090      
2091      // try innerHTML approach
2092      var parentTag = this.NODEMAP[elementName] || 'div';
2093      var parentElement = document.createElement(parentTag);
2094      try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
2095        parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
2096      } catch(e) {}
2097      var element = parentElement.firstChild || null;
2098        
2099      // see if browser added wrapping tags
2100      if(element && (element.tagName != elementName))
2101        element = element.getElementsByTagName(elementName)[0];
2102      
2103      // fallback to createElement approach
2104      if(!element) element = document.createElement(elementName);
2105      
2106      // abort if nothing could be created
2107      if(!element) return;
2108  
2109      // attributes (or text)
2110      if(arguments[1])
2111        if(this._isStringOrNumber(arguments[1]) ||
2112          (arguments[1] instanceof Array)) {
2113            this._children(element, arguments[1]);
2114          } else {
2115            var attrs = this._attributes(arguments[1]);
2116            if(attrs.length) {
2117              try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
2118                parentElement.innerHTML = "<" +elementName + " " +
2119                  attrs + "></" + elementName + ">";
2120              } catch(e) {}
2121              element = parentElement.firstChild || null;
2122              // workaround firefox 1.0.X bug
2123              if(!element) {
2124                element = document.createElement(elementName);
2125                for(attr in arguments[1]) 
2126                  element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
2127              }
2128              if(element.tagName != elementName)
2129                element = parentElement.getElementsByTagName(elementName)[0];
2130              }
2131          } 
2132  
2133      // text, or array of children
2134      if(arguments[2])
2135        this._children(element, arguments[2]);
2136  
2137       return element;
2138    },
2139    _text: function(text) {
2140       return document.createTextNode(text);
2141    },
2142    _attributes: function(attributes) {
2143      var attrs = [];
2144      for(attribute in attributes)
2145        attrs.push((attribute=='className' ? 'class' : attribute) +
2146            '="' + attributes[attribute].toString().escapeHTML() + '"');
2147      return attrs.join(" ");
2148    },
2149    _children: function(element, children) {
2150      if(typeof children=='object') { // array can hold nodes and text
2151        children.flatten().each( function(e) {
2152          if(typeof e=='object')
2153            element.appendChild(e)
2154          else
2155            if(Builder._isStringOrNumber(e))
2156              element.appendChild(Builder._text(e));
2157        });
2158      } else
2159        if(Builder._isStringOrNumber(children)) 
2160           element.appendChild(Builder._text(children));
2161    },
2162    _isStringOrNumber: function(param) {
2163      return(typeof param=='string' || typeof param=='number');
2164    }
2165  }
2166  
2167  
2168  Object.extend(Builder,
2169  {
2170      exportTags:function()
2171      {
2172          var tags=["BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG", "CAPTION"];
2173          tags.each(function(tag)
2174          {
2175              window[tag]=function()
2176              {
2177                  var args=$A(arguments);
2178                  if(args.length==0)
2179                      return Builder.node(tag,null);
2180                  if(args.length==1)
2181                      return Builder.node(tag,args[0]);
2182                  if(args.length>1)
2183                      return Builder.node(tag,args.shift(),args);
2184  
2185              };
2186          });
2187      }
2188  });
2189  
2190  Builder.exportTags();
2191  
2192  
2193  
2194  Object.extend(Date.prototype,
2195  {    
2196      SimpleFormat: function(format, data)
2197      {
2198          data = data || {};
2199          var bits = new Array();
2200          bits['d'] = this.getDate();
2201          bits['dd'] = String(this.getDate()).zerofill(2);
2202          
2203          bits['M'] = this.getMonth()+1;
2204          bits['MM'] = String(this.getMonth()+1).zerofill(2);
2205          if(data.AbbreviatedMonthNames)
2206              bits['MMM'] = data.AbbreviatedMonthNames[this.getMonth()];
2207          if(data.MonthNames)
2208              bits['MMMM'] = data.MonthNames[this.getMonth()];
2209          var yearStr = "" + this.getFullYear();
2210          yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
2211          bits['yyyy'] = yearStr;
2212          bits['yy'] = bits['yyyy'].toString().substr(2,2);
2213          
2214          // do some funky regexs to replace the format string
2215          // with the real values
2216          var frm = new String(format);
2217          for (var sect in bits) 
2218          {
2219              var reg = new RegExp("\\b"+sect+"\\b" ,"g");
2220              frm = frm.replace(reg, bits[sect]);
2221          }
2222          return frm;
2223      },
2224  
2225      toISODate : function()
2226      {
2227          var y = this.getFullYear();
2228          var m = String(this.getMonth() + 1).zerofill(2);
2229          var d = String(this.getDate()).zerofill(2);
2230          return String(y) + String(m) + String(d);
2231      }
2232  });
2233  
2234  Object.extend(Date, 
2235  {
2236      SimpleParse: function(value, format)
2237      {    
2238          val=String(value);
2239          format=String(format);
2240          
2241          if(val.length <= 0) return null;
2242          
2243          if(format.length <= 0) return new Date(value);
2244              
2245          var isInteger = function (val) 
2246          {
2247              var digits="1234567890";
2248              for (var i=0; i < val.length; i++) 
2249              {
2250                  if (digits.indexOf(val.charAt(i))==-1) { return false; }
2251              }
2252              return true;
2253          };
2254          
2255          var getInt = function(str,i,minlength,maxlength) 
2256          {
2257              for (var x=maxlength; x>=minlength; x--) 
2258              {
2259                  var token=str.substring(i,i+x);
2260                  if (token.length < minlength) { return null; }
2261                  if (isInteger(token)) { return token; }
2262              }
2263              return null;
2264          };
2265      
2266          var i_val=0;
2267          var i_format=0;
2268          var c="";
2269          var token="";
2270          var token2="";
2271          var x,y;
2272          var now=new Date();
2273          var year=now.getFullYear();
2274          var month=now.getMonth()+1;
2275          var date=1;
2276      
2277          while (i_format < format.length) 
2278          {
2279              // Get next token from format string
2280              c=format.charAt(i_format);
2281              token="";
2282              while ((format.charAt(i_format)==c) && (i_format < format.length)) 
2283              {
2284                  token += format.charAt(i_format++);
2285              }
2286          
2287              // Extract contents of value based on format token
2288              if (token=="yyyy" || token=="yy" || token=="y") 
2289              {
2290                  if (token=="yyyy") { x=4;y=4; }
2291                  if (token=="yy")   { x=2;y=2; }
2292                  if (token=="y")    { x=2;y=4; }
2293                  year=getInt(val,i_val,x,y);
2294                  if (year==null) { return null; }
2295                  i_val += year.length;
2296                  if (year.length==2) 
2297                  {
2298                      if (year > 70) { year=1900+(year-0); }
2299                      else { year=2000+(year-0); }
2300                  }
2301              }
2302  
2303              else if (token=="MM"||token=="M") 
2304              {
2305                  month=getInt(val,i_val,token.length,2);
2306                  if(month==null||(month<1)||(month>12)){return null;}
2307                  i_val+=month.length;
2308              }
2309              else if (token=="dd"||token=="d") 
2310              {
2311                  date=getInt(val,i_val,token.length,2);
2312                  if(date==null||(date<1)||(date>31)){return null;}
2313                  i_val+=date.length;
2314              }
2315              else 
2316              {
2317                  if (val.substring(i_val,i_val+token.length)!=token) {return null;}
2318                  else {i_val+=token.length;}
2319              }
2320          }
2321      
2322          // If there are any trailing characters left in the value, it doesn't match
2323          if (i_val != val.length) { return null; }
2324          
2325          // Is date valid for month?
2326          if (month==2) 
2327          {
2328              // Check for leap year
2329              if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
2330                  if (date > 29){ return null; }
2331              }
2332              else { if (date > 28) { return null; } }
2333          }
2334      
2335          if ((month==4)||(month==6)||(month==9)||(month==11)) 
2336          {
2337              if (date > 30) { return null; }
2338          }
2339          
2340          var newdate=new Date(year,month-1,date, 0, 0, 0);
2341          return newdate;
2342      }
2343  });
2344  
2345  
2346  var Prado =
2347  {
2348      Version: '3.0.0',
2349  
2350      /**
2351       * Returns browser information. Example
2352       * <code>
2353       * var browser = Prado.Browser();
2354       * alert(browser.ie); //should ouput true if IE, false otherwise
2355       * </code>
2356       * @param ${parameter}
2357       * @return ${return}
2358       */
2359      Browser : function()
2360      {
2361          var info = { Version : "1.0" };
2362          var is_major = parseInt( navigator.appVersion );
2363          info.nver = is_major;
2364          info.ver = navigator.appVersion;
2365          info.agent = navigator.userAgent;
2366          info.dom = document.getElementById ? 1 : 0;
2367          info.opera = window.opera ? 1 : 0;
2368          info.ie5 = ( info.ver.indexOf( "MSIE 5" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
2369          info.ie6 = ( info.ver.indexOf( "MSIE 6" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
2370          info.ie4 = ( document.all && !info.dom && !info.opera ) ? 1 : 0;
2371          info.ie = info.ie4 || info.ie5 || info.ie6;
2372          info.mac = info.agent.indexOf( "Mac" ) > -1;
2373          info.ns6 = ( info.dom && parseInt( info.ver ) >= 5 ) ? 1 : 0;
2374          info.ie3 = ( info.ver.indexOf( "MSIE" ) && ( is_major < 4 ) );
2375          info.hotjava = ( info.agent.toLowerCase().indexOf( 'hotjava' ) != -1 ) ? 1 : 0;
2376          info.ns4 = ( document.layers && !info.dom && !info.hotjava ) ? 1 : 0;
2377          info.bw = ( info.ie6 || info.ie5 || info.ie4 || info.ns4 || info.ns6 || info.opera );
2378          info.ver3 = ( info.hotjava || info.ie3 );
2379          info.opera7 = ( ( info.agent.toLowerCase().indexOf( 'opera 7' ) > -1 ) || ( info.agent.toLowerCase().indexOf( 'opera/7' ) > -1 ) );
2380          info.operaOld = info.opera && !info.opera7;
2381          return info;
2382      },
2383  
2384      ImportCss : function(doc, css_file)
2385      {
2386          if (Prado.Browser().ie)
2387              var styleSheet = doc.createStyleSheet(css_file);
2388          else
2389          {
2390              var elm = doc.createElement("link");
2391  
2392              elm.rel = "stylesheet";
2393              elm.href = css_file;
2394  
2395              if (headArr = doc.getElementsByTagName("head"))
2396                  headArr[0].appendChild(elm);
2397          }
2398      }
2399  };
2400  
2401  
2402  /*Prado.Focus = Class.create();
2403  
2404  Prado.Focus.setFocus = function(id)
2405  {
2406      var target = document.getElementById ? document.getElementById(id) : document.all[id];
2407      if(target && !Prado.Focus.canFocusOn(target))
2408      {
2409          target = Prado.Focus.findTarget(target);
2410      }
2411      if(target)
2412      {
2413          try
2414          {
2415              target.focus();
2416              target.scrollIntoView(false);
2417              if (window.__smartNav)
2418              {
2419                  window.__smartNav.ae = target.id;
2420              }
2421          }
2422          catch (e)
2423          {
2424          }
2425      }
2426  }
2427  
2428  Prado.Focus.canFocusOn = function(element)
2429  {
2430      if(!element || !(element.tagName))
2431          return false;
2432      var tagName = element.tagName.toLowerCase();
2433      return !element.disabled && (!element.type || element.type.toLowerCase() != "hidden") && Prado.Focus.isFocusableTag(tagName) && Prado.Focus.isVisible(element);
2434  }
2435  
2436  Prado.Focus.isFocusableTag = function(tagName)
2437  {
2438      return (tagName == "input" || tagName == "textarea" || tagName == "select" || tagName == "button" || tagName == "a");
2439  }
2440  
2441  
2442  Prado.Focus.findTarget = function(element)
2443  {
2444      if(!element || !(element.tagName))
2445      {
2446          return null;
2447      }
2448      var tagName = element.tagName.toLowerCase();
2449      if (tagName == "undefined")
2450      {
2451          return null;
2452      }
2453      var children = element.childNodes;
2454      if (children)
2455      {
2456          for(var i=0;i<children.length;i++)
2457          {
2458              try
2459              {
2460                  if(Prado.Focus.canFocusOn(children[i]))
2461                  {
2462                      return children[i];
2463                  }
2464                  else
2465                  {
2466                      var target = Prado.Focus.findTarget(children[i]);
2467                      if(target)
2468                      {
2469                          return target;
2470                      }
2471                  }
2472              }
2473              catch (e)
2474              {
2475              }
2476          }
2477      }
2478      return null;
2479  }
2480  
2481  Prado.Focus.isVisible = function(element)
2482  {
2483      var current = element;
2484      while((typeof(current) != "undefined") && (current != null))
2485      {
2486          if(current.disabled || (typeof(current.style) != "undefined" && ((typeof(current.style.display) != "undefined" && current.style.display == "none") || (typeof(current.style.visibility) != "undefined" && current.style.visibility == "hidden") )))
2487          {
2488              return false;
2489          }
2490          if(typeof(current.parentNode) != "undefined" &&    current.parentNode != null && current.parentNode != current && current.parentNode.tagName.toLowerCase() != "body")
2491          {
2492              current = current.parentNode;
2493          }
2494          else
2495          {
2496              return true;
2497          }
2498      }
2499      return true;
2500  }
2501  */
2502  
2503  
2504  Prado.PostBack = function(event,options)
2505  {
2506      var form = $(options['FormID']);
2507      var canSubmit = true;
2508  
2509      if(options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
2510      {
2511          if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup'], $(options['ID'])))
2512              return Event.stop(event);
2513      }
2514  
2515      if(options['PostBackUrl'] && options['PostBackUrl'].length > 0)
2516          form.action = options['PostBackUrl'];
2517  
2518      if(options['TrackFocus'])
2519      {
2520          var lastFocus = $('PRADO_LASTFOCUS');
2521          if(lastFocus)
2522          {
2523              var active = document.activeElement; //where did this come from
2524              if(active)
2525                  lastFocus.value = active.id;
2526              else
2527                  lastFocus.value = options['EventTarget'];
2528          }
2529      }
2530  
2531      $('PRADO_POSTBACK_TARGET').value = options['EventTarget'];
2532      $('PRADO_POSTBACK_PARAMETER').value = options['EventParameter'];
2533      /**
2534       * Since google toolbar prevents browser default action,
2535       * we will always disable default client-side browser action
2536       */
2537      /*if(options['StopEvent']) */
2538          Event.stop(event);
2539      Event.fireEvent(form,"submit");
2540  }
2541  
2542  /*
2543  
2544  Prado.doPostBack = function(formID, eventTarget, eventParameter, performValidation, validationGroup, actionUrl, trackFocus, clientSubmit)
2545  {
2546      if (typeof(performValidation) == 'undefined')
2547      {
2548          var performValidation = false;
2549          var validationGroup = '';
2550          var actionUrl = null;
2551          var trackFocus = false;
2552          var clientSubmit = true;
2553      }
2554      var theForm = document.getElementById ? document.getElementById(formID) : document.forms[formID];
2555      var canSubmit = true;
2556      if (performValidation)
2557      {
2558          //canSubmit = Prado.Validation.validate(validationGroup);
2559      *    Prado.Validation.ActiveTarget = theForm;
2560          Prado.Validation.CurrentTargetGroup = null;
2561          Prado.Validation.IsGroupValidation = false;
2562          canSubmit = Prado.Validation.IsValid(theForm);
2563          Logger.debug(canSubmit);*
2564          canSubmit = Prado.Validation.IsValid(theForm);
2565      }
2566      if (canSubmit)
2567      {
2568          if (actionUrl != null && (actionUrl.length > 0))
2569          {
2570              theForm.action = actionUrl;
2571          }
2572          if (trackFocus)
2573          {
2574              var lastFocus = theForm.elements['PRADO_LASTFOCUS'];
2575              if ((typeof(lastFocus) != 'undefined') && (lastFocus != null))
2576              {
2577                  var active = document.activeElement;
2578                  if (typeof(active) == 'undefined')
2579                  {
2580                      lastFocus.value = eventTarget;
2581                  }
2582                  else
2583                  {
2584                      if ((active != null) && (typeof(active.id) != 'undefined'))
2585                      {
2586                          if (active.id.length > 0)
2587                          {
2588                              lastFocus.value = active.id;
2589                          }
2590                          else if (typeof(active.name) != 'undefined')
2591                          {
2592                              lastFocus.value = active.name;
2593                          }
2594                      }
2595                  }
2596              }
2597          }
2598          if (!clientSubmit)
2599          {
2600              canSubmit = false;
2601          }
2602      }
2603      if (canSubmit && (!theForm.onsubmit || theForm.onsubmit()))
2604      {
2605          theForm.PRADO_POSTBACK_TARGET.value = eventTarget;
2606          theForm.PRADO_POSTBACK_PARAMETER.value = eventParameter;
2607          theForm.submit();
2608      }
2609  }
2610  */
2611  
2612  Prado.Element = 
2613  {
2614      /**
2615       * Set the value of a particular element.
2616       * @param string element id
2617       * @param string new element value.
2618       */
2619      setValue : function(element, value)
2620      {
2621          var el = $(element);
2622          if(el && typeof(el.value) != "undefined")
2623              el.value = value;
2624      },
2625  
2626      select : function(element, method, value)
2627      {
2628          var el = $(element);
2629          var isList = element.indexOf('[]') > -1;
2630          if(!el && !isList) return;
2631          method = isList ? 'check'+method : el.tagName.toLowerCase()+method;
2632          var selection = Prado.Element.Selection;
2633          if(isFunction(selection[method])) 
2634              selection[method](isList ? element : el,value);
2635      },
2636  
2637      click : function(element)
2638      {
2639          var el = $(element);
2640          if(el) 
2641              Event.fireEvent(el,'click');
2642      },
2643      
2644      setAttribute : function(element, attribute, value)
2645      {
2646          var el = $(element);
2647          if(attribute == "disabled" && value==false)
2648              el.removeAttribute(attribute);
2649          else
2650              el.setAttribute(attribute, value);
2651      },
2652  
2653      setOptions : function(element, options)
2654      {
2655          var el = $(element);
2656          if(el && el.tagName.toLowerCase() == "select")
2657          {
2658              while(el.length > 0)
2659                  el.remove(0);
2660              for(var i = 0; i<options.length; i++)
2661                  el.options[el.options.length] = new Option(options[i][0],options[i][1]);
2662          }
2663      },
2664  
2665      /**
2666       * A delayed focus on a particular element
2667       * @param {element} element to apply focus()
2668       */
2669      focus : function(element)
2670      {
2671          var obj = $(element);
2672          if(typeof(obj) != "undefined" && typeof(obj.focus) != "undefined")
2673              setTimeout(function(){ obj.focus(); }, 100);
2674          return false;
2675      }
2676  }
2677  
2678  Prado.Element.Selection = 
2679  {
2680      inputValue : function(el, value)
2681      {
2682          switch(el.type.toLowerCase()) 
2683          {
2684              case 'checkbox':  
2685              case 'radio':
2686              return el.checked = value;
2687          }
2688      },
2689  
2690      selectValue : function(el, value)
2691      {
2692          $A(el.options).each(function(option)
2693          {
2694              option.selected = option.value == value;
2695          });
2696      },
2697  
2698      selectIndex : function(el, index)
2699      {
2700          if(el.type == 'select-one')
2701              el.selectedIndex = index;
2702          else
2703          {
2704              for(var i = 0; i<el.length; i++)
2705              {
2706                  if(i == index)
2707                      el.options[i].selected = true;
2708              }
2709          }
2710      },
2711  
2712      selectClear : function(el)
2713      {
2714          el.selectedIndex = -1;
2715      },
2716  
2717      selectAll : function(el)
2718      {
2719          $A(el.options).each(function(option)
2720          {
2721              option.selected = true;
2722              Logger.warn(option.value);
2723          });
2724      },
2725  
2726      selectInvert : function(el)
2727      {
2728          $A(el.options).each(function(option)
2729          {
2730              option.selected = !option.selected;
2731          });
2732      },
2733  
2734      checkValue : function(name, value)
2735      {
2736          $A(document.getElementsByName(name)).each(function(el)
2737          {
2738              el.checked = el.value == value
2739          });
2740      },
2741  
2742      checkIndex : function(name, index)
2743      {
2744          var elements = $A(document.getElementsByName(name));
2745          for(var i = 0; i<elements.length; i++)
2746          {
2747              if(i == index)
2748                  elements[i].checked = true;
2749          }
2750      },
2751  
2752      checkClear : function(name)
2753      {
2754          $A(document.getElementsByName(name)).each(function(el)
2755          {
2756              el.checked = false;
2757          });
2758      },
2759  
2760      checkAll : function(name)
2761      {
2762          $A(document.getElementsByName(name)).each(function(el)
2763          {
2764              el.checked = true;
2765          });
2766      },
2767      checkInvert : function(name)
2768      {
2769          $A(document.getElementsByName(name)).each(function(el)
2770          {
2771              el.checked = !el.checked;
2772          });
2773      }
2774  };
2775  
2776  Prado.WebUI = Class.create();
2777  
2778  //base postback-able controls
2779  /*Prado.WebUI.PostBackControl = Class.create();
2780  Prado.WebUI.PostBackControl.prototype =
2781  {
2782      initialize : function(options)
2783      {
2784          this.element = $(options['ID']);
2785          
2786  /*        if(options.CausesValidation && typeof(Prado.Validation) != 'undefined')
2787          {
2788              Prado.Validation.registerTarget(options);
2789          }
2790          
2791          //TODO: what do the following options do?
2792          //options['PostBackUrl']
2793          //options['ClientSubmit']
2794  
2795          if(this.onInit)
2796              this.onInit(options);
2797      }
2798  };
2799  
2800  //short cut to create postback components
2801  Prado.WebUI.createPostBackComponent = function(definition)
2802  {
2803      var component = Class.create();
2804      Object.extend(component.prototype, Prado.WebUI.PostBackControl.prototype);
2805      if(definition) Object.extend(component.prototype, definition);
2806      return component;
2807  }
2808  
2809  Prado.WebUI.TButton = Prado.WebUI.createPostBackComponent();
2810  */
2811  Prado.WebUI.PostBackControl = Class.create();
2812  
2813  Prado.WebUI.PostBackControl.prototype = 
2814  {
2815      _elementOnClick : null, //capture the element's onclick function
2816  
2817      initialize : function(options)
2818      {
2819          this.element = $(options.ID);
2820          if(this.onInit)
2821              this.onInit(options);
2822      },
2823      
2824      onInit : function(options)
2825      {
2826          if(typeof(this.element.onclick)=="function")
2827          {
2828              this._elementOnClick = this.element.onclick;
2829              this.element.onclick = null;
2830          }
2831          Event.observe(this.element, "click", this.onClick.bindEvent(this,options));        
2832      },
2833  
2834      onClick : function(event, options)
2835      {
2836          var src = Event.element(event);
2837          var doPostBack = true;
2838          var onclicked = null;
2839  
2840          if(this._elementOnClick)
2841          {
2842              var onclicked = this._elementOnClick(event);
2843              if(typeof(onclicked) == "boolean")
2844                  doPostBack = onclicked;
2845          }
2846          if(doPostBack)
2847              this.onPostBack(event,options);
2848          if(typeof(onclicked) == "boolean" && !onclicked)
2849              Event.stop(event);
2850      },
2851  
2852      onPostBack : function(event, options)
2853      {
2854          Prado.PostBack(event,options);
2855      }
2856  };
2857  
2858  Prado.WebUI.TButton = Class.extend(Prado.WebUI.PostBackControl);
2859  Prado.WebUI.TLinkButton = Class.extend(Prado.WebUI.PostBackControl);
2860  Prado.WebUI.TCheckBox = Class.extend(Prado.WebUI.PostBackControl);
2861  Prado.WebUI.TBulletedList = Class.extend(Prado.WebUI.PostBackControl);
2862  Prado.WebUI.TImageMap = Class.extend(Prado.WebUI.PostBackControl);
2863  
2864  /**
2865   * TImageButton client-side behaviour. With validation, Firefox needs 
2866   * to capture the x,y point of the clicked image in hidden form fields.
2867   */
2868  Prado.WebUI.TImageButton = Class.extend(Prado.WebUI.PostBackControl);
2869  Object.extend(Prado.WebUI.TImageButton.prototype,
2870  {
2871      /**
2872       * Only add the hidden inputs once.
2873       */
2874      hasXYInput : false,
2875      
2876      /**
2877       * Override parent onPostBack function, tried to add hidden forms
2878       * inputs to capture x,y clicked point.
2879       */
2880      onPostBack : function(event, options)
2881      {
2882          if(!this.hasXYInput)
2883          {
2884              this.addXYInput(event,options);
2885              this.hasXYInput = true;
2886          }
2887          Prado.PostBack(event, options);
2888      },
2889      
2890      /**
2891       * Add hidden inputs to capture the x,y point clicked on the image.
2892       * @param event DOM click event.
2893       * @param array image button options.
2894       */
2895      addXYInput : function(event,options)
2896      {
2897          var imagePos = Position.cumulativeOffset(this.element);
2898          var clickedPos = [event.clientX, event.clientY];
2899          var x = clickedPos[0]-imagePos[0]+1;
2900          var y = clickedPos[1]-imagePos[1]+1;
2901          var id = options['EventTarget'];
2902          var x_input = INPUT({type:'hidden',name:id+'_x',value:x});
2903          var y_input = INPUT({type:'hidden',name:id+'_y',value:y});
2904          this.element.parentNode.appendChild(x_input);
2905          this.element.parentNode.appendChild(y_input);        
2906      }
2907  });
2908  
2909  
2910  /**
2911   * Radio button, only initialize if not already checked.
2912   */
2913  Prado.WebUI.TRadioButton = Class.extend(Prado.WebUI.PostBackControl);
2914  Prado.WebUI.TRadioButton.prototype.onRadioButtonInitialize = Prado.WebUI.TRadioButton.prototype.initialize;
2915  Object.extend(Prado.WebUI.TRadioButton.prototype,
2916  {
2917      initialize : function(options)
2918      {
2919          this.element = $(options['ID']);
2920          if(!this.element.checked)
2921              this.onRadioButtonInitialize(options);
2922      }
2923  });
2924  
2925  
2926  Prado.WebUI.TTextBox = Class.extend(Prado.WebUI.PostBackControl,
2927  {
2928      onInit : function(options)
2929      {
2930          if(options['TextMode'] != 'MultiLine')
2931              Event.observe(this.element, "keydown", this.handleReturnKey.bind(this));
2932          Event.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
2933      },
2934  
2935      handleReturnKey : function(e)
2936      {
2937           if(Event.keyCode(e) == Event.KEY_RETURN)
2938          {
2939              var target = Event.element(e);
2940              if(target)
2941              {
2942                  Event.fireEvent(target, "change");
2943                  Event.stop(e);
2944              }
2945          }
2946      }
2947  });
2948  
2949  Prado.WebUI.TListControl = Class.extend(Prado.WebUI.PostBackControl,
2950  {
2951      onInit : function(options)
2952      {
2953          Event.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
2954      }
2955  });
2956  
2957  Prado.WebUI.TListBox = Class.extend(Prado.WebUI.TListControl);
2958  Prado.WebUI.TDropDownList = Class.extend(Prado.WebUI.TListControl);
2959  
2960  Prado.WebUI.DefaultButton = Class.create();
2961  Prado.WebUI.DefaultButton.prototype = 
2962  {
2963      initialize : function(options)
2964      {
2965          this.options = options;
2966          this._event = this.triggerEvent.bindEvent(this);
2967          Event.observe(options['Panel'], 'keydown', this._event);
2968      },
2969  
2970      triggerEvent : function(ev, target)
2971      {
2972          var enterPressed = Event.keyCode(ev) == Event.KEY_RETURN;
2973          var isTextArea = Event.element(ev).tagName.toLowerCase() == "textarea";
2974          if(enterPressed && !isTextArea)
2975          {
2976              var defaultButton = $(this.options['Target']);
2977              if(defaultButton)
2978              {
2979                  this.triggered = true;
2980                  $('PRADO_POSTBACK_TARGET').value = this.options.EventTarget;                
2981                  Event.fireEvent(defaultButton, this.options['Event']);
2982                  Event.stop(ev);
2983              }
2984          }
2985      }
2986  };
2987  
2988  Prado.WebUI.TTextHighlighter=Class.create();
2989  Prado.WebUI.TTextHighlighter.prototype=
2990  {
2991      initialize:function(id)
2992      {
2993          if(!window.clipboardData) return;
2994          var options =
2995          {
2996              href : 'javascript:;/'+'/copy code to clipboard',
2997              onclick : 'Prado.WebUI.TTextHighlighter.copy(this)',
2998              onmouseover : 'Prado.WebUI.TTextHighlighter.hover(this)',
2999              onmouseout : 'Prado.WebUI.TTextHighlighter.out(this)'
3000          }
3001          var div = DIV({className:'copycode'}, A(options, 'Copy Code'));
3002          document.write(DIV(null,div).innerHTML);
3003      }
3004  };
3005  
3006  Object.extend(Prado.WebUI.TTextHighlighter,
3007  {
3008      copy : function(obj)
3009      {
3010          var parent = obj.parentNode.parentNode.parentNode;
3011          var text = '';
3012          for(var i = 0; i < parent.childNodes.length; i++)
3013          {
3014              var node = parent.childNodes[i];
3015              if(node.innerText)
3016                  text += node.innerText == 'Copy Code' ? '' : node.innerText;
3017              else
3018                  text += node.nodeValue;
3019          }
3020          if(text.length > 0)
3021              window.clipboardData.setData("Text", text);
3022      },
3023  
3024      hover : function(obj)
3025      {
3026          obj.parentNode.className = "copycode copycode_hover";
3027      },
3028  
3029      out : function(obj)
3030      {
3031          obj.parentNode.className = "copycode";
3032      }
3033  });
3034  
3035  
3036  Prado.WebUI.TRatingList = Class.create();    
3037  Prado.WebUI.TRatingList.prototype = 
3038  {
3039      selectedIndex : -1,
3040  
3041      initialize : function(options)
3042      {
3043          this.options = options;
3044          this.element = $(options['ID']);
3045          Element.addClassName(this.element,options.cssClass);
3046          this.radios = document.getElementsByName(options.field);
3047          for(var i = 0; i<this.radios.length; i++)
3048          {
3049              Event.observe(this.radios[i].parentNode, "mouseover", this.hover.bindEvent(this,i));
3050              Event.observe(this.radios[i].parentNode, "mouseout", this.recover.bindEvent(this,i));
3051              Event.observe(this.radios[i].parentNode, "click", this.click.bindEvent(this, i));
3052          }        
3053          this.caption = CAPTION();
3054          this.element.appendChild(this.caption);
3055          this.selectedIndex = options.selectedIndex;
3056          this.setRating(this.selectedIndex);
3057      },
3058      
3059      hover : function(ev,index)
3060      {
3061          for(var i = 0; i<this.radios.length; i++)
3062              this.radios[i].parentNode.className = (i<=index) ? "rating_hover" : "";
3063          this.setCaption(index);
3064      },
3065      
3066      recover : function(ev,index)
3067      {
3068          for(var i = 0; i<=index; i++)
3069              Element.removeClassName(this.radios[i].parentNode, "rating_hover");
3070          this.setRating(this.selectedIndex);
3071      },
3072      
3073      click : function(ev, index)
3074      {
3075          for(var i = 0; i<this.radios.length; i++)
3076              this.radios[i].checked = (i == index);
3077          this.selectedIndex = index;
3078          this.setRating(index);
3079          if(isFunction(this.options.onChange))
3080              this.options.onChange(this,index);        
3081      },
3082      
3083      setRating: function(index)
3084      {
3085          for(var i = 0; i<=index; i++)
3086              this.radios[i].parentNode.className = "rating_selected";
3087          this.setCaption(index);
3088      },
3089      
3090      setCaption : function(index)
3091      {
3092          this.caption.innerHTML = index > -1 ? 
3093              this.radios[index].value : this.options.caption;    
3094      }
3095  }
3096  


Généré le : Sun Feb 25 21:07:04 2007 par Balluche grâce à PHPXref 0.7